@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Give the Phortune external portal an order view

Summary:
Depends on D20739. Ref T13366. Slightly modularize/update components of order views, and make orders viewable from either an account context (existing view) or an external context (new view).

The new view is generally simpler so this mostly just reorganizes existing code.

Test Plan: Viewed orders as an account owner and an external user.

Maniphest Tasks: T13366

Differential Revision: https://secure.phabricator.com/D20740

+662 -462
+8 -2
src/__phutil_library_map__.php
··· 5302 5302 'PhortuneExternalOrderController' => 'applications/phortune/controller/external/PhortuneExternalOrderController.php', 5303 5303 'PhortuneExternalOverviewController' => 'applications/phortune/controller/external/PhortuneExternalOverviewController.php', 5304 5304 'PhortuneExternalUnsubscribeController' => 'applications/phortune/controller/external/PhortuneExternalUnsubscribeController.php', 5305 - 'PhortuneInvoiceView' => 'applications/phortune/view/PhortuneInvoiceView.php', 5306 5305 'PhortuneLandingController' => 'applications/phortune/controller/PhortuneLandingController.php', 5307 5306 'PhortuneMemberHasAccountEdgeType' => 'applications/phortune/edge/PhortuneMemberHasAccountEdgeType.php', 5308 5307 'PhortuneMemberHasMerchantEdgeType' => 'applications/phortune/edge/PhortuneMemberHasMerchantEdgeType.php', ··· 5343 5342 'PhortuneMerchantTransactionQuery' => 'applications/phortune/query/PhortuneMerchantTransactionQuery.php', 5344 5343 'PhortuneMerchantTransactionType' => 'applications/phortune/xaction/PhortuneMerchantTransactionType.php', 5345 5344 'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php', 5345 + 'PhortuneOrderDescriptionView' => 'applications/phortune/view/PhortuneOrderDescriptionView.php', 5346 + 'PhortuneOrderItemsView' => 'applications/phortune/view/PhortuneOrderItemsView.php', 5347 + 'PhortuneOrderSummaryView' => 'applications/phortune/view/PhortuneOrderSummaryView.php', 5346 5348 'PhortuneOrderTableView' => 'applications/phortune/view/PhortuneOrderTableView.php', 5349 + 'PhortuneOrderView' => 'applications/phortune/view/PhortuneOrderView.php', 5347 5350 'PhortunePayPalPaymentProvider' => 'applications/phortune/provider/PhortunePayPalPaymentProvider.php', 5348 5351 'PhortunePaymentMethod' => 'applications/phortune/storage/PhortunePaymentMethod.php', 5349 5352 'PhortunePaymentMethodCreateController' => 'applications/phortune/controller/paymentmethod/PhortunePaymentMethodCreateController.php', ··· 11895 11898 'PhortuneExternalOrderController' => 'PhortuneExternalController', 11896 11899 'PhortuneExternalOverviewController' => 'PhortuneExternalController', 11897 11900 'PhortuneExternalUnsubscribeController' => 'PhortuneExternalController', 11898 - 'PhortuneInvoiceView' => 'AphrontTagView', 11899 11901 'PhortuneLandingController' => 'PhortuneController', 11900 11902 'PhortuneMemberHasAccountEdgeType' => 'PhabricatorEdgeType', 11901 11903 'PhortuneMemberHasMerchantEdgeType' => 'PhabricatorEdgeType', ··· 11940 11942 'PhortuneMerchantTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 11941 11943 'PhortuneMerchantTransactionType' => 'PhabricatorModularTransactionType', 11942 11944 'PhortuneMonthYearExpiryControl' => 'AphrontFormControl', 11945 + 'PhortuneOrderDescriptionView' => 'AphrontView', 11946 + 'PhortuneOrderItemsView' => 'PhortuneOrderView', 11947 + 'PhortuneOrderSummaryView' => 'PhortuneOrderView', 11943 11948 'PhortuneOrderTableView' => 'AphrontView', 11949 + 'PhortuneOrderView' => 'AphrontView', 11944 11950 'PhortunePayPalPaymentProvider' => 'PhortunePaymentProvider', 11945 11951 'PhortunePaymentMethod' => array( 11946 11952 'PhortuneDAO',
+12 -1
src/applications/base/controller/PhabricatorController.php
··· 481 481 482 482 protected function buildTransactionTimeline( 483 483 PhabricatorApplicationTransactionInterface $object, 484 - PhabricatorApplicationTransactionQuery $query, 484 + PhabricatorApplicationTransactionQuery $query = null, 485 485 PhabricatorMarkupEngine $engine = null, 486 486 $view_data = array()) { 487 487 488 488 $request = $this->getRequest(); 489 489 $viewer = $this->getViewer(); 490 490 $xaction = $object->getApplicationTransactionTemplate(); 491 + 492 + if (!$query) { 493 + $query = PhabricatorApplicationTransactionQuery::newQueryForObject( 494 + $object); 495 + if (!$query) { 496 + throw new Exception( 497 + pht( 498 + 'Unable to find transaction query for object of class "%s".', 499 + get_class($object))); 500 + } 501 + } 491 502 492 503 $pager = id(new AphrontCursorPagerView()) 493 504 ->readFromRequest($request)
+4 -1
src/applications/phortune/application/PhabricatorPhortuneApplication.php
··· 113 113 '' => 'PhortuneExternalOverviewController', 114 114 'unsubscribe/' => 'PhortuneExternalUnsubscribeController', 115 115 'order/' => array( 116 - '(?P<orderID>[^/]+)/' => 'PhortuneExternalOrderController', 116 + '(?P<orderID>[^/]+)/' => array( 117 + '' => 'PhortuneExternalOrderController', 118 + '(?P<action>print)/' => 'PhortuneExternalOrderController', 119 + ), 117 120 ), 118 121 ), 119 122 'merchant/' => array(
+9 -6
src/applications/phortune/controller/cart/PhortuneCartCheckoutController.php
··· 207 207 ->appendChild($form) 208 208 ->appendChild($provider_form); 209 209 210 - $description_box = $this->renderCartDescription($cart); 210 + $description_view = id(new PhortuneOrderDescriptionView()) 211 + ->setViewer($viewer) 212 + ->setOrder($cart); 211 213 212 214 $crumbs = $this->buildApplicationCrumbs(); 213 215 $crumbs->addTextCrumb(pht('Checkout')); ··· 220 222 221 223 $view = id(new PHUITwoColumnView()) 222 224 ->setHeader($header) 223 - ->setFooter(array( 224 - $cart_box, 225 - $description_box, 226 - $payment_box, 227 - )); 225 + ->setFooter( 226 + array( 227 + $description_view, 228 + $cart_box, 229 + $payment_box, 230 + )); 228 231 229 232 return $this->newPage() 230 233 ->setTitle($title)
-57
src/applications/phortune/controller/cart/PhortuneCartController.php
··· 74 74 PhabricatorPolicyCapability::CAN_EDIT); 75 75 } 76 76 77 - protected function buildCartContentTable(PhortuneCart $cart) { 78 - 79 - $rows = array(); 80 - foreach ($cart->getPurchases() as $purchase) { 81 - $rows[] = array( 82 - $purchase->getFullDisplayName(), 83 - $purchase->getBasePriceAsCurrency()->formatForDisplay(), 84 - $purchase->getQuantity(), 85 - $purchase->getTotalPriceAsCurrency()->formatForDisplay(), 86 - ); 87 - } 88 - 89 - $rows[] = array( 90 - phutil_tag('strong', array(), pht('Total')), 91 - '', 92 - '', 93 - phutil_tag('strong', array(), 94 - $cart->getTotalPriceAsCurrency()->formatForDisplay()), 95 - ); 96 - 97 - $table = new AphrontTableView($rows); 98 - $table->setHeaders( 99 - array( 100 - pht('Item'), 101 - pht('Price'), 102 - pht('Qty.'), 103 - pht('Total'), 104 - )); 105 - $table->setColumnClasses( 106 - array( 107 - 'wide', 108 - 'right', 109 - 'right', 110 - 'right', 111 - )); 112 - 113 - return $table; 114 - } 115 - 116 - protected function renderCartDescription(PhortuneCart $cart) { 117 - $description = $cart->getDescription(); 118 - if (!strlen($description)) { 119 - return null; 120 - } 121 - 122 - $output = new PHUIRemarkupView($this->getViewer(), $description); 123 - 124 - $box = id(new PHUIBoxView()) 125 - ->addMargin(PHUI::MARGIN_LARGE) 126 - ->appendChild($output); 127 - 128 - return id(new PHUIObjectBoxView()) 129 - ->setHeaderText(pht('Description')) 130 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 131 - ->appendChild($box); 132 - } 133 - 134 77 }
+64 -221
src/applications/phortune/controller/cart/PhortuneCartViewController.php
··· 3 3 final class PhortuneCartViewController 4 4 extends PhortuneCartController { 5 5 6 - private $action = null; 7 - 8 6 protected function shouldRequireAccountAuthority() { 9 7 return false; 10 8 } ··· 15 13 16 14 protected function handleCartRequest(AphrontRequest $request) { 17 15 $viewer = $request->getViewer(); 18 - $cart = $this->getCart(); 16 + $order = $this->getCart(); 19 17 $authority = $this->getMerchantAuthority(); 20 18 $can_edit = $this->hasAccountAuthority(); 21 19 22 - $this->action = $request->getURIData('action'); 20 + $is_printable = ($request->getURIData('action') === 'print'); 23 21 24 - $cart_table = $this->buildCartContentTable($cart); 25 - 26 - $errors = array(); 27 - $error_view = null; 28 22 $resume_uri = null; 29 - switch ($cart->getStatus()) { 30 - case PhortuneCart::STATUS_READY: 31 - if ($cart->getIsInvoice()) { 32 - $error_view = id(new PHUIInfoView()) 33 - ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) 34 - ->appendChild(pht('This invoice is ready for payment.')); 35 - } 36 - break; 37 - case PhortuneCart::STATUS_PURCHASING: 38 - if ($can_edit) { 39 - $resume_uri = $cart->getMetadataValue('provider.checkoutURI'); 40 - if ($resume_uri) { 41 - $errors[] = pht( 42 - 'The checkout process has been started, but not yet completed. '. 43 - 'You can continue checking out by clicking %s, or cancel the '. 44 - 'order, or contact the merchant for assistance.', 45 - phutil_tag('strong', array(), pht('Continue Checkout'))); 46 - } else { 47 - $errors[] = pht( 48 - 'The checkout process has been started, but an error occurred. '. 49 - 'You can cancel the order or contact the merchant for '. 50 - 'assistance.'); 51 - } 52 - } 53 - break; 54 - case PhortuneCart::STATUS_CHARGED: 55 - if ($can_edit) { 56 - $errors[] = pht( 57 - 'You have been charged, but processing could not be completed. '. 58 - 'You can cancel your order, or contact the merchant for '. 59 - 'assistance.'); 60 - } 61 - break; 62 - case PhortuneCart::STATUS_HOLD: 63 - if ($can_edit) { 64 - $errors[] = pht( 65 - 'Payment for this order is on hold. You can click %s to check '. 66 - 'for updates, cancel the order, or contact the merchant for '. 67 - 'assistance.', 68 - phutil_tag('strong', array(), pht('Update Status'))); 69 - } 70 - break; 71 - case PhortuneCart::STATUS_REVIEW: 72 - if ($authority) { 73 - $errors[] = pht( 74 - 'This order has been flagged for manual review. Review the order '. 75 - 'and choose %s to accept it or %s to reject it.', 76 - phutil_tag('strong', array(), pht('Accept Order')), 77 - phutil_tag('strong', array(), pht('Refund Order'))); 78 - } else if ($can_edit) { 79 - $errors[] = pht( 80 - 'This order requires manual processing and will complete once '. 81 - 'the merchant accepts it.'); 82 - } 83 - break; 84 - case PhortuneCart::STATUS_PURCHASED: 85 - $error_view = id(new PHUIInfoView()) 86 - ->setSeverity(PHUIInfoView::SEVERITY_SUCCESS) 87 - ->appendChild(pht('This purchase has been completed.')); 88 - break; 23 + if ($order->getStatus() === PhortuneCart::STATUS_PURCHASING) { 24 + if ($can_edit) { 25 + $resume_uri = $order->getMetadataValue('provider.checkoutURI'); 26 + } 89 27 } 90 28 91 - if ($errors) { 92 - $error_view = id(new PHUIInfoView()) 93 - ->setSeverity(PHUIInfoView::SEVERITY_WARNING) 94 - ->appendChild($errors); 95 - } 96 - 97 - $details = $this->buildDetailsView($cart); 98 - $curtain = $this->buildCurtainView( 99 - $cart, 100 - $can_edit, 101 - $authority, 102 - $resume_uri); 103 - 104 29 $header = id(new PHUIHeaderView()) 105 30 ->setUser($viewer) 106 - ->setHeader($cart->getName()) 31 + ->setHeader($order->getName()) 107 32 ->setHeaderIcon('fa-shopping-bag'); 108 33 109 - if ($cart->getStatus() == PhortuneCart::STATUS_PURCHASED) { 110 - $done_uri = $cart->getDoneURI(); 34 + if ($order->getStatus() == PhortuneCart::STATUS_PURCHASED) { 35 + $done_uri = $order->getDoneURI(); 111 36 if ($done_uri) { 112 37 $header->addActionLink( 113 38 id(new PHUIButtonView()) 114 39 ->setTag('a') 115 40 ->setHref($done_uri) 116 41 ->setIcon('fa-check-square green') 117 - ->setText($cart->getDoneActionName())); 42 + ->setText($order->getDoneActionName())); 118 43 } 119 44 } 120 45 121 - $cart_box = id(new PHUIObjectBoxView()) 122 - ->setHeaderText(pht('Cart Items')) 123 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 124 - ->setTable($cart_table); 125 - 126 - $description = $this->renderCartDescription($cart); 127 - 128 - $charges = id(new PhortuneChargeQuery()) 46 + $order_view = id(new PhortuneOrderSummaryView()) 129 47 ->setViewer($viewer) 130 - ->withCartPHIDs(array($cart->getPHID())) 131 - ->needCarts(true) 132 - ->execute(); 48 + ->setOrder($order) 49 + ->setResumeURI($resume_uri) 50 + ->setPrintable($is_printable); 133 51 134 - $charges_table = id(new PhortuneChargeTableView()) 135 - ->setUser($viewer) 136 - ->setCharges($charges) 137 - ->setShowOrder(false); 52 + $crumbs = null; 53 + $curtain = null; 138 54 139 - $charges = id(new PHUIObjectBoxView()) 140 - ->setHeaderText(pht('Charges')) 141 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 142 - ->setTable($charges_table); 55 + $main = array(); 56 + $tail = array(); 143 57 144 - $account = $cart->getAccount(); 58 + require_celerity_resource('phortune-invoice-css'); 145 59 146 - $crumbs = $this->buildApplicationCrumbs() 147 - ->addTextCrumb($account->getName(), $account->getURI()) 148 - ->addTextCrumb(pht('Orders'), $account->getOrdersURI()) 149 - ->addTextCrumb(pht('Cart %d', $cart->getID())) 150 - ->setBorder(true); 60 + if ($is_printable) { 61 + $body_class = 'phortune-invoice-view'; 151 62 152 - require_celerity_resource('phortune-css'); 63 + $tail[] = $order_view; 64 + } else { 65 + $body_class = 'phortune-cart-page'; 153 66 154 - if (!$this->action) { 155 - $class = 'phortune-cart-page'; 156 - $timeline = $this->buildTransactionTimeline( 157 - $cart, 158 - new PhortuneCartTransactionQuery()); 159 - $timeline 160 - ->setShouldTerminate(true); 67 + $curtain = $this->buildCurtainView( 68 + $order, 69 + $can_edit, 70 + $authority, 71 + $resume_uri); 161 72 162 - $view = id(new PHUITwoColumnView()) 163 - ->setHeader($header) 164 - ->setCurtain($curtain) 165 - ->setMainColumn(array( 166 - $error_view, 167 - $details, 168 - $cart_box, 169 - $description, 170 - $charges, 171 - $timeline, 172 - )); 73 + $account = $order->getAccount(); 74 + $crumbs = $this->buildApplicationCrumbs() 75 + ->addTextCrumb($account->getName(), $account->getURI()) 76 + ->addTextCrumb(pht('Orders'), $account->getOrdersURI()) 77 + ->addTextCrumb($order->getObjectName()) 78 + ->setBorder(true); 173 79 174 - } else { 175 - $class = 'phortune-invoice-view'; 176 - $crumbs = null; 177 - $merchant_phid = $cart->getMerchantPHID(); 178 - $buyer_phid = $cart->getAuthorPHID(); 179 - $merchant = id(new PhortuneMerchantQuery()) 180 - ->setViewer($viewer) 181 - ->withPHIDs(array($merchant_phid)) 182 - ->needProfileImage(true) 183 - ->executeOne(); 184 - $buyer = id(new PhabricatorPeopleQuery()) 185 - ->setViewer($viewer) 186 - ->withPHIDs(array($buyer_phid)) 187 - ->needProfileImage(true) 188 - ->executeOne(); 80 + $timeline = $this->buildTransactionTimeline($order) 81 + ->setShouldTerminate(true); 189 82 190 - $merchant_contact = new PHUIRemarkupView( 191 - $viewer, 192 - $merchant->getContactInfo()); 83 + $main[] = $order_view; 84 + $main[] = $timeline; 85 + } 193 86 194 - $account_name = $account->getBillingName(); 195 - if (!strlen($account_name)) { 196 - $account_name = $buyer->getRealName(); 197 - } 87 + $column_view = id(new PHUITwoColumnView()) 88 + ->setMainColumn($main) 89 + ->setFooter($tail); 198 90 199 - $account_contact = $account->getBillingAddress(); 200 - if (strlen($account_contact)) { 201 - $account_contact = new PHUIRemarkupView( 202 - $viewer, 203 - $account_contact); 204 - } 205 - 206 - $view = id(new PhortuneInvoiceView()) 207 - ->setMerchantName($merchant->getName()) 208 - ->setMerchantLogo($merchant->getProfileImageURI()) 209 - ->setMerchantContact($merchant_contact) 210 - ->setMerchantFooter($merchant->getInvoiceFooter()) 211 - ->setAccountName($account_name) 212 - ->setAccountContact($account_contact) 213 - ->setStatus($error_view) 214 - ->setContent( 215 - array( 216 - $details, 217 - $cart_box, 218 - $charges, 219 - )); 91 + if ($curtain) { 92 + $column_view->setCurtain($curtain); 220 93 } 221 94 222 95 $page = $this->newPage() 223 - ->setTitle(pht('Cart %d', $cart->getID())) 224 - ->addClass($class) 225 - ->appendChild($view); 96 + ->addClass($body_class) 97 + ->setTitle( 98 + array( 99 + $order->getObjectName(), 100 + $order->getName(), 101 + )) 102 + ->appendChild($column_view); 226 103 227 104 if ($crumbs) { 228 105 $page->setCrumbs($crumbs); ··· 231 108 return $page; 232 109 } 233 110 234 - private function buildDetailsView(PhortuneCart $cart) { 235 - $viewer = $this->getViewer(); 236 - $view = id(new PHUIPropertyListView()) 237 - ->setUser($viewer) 238 - ->setObject($cart); 239 - 240 - $handles = $this->loadViewerHandles( 241 - array( 242 - $cart->getAccountPHID(), 243 - $cart->getAuthorPHID(), 244 - $cart->getMerchantPHID(), 245 - )); 246 - 247 - if ($this->action == 'print') { 248 - $view->addProperty(pht('Order Name'), $cart->getName()); 249 - } 250 - 251 - $view->addProperty( 252 - pht('Account'), 253 - $handles[$cart->getAccountPHID()]->renderLink()); 254 - $view->addProperty( 255 - pht('Authorized By'), 256 - $handles[$cart->getAuthorPHID()]->renderLink()); 257 - $view->addProperty( 258 - pht('Merchant'), 259 - $handles[$cart->getMerchantPHID()]->renderLink()); 260 - $view->addProperty( 261 - pht('Status'), 262 - PhortuneCart::getNameForStatus($cart->getStatus())); 263 - $view->addProperty( 264 - pht('Updated'), 265 - phabricator_datetime($cart->getDateModified(), $viewer)); 266 - 267 - return id(new PHUIObjectBoxView()) 268 - ->setHeaderText(pht('Details')) 269 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 270 - ->appendChild($view); 271 - } 272 - 273 111 private function buildCurtainView( 274 112 PhortuneCart $cart, 275 113 $can_edit, ··· 297 135 $checkout_uri = $cart->getCheckoutURI(); 298 136 $void_uri = $this->getApplicationURI("cart/{$id}/void/"); 299 137 138 + 139 + $curtain->addAction( 140 + id(new PhabricatorActionView()) 141 + ->setName(pht('Printable Version')) 142 + ->setHref($print_uri) 143 + ->setOpenInNewWindow(true) 144 + ->setIcon('fa-print')); 145 + 146 + $curtain->addAction( 147 + id(new PhabricatorActionView()) 148 + ->setType(PhabricatorActionView::TYPE_DIVIDER)); 149 + 300 150 $curtain->addAction( 301 151 id(new PhabricatorActionView()) 302 152 ->setName(pht('Pay Now')) ··· 326 176 ->setIcon('fa-shopping-bag') 327 177 ->setHref($resume_uri)); 328 178 } 329 - 330 - $curtain->addAction( 331 - id(new PhabricatorActionView()) 332 - ->setName(pht('Printable Version')) 333 - ->setHref($print_uri) 334 - ->setOpenInNewWindow(true) 335 - ->setIcon('fa-print')); 336 179 337 180 if ($authority) { 338 181 $curtain->addAction(
+73 -15
src/applications/phortune/controller/external/PhortuneExternalOrderController.php
··· 17 17 return new Aphront404Response(); 18 18 } 19 19 20 - $timeline = $this->buildTransactionTimeline( 21 - $order, 22 - new PhortuneCartTransactionQuery()); 23 - $timeline->setShouldTerminate(true); 20 + $is_printable = ($request->getURIData('action') === 'print'); 24 21 25 - $crumbs = $this->newExternalCrumbs() 26 - ->addTextCrumb($order->getObjectName()); 22 + $order_view = id(new PhortuneOrderSummaryView()) 23 + ->setViewer($xviewer) 24 + ->setOrder($order) 25 + ->setPrintable($is_printable); 27 26 28 - $view = id(new PHUITwoColumnView()) 29 - ->setMainColumn( 27 + $crumbs = null; 28 + $curtain = null; 29 + 30 + $main = array(); 31 + $tail = array(); 32 + 33 + require_celerity_resource('phortune-invoice-css'); 34 + 35 + if ($is_printable) { 36 + $body_class = 'phortune-invoice-view'; 37 + 38 + $tail[] = $order_view; 39 + } else { 40 + $body_class = 'phortune-cart-page'; 41 + 42 + $curtain = $this->newCurtain($order); 43 + 44 + $crumbs = $this->newExternalCrumbs() 45 + ->addTextCrumb($order->getObjectName()) 46 + ->setBorder(true); 47 + 48 + $timeline = $this->buildTransactionTimeline($order) 49 + ->setShouldTerminate(true); 50 + 51 + $main[] = $order_view; 52 + $main[] = $timeline; 53 + } 54 + 55 + $column_view = id(new PHUITwoColumnView()) 56 + ->setMainColumn($main) 57 + ->setFooter($tail); 58 + 59 + if ($curtain) { 60 + $column_view->setCurtain($curtain); 61 + } 62 + 63 + $page = $this->newPage() 64 + ->addClass($body_class) 65 + ->setTitle( 30 66 array( 31 - $timeline, 32 - )); 67 + $order->getObjectName(), 68 + $order->getName(), 69 + )) 70 + ->appendChild($column_view); 33 71 34 - return $this->newPage() 35 - ->setTitle(pht('Order %d', $order->getID())) 36 - ->setCrumbs($crumbs) 37 - ->appendChild($view); 38 - } 72 + if ($crumbs) { 73 + $page->setCrumbs($crumbs); 74 + } 75 + 76 + return $page; 77 + } 78 + 79 + 80 + private function newCurtain(PhortuneCart $order) { 81 + $xviewer = $this->getExternalViewer(); 82 + $email = $this->getAccountEmail(); 83 + 84 + $curtain = $this->newCurtainView($order); 85 + 86 + $print_uri = $email->getExternalOrderPrintURI($order); 87 + 88 + $curtain->addAction( 89 + id(new PhabricatorActionView()) 90 + ->setName(pht('Printable Version')) 91 + ->setHref($print_uri) 92 + ->setOpenInNewWindow(true) 93 + ->setIcon('fa-print')); 94 + 95 + return $curtain; 96 + } 39 97 40 98 }
+8
src/applications/phortune/storage/PhortuneAccountEmail.php
··· 100 100 $cart->getID()); 101 101 } 102 102 103 + public function getExternalOrderPrintURI(PhortuneCart $cart) { 104 + return urisprintf( 105 + '/phortune/external/%s/%s/order/%d/print/', 106 + $this->getAddressKey(), 107 + $this->getAccessKey(), 108 + $cart->getID()); 109 + } 110 + 103 111 104 112 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 105 113
-159
src/applications/phortune/view/PhortuneInvoiceView.php
··· 1 - <?php 2 - 3 - final class PhortuneInvoiceView extends AphrontTagView { 4 - 5 - private $merchantName; 6 - private $merchantLogo; 7 - private $merchantContact; 8 - private $merchantFooter; 9 - private $accountName; 10 - private $accountContact; 11 - private $status; 12 - private $content; 13 - 14 - public function setMerchantName($name) { 15 - $this->merchantName = $name; 16 - return $this; 17 - } 18 - 19 - public function setMerchantLogo($logo) { 20 - $this->merchantLogo = $logo; 21 - return $this; 22 - } 23 - 24 - public function setMerchantContact($contact) { 25 - $this->merchantContact = $contact; 26 - return $this; 27 - } 28 - 29 - public function setMerchantFooter($footer) { 30 - $this->merchantFooter = $footer; 31 - return $this; 32 - } 33 - 34 - public function setAccountName($name) { 35 - $this->accountName = $name; 36 - return $this; 37 - } 38 - 39 - public function setAccountContact($contact) { 40 - $this->accountContact = $contact; 41 - return $this; 42 - } 43 - 44 - public function setStatus($status) { 45 - $this->status = $status; 46 - return $this; 47 - } 48 - 49 - public function setContent($content) { 50 - $this->content = $content; 51 - return $this; 52 - } 53 - 54 - protected function getTagAttributes() { 55 - $classes = array(); 56 - $classes[] = 'phortune-invoice-view'; 57 - 58 - return array( 59 - 'class' => implode(' ', $classes), 60 - ); 61 - } 62 - 63 - protected function getTagContent() { 64 - require_celerity_resource('phortune-invoice-css'); 65 - 66 - $logo = phutil_tag( 67 - 'div', 68 - array( 69 - 'class' => 'phortune-invoice-logo', 70 - ), 71 - phutil_tag( 72 - 'img', 73 - array( 74 - 'height' => '50', 75 - 'width' => '50', 76 - 'alt' => $this->merchantName, 77 - 'src' => $this->merchantLogo, 78 - ))); 79 - 80 - $to_title = phutil_tag( 81 - 'div', 82 - array( 83 - 'class' => 'phortune-mini-header', 84 - ), 85 - pht('Bill To:')); 86 - 87 - $bill_to = phutil_tag( 88 - 'td', 89 - array( 90 - 'class' => 'phortune-invoice-to', 91 - 'width' => '50%', 92 - ), 93 - array( 94 - $to_title, 95 - phutil_tag('strong', array(), $this->accountName), 96 - phutil_tag('br', array()), 97 - $this->accountContact, 98 - )); 99 - 100 - $from_title = phutil_tag( 101 - 'div', 102 - array( 103 - 'class' => 'phortune-mini-header', 104 - ), 105 - pht('From:')); 106 - 107 - $bill_from = phutil_tag( 108 - 'td', 109 - array( 110 - 'class' => 'phortune-invoice-from', 111 - 'width' => '50%', 112 - ), 113 - array( 114 - $from_title, 115 - phutil_tag('strong', array(), $this->merchantName), 116 - phutil_tag('br', array()), 117 - $this->merchantContact, 118 - )); 119 - 120 - $contact = phutil_tag( 121 - 'table', 122 - array( 123 - 'class' => 'phortune-invoice-contact', 124 - 'width' => '100%', 125 - ), 126 - phutil_tag( 127 - 'tr', 128 - array(), 129 - array( 130 - $bill_to, 131 - $bill_from, 132 - ))); 133 - 134 - $status = null; 135 - if ($this->status) { 136 - $status = phutil_tag( 137 - 'div', 138 - array( 139 - 'class' => 'phortune-invoice-status', 140 - ), 141 - $this->status); 142 - } 143 - 144 - $footer = phutil_tag( 145 - 'div', 146 - array( 147 - 'class' => 'phortune-invoice-footer', 148 - ), 149 - $this->merchantFooter); 150 - 151 - return array( 152 - $logo, 153 - $contact, 154 - $status, 155 - $this->content, 156 - $footer, 157 - ); 158 - } 159 - }
+39
src/applications/phortune/view/PhortuneOrderDescriptionView.php
··· 1 + <?php 2 + 3 + final class PhortuneOrderDescriptionView 4 + extends AphrontView { 5 + 6 + private $order; 7 + 8 + public function setOrder(PhortuneCart $order) { 9 + $this->order = $order; 10 + return $this; 11 + } 12 + 13 + public function getOrder() { 14 + return $this->order; 15 + } 16 + 17 + public function render() { 18 + $viewer = $this->getViewer(); 19 + $order = $this->getOrder(); 20 + 21 + $description = $order->getDescription(); 22 + if (!strlen($description)) { 23 + return null; 24 + } 25 + 26 + $output = new PHUIRemarkupView($viewer, $description); 27 + 28 + $description_box = id(new PHUIBoxView()) 29 + ->addMargin(PHUI::MARGIN_LARGE) 30 + ->appendChild($output); 31 + 32 + return id(new PHUIObjectBoxView()) 33 + ->setHeaderText(pht('Description')) 34 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 35 + ->appendChild($description_box); 36 + } 37 + 38 + 39 + }
+58
src/applications/phortune/view/PhortuneOrderItemsView.php
··· 1 + <?php 2 + 3 + final class PhortuneOrderItemsView 4 + extends PhortuneOrderView { 5 + 6 + public function render() { 7 + $viewer = $this->getViewer(); 8 + $order = $this->getOrder(); 9 + 10 + $purchases = id(new PhortunePurchaseQuery()) 11 + ->setViewer($viewer) 12 + ->withCartPHIDs(array($order->getPHID())) 13 + ->execute(); 14 + 15 + $order->attachPurchases($purchases); 16 + 17 + $rows = array(); 18 + foreach ($purchases as $purchase) { 19 + $rows[] = array( 20 + $purchase->getFullDisplayName(), 21 + $purchase->getBasePriceAsCurrency()->formatForDisplay(), 22 + $purchase->getQuantity(), 23 + $purchase->getTotalPriceAsCurrency()->formatForDisplay(), 24 + ); 25 + } 26 + 27 + $rows[] = array( 28 + phutil_tag('strong', array(), pht('Total')), 29 + '', 30 + '', 31 + phutil_tag('strong', array(), 32 + $order->getTotalPriceAsCurrency()->formatForDisplay()), 33 + ); 34 + 35 + $table = new AphrontTableView($rows); 36 + $table->setHeaders( 37 + array( 38 + pht('Item'), 39 + pht('Price'), 40 + pht('Qty.'), 41 + pht('Total'), 42 + )); 43 + $table->setColumnClasses( 44 + array( 45 + 'wide', 46 + 'right', 47 + 'right', 48 + 'right', 49 + )); 50 + 51 + return id(new PHUIObjectBoxView()) 52 + ->setHeaderText(pht('Items')) 53 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 54 + ->setTable($table); 55 + } 56 + 57 + 58 + }
+370
src/applications/phortune/view/PhortuneOrderSummaryView.php
··· 1 + <?php 2 + 3 + final class PhortuneOrderSummaryView 4 + extends PhortuneOrderView { 5 + 6 + private $resumeURI; 7 + private $printable; 8 + 9 + public function setResumeURI($resume_uri) { 10 + $this->resumeURI = $resume_uri; 11 + return $this; 12 + } 13 + 14 + public function getResumeURI() { 15 + return $this->resumeURI; 16 + } 17 + 18 + public function setPrintable($printable) { 19 + $this->printable = $printable; 20 + return $this; 21 + } 22 + 23 + public function getPrintable() { 24 + return $this->printable; 25 + } 26 + 27 + public function render() { 28 + $is_printable = $this->getPrintable(); 29 + 30 + $content = array(); 31 + 32 + if ($is_printable) { 33 + $content[] = $this->newContactHeader(); 34 + } 35 + 36 + $content[] = $this->newMessagesView(); 37 + $content[] = $this->newDetailsView(); 38 + $content[] = $this->newDescriptionView(); 39 + $content[] = $this->newItemsView(); 40 + $content[] = $this->newChargesView(); 41 + 42 + if ($is_printable) { 43 + $content[] = $this->newContactFooter(); 44 + } 45 + 46 + return $content; 47 + } 48 + 49 + private function newMessagesView() { 50 + $viewer = $this->getViewer(); 51 + $order = $this->getOrder(); 52 + 53 + $messages = array(); 54 + $severity = null; 55 + 56 + $resume_uri = $this->getResumeURI(); 57 + 58 + $can_edit = PhabricatorPolicyFilter::hasCapability( 59 + $viewer, 60 + $order, 61 + PhabricatorPolicyCapability::CAN_EDIT); 62 + 63 + $can_merchant = PhabricatorPolicyFilter::hasCapability( 64 + $viewer, 65 + $order->getMerchant(), 66 + PhabricatorPolicyCapability::CAN_EDIT); 67 + 68 + switch ($order->getStatus()) { 69 + case PhortuneCart::STATUS_READY: 70 + if ($order->getIsInvoice()) { 71 + $severity = PHUIInfoView::SEVERITY_NOTICE; 72 + $messages[] = pht('This invoice is ready for payment.'); 73 + } 74 + break; 75 + case PhortuneCart::STATUS_PURCHASING: 76 + if ($can_edit) { 77 + if ($resume_uri) { 78 + $messages[] = pht( 79 + 'The checkout process has been started, but not yet completed. '. 80 + 'You can continue checking out by clicking %s, or cancel the '. 81 + 'order, or contact the merchant for assistance.', 82 + phutil_tag('strong', array(), pht('Continue Checkout'))); 83 + } else { 84 + $messages[] = pht( 85 + 'The checkout process has been started, but an error occurred. '. 86 + 'You can cancel the order or contact the merchant for '. 87 + 'assistance.'); 88 + } 89 + } 90 + break; 91 + case PhortuneCart::STATUS_CHARGED: 92 + if ($can_edit) { 93 + $messages[] = pht( 94 + 'You have been charged, but processing could not be completed. '. 95 + 'You can cancel your order, or contact the merchant for '. 96 + 'assistance.'); 97 + } 98 + break; 99 + case PhortuneCart::STATUS_HOLD: 100 + if ($can_edit) { 101 + $messages[] = pht( 102 + 'Payment for this order is on hold. You can click %s to check '. 103 + 'for updates, cancel the order, or contact the merchant for '. 104 + 'assistance.', 105 + phutil_tag('strong', array(), pht('Update Status'))); 106 + } 107 + break; 108 + case PhortuneCart::STATUS_REVIEW: 109 + if ($can_merchant) { 110 + $messages[] = pht( 111 + 'This order has been flagged for manual review. Review the order '. 112 + 'and choose %s to accept it or %s to reject it.', 113 + phutil_tag('strong', array(), pht('Accept Order')), 114 + phutil_tag('strong', array(), pht('Refund Order'))); 115 + } else if ($can_edit) { 116 + $messages[] = pht( 117 + 'This order requires manual processing and will complete once '. 118 + 'the merchant accepts it.'); 119 + } 120 + break; 121 + case PhortuneCart::STATUS_PURCHASED: 122 + $severity = PHUIInfoView::SEVERITY_SUCCESS; 123 + $messages[] = pht('This purchase has been completed.'); 124 + break; 125 + } 126 + 127 + if (!$messages) { 128 + return null; 129 + } 130 + 131 + if ($severity === null) { 132 + $severity = PHUIInfoView::SEVERITY_WARNING; 133 + } 134 + 135 + $messages_view = id(new PHUIInfoView()) 136 + ->setSeverity($severity) 137 + ->appendChild($messages); 138 + 139 + $is_printable = $this->getPrintable(); 140 + if ($is_printable) { 141 + $messages_view = phutil_tag( 142 + 'div', 143 + array( 144 + 'class' => 'phortune-invoice-status', 145 + ), 146 + $messages_view); 147 + } 148 + 149 + return $messages_view; 150 + } 151 + 152 + private function newDetailsView() { 153 + $viewer = $this->getViewer(); 154 + $order = $this->getOrder(); 155 + $is_printable = $this->getPrintable(); 156 + 157 + $view = id(new PHUIPropertyListView()) 158 + ->setViewer($viewer) 159 + ->setObject($order); 160 + 161 + $account_phid = $order->getAccountPHID(); 162 + $author_phid = $order->getAuthorPHID(); 163 + $merchant_phid = $order->getMerchantPHID(); 164 + 165 + $handles = $viewer->loadHandles( 166 + array( 167 + $account_phid, 168 + $author_phid, 169 + $merchant_phid, 170 + )); 171 + 172 + if ($is_printable) { 173 + $account_link = $handles[$account_phid]->getFullName(); 174 + $author_link = $handles[$author_phid]->getFullName(); 175 + $merchant_link = $handles[$merchant_phid]->getFullName(); 176 + } else { 177 + $account_link = $handles[$account_phid]->renderLink(); 178 + $author_link = $handles[$author_phid]->renderLink(); 179 + $merchant_link = $handles[$merchant_phid]->renderLink(); 180 + } 181 + 182 + if ($is_printable) { 183 + $view->addProperty(pht('Order Name'), $order->getName()); 184 + } 185 + 186 + $view->addProperty(pht('Account'), $account_link); 187 + $view->addProperty(pht('Authorized By'), $author_link); 188 + $view->addProperty(pht('Merchant'), $merchant_link); 189 + 190 + $view->addProperty( 191 + pht('Order Status'), 192 + PhortuneCart::getNameForStatus($order->getStatus())); 193 + $view->addProperty( 194 + pht('Created'), 195 + phabricator_datetime($order->getDateCreated(), $viewer)); 196 + $view->addProperty( 197 + pht('Updated'), 198 + phabricator_datetime($order->getDateModified(), $viewer)); 199 + 200 + return id(new PHUIObjectBoxView()) 201 + ->setHeaderText(pht('Details')) 202 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 203 + ->appendChild($view); 204 + } 205 + 206 + private function newChargesView() { 207 + $viewer = $this->getViewer(); 208 + $order = $this->getOrder(); 209 + 210 + $charges = id(new PhortuneChargeQuery()) 211 + ->setViewer($viewer) 212 + ->withCartPHIDs(array($order->getPHID())) 213 + ->needCarts(true) 214 + ->execute(); 215 + 216 + $charges_table = id(new PhortuneChargeTableView()) 217 + ->setUser($viewer) 218 + ->setCharges($charges) 219 + ->setShowOrder(false); 220 + 221 + $charges_view = id(new PHUIObjectBoxView()) 222 + ->setHeaderText(pht('Charges')) 223 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 224 + ->setTable($charges_table); 225 + 226 + return $charges_view; 227 + } 228 + 229 + private function newDescriptionView() { 230 + $viewer = $this->getViewer(); 231 + $order = $this->getOrder(); 232 + 233 + return id(new PhortuneOrderDescriptionView()) 234 + ->setViewer($viewer) 235 + ->setOrder($order); 236 + } 237 + 238 + private function newItemsView() { 239 + $viewer = $this->getViewer(); 240 + $order = $this->getOrder(); 241 + 242 + return id(new PhortuneOrderItemsView()) 243 + ->setViewer($viewer) 244 + ->setOrder($order); 245 + } 246 + 247 + private function newContactHeader() { 248 + $viewer = $this->getViewer(); 249 + $order = $this->getOrder(); 250 + 251 + $merchant = id(new PhortuneMerchantQuery()) 252 + ->setViewer($viewer) 253 + ->withPHIDs(array($order->getMerchant()->getPHID())) 254 + ->needProfileImage(true) 255 + ->executeOne(); 256 + 257 + $merchant_name = $merchant->getName(); 258 + $merchant_image = $merchant->getProfileImageURI(); 259 + 260 + $account = $order->getAccount(); 261 + $account_name = $account->getBillingName(); 262 + 263 + $account_contact = $account->getBillingAddress(); 264 + if (strlen($account_contact)) { 265 + $account_contact = new PHUIRemarkupView( 266 + $viewer, 267 + $account_contact); 268 + } 269 + 270 + $merchant_contact = $merchant->getContactInfo(); 271 + if (strlen($merchant_contact)) { 272 + $merchant_contact = new PHUIRemarkupView( 273 + $viewer, 274 + $merchant->getContactInfo()); 275 + } 276 + 277 + $logo = phutil_tag( 278 + 'div', 279 + array( 280 + 'class' => 'phortune-invoice-logo', 281 + ), 282 + phutil_tag( 283 + 'img', 284 + array( 285 + 'height' => '50', 286 + 'width' => '50', 287 + 'alt' => $merchant_name, 288 + 'src' => $merchant_image, 289 + ))); 290 + 291 + $to_title = phutil_tag( 292 + 'div', 293 + array( 294 + 'class' => 'phortune-mini-header', 295 + ), 296 + pht('Bill To:')); 297 + 298 + $bill_to = phutil_tag( 299 + 'td', 300 + array( 301 + 'class' => 'phortune-invoice-to', 302 + 'width' => '50%', 303 + ), 304 + array( 305 + $to_title, 306 + phutil_tag('strong', array(), $account_name), 307 + phutil_tag('br', array()), 308 + $account_contact, 309 + )); 310 + 311 + $from_title = phutil_tag( 312 + 'div', 313 + array( 314 + 'class' => 'phortune-mini-header', 315 + ), 316 + pht('From:')); 317 + 318 + $bill_from = phutil_tag( 319 + 'td', 320 + array( 321 + 'class' => 'phortune-invoice-from', 322 + 'width' => '50%', 323 + ), 324 + array( 325 + $from_title, 326 + phutil_tag('strong', array(), $merchant_name), 327 + phutil_tag('br', array()), 328 + $merchant_contact, 329 + )); 330 + 331 + $contact = phutil_tag( 332 + 'table', 333 + array( 334 + 'class' => 'phortune-invoice-contact', 335 + 'width' => '100%', 336 + ), 337 + phutil_tag( 338 + 'tr', 339 + array(), 340 + array( 341 + $bill_to, 342 + $bill_from, 343 + ))); 344 + 345 + return array( 346 + $logo, 347 + $contact, 348 + ); 349 + } 350 + 351 + private function newContactFooter() { 352 + $viewer = $this->getViewer(); 353 + $order = $this->getOrder(); 354 + 355 + $merchant = $order->getMerchant(); 356 + $footer = $merchant->getInvoiceFooter(); 357 + 358 + if (!strlen($footer)) { 359 + return null; 360 + } 361 + 362 + return phutil_tag( 363 + 'div', 364 + array( 365 + 'class' => 'phortune-invoice-footer', 366 + ), 367 + $footer); 368 + } 369 + 370 + }
+17
src/applications/phortune/view/PhortuneOrderView.php
··· 1 + <?php 2 + 3 + abstract class PhortuneOrderView 4 + extends AphrontView { 5 + 6 + private $order; 7 + 8 + final public function setOrder(PhortuneCart $order) { 9 + $this->order = $order; 10 + return $this; 11 + } 12 + 13 + final public function getOrder() { 14 + return $this->order; 15 + } 16 + 17 + }