1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 14:52:41 +01:00

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
This commit is contained in:
epriestley 2019-08-24 09:43:27 -07:00
parent a0a3879712
commit 97a4a59cf2
13 changed files with 663 additions and 463 deletions

View file

@ -5302,7 +5302,6 @@ phutil_register_library_map(array(
'PhortuneExternalOrderController' => 'applications/phortune/controller/external/PhortuneExternalOrderController.php',
'PhortuneExternalOverviewController' => 'applications/phortune/controller/external/PhortuneExternalOverviewController.php',
'PhortuneExternalUnsubscribeController' => 'applications/phortune/controller/external/PhortuneExternalUnsubscribeController.php',
'PhortuneInvoiceView' => 'applications/phortune/view/PhortuneInvoiceView.php',
'PhortuneLandingController' => 'applications/phortune/controller/PhortuneLandingController.php',
'PhortuneMemberHasAccountEdgeType' => 'applications/phortune/edge/PhortuneMemberHasAccountEdgeType.php',
'PhortuneMemberHasMerchantEdgeType' => 'applications/phortune/edge/PhortuneMemberHasMerchantEdgeType.php',
@ -5343,7 +5342,11 @@ phutil_register_library_map(array(
'PhortuneMerchantTransactionQuery' => 'applications/phortune/query/PhortuneMerchantTransactionQuery.php',
'PhortuneMerchantTransactionType' => 'applications/phortune/xaction/PhortuneMerchantTransactionType.php',
'PhortuneMonthYearExpiryControl' => 'applications/phortune/control/PhortuneMonthYearExpiryControl.php',
'PhortuneOrderDescriptionView' => 'applications/phortune/view/PhortuneOrderDescriptionView.php',
'PhortuneOrderItemsView' => 'applications/phortune/view/PhortuneOrderItemsView.php',
'PhortuneOrderSummaryView' => 'applications/phortune/view/PhortuneOrderSummaryView.php',
'PhortuneOrderTableView' => 'applications/phortune/view/PhortuneOrderTableView.php',
'PhortuneOrderView' => 'applications/phortune/view/PhortuneOrderView.php',
'PhortunePayPalPaymentProvider' => 'applications/phortune/provider/PhortunePayPalPaymentProvider.php',
'PhortunePaymentMethod' => 'applications/phortune/storage/PhortunePaymentMethod.php',
'PhortunePaymentMethodCreateController' => 'applications/phortune/controller/paymentmethod/PhortunePaymentMethodCreateController.php',
@ -11895,7 +11898,6 @@ phutil_register_library_map(array(
'PhortuneExternalOrderController' => 'PhortuneExternalController',
'PhortuneExternalOverviewController' => 'PhortuneExternalController',
'PhortuneExternalUnsubscribeController' => 'PhortuneExternalController',
'PhortuneInvoiceView' => 'AphrontTagView',
'PhortuneLandingController' => 'PhortuneController',
'PhortuneMemberHasAccountEdgeType' => 'PhabricatorEdgeType',
'PhortuneMemberHasMerchantEdgeType' => 'PhabricatorEdgeType',
@ -11940,7 +11942,11 @@ phutil_register_library_map(array(
'PhortuneMerchantTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhortuneMerchantTransactionType' => 'PhabricatorModularTransactionType',
'PhortuneMonthYearExpiryControl' => 'AphrontFormControl',
'PhortuneOrderDescriptionView' => 'AphrontView',
'PhortuneOrderItemsView' => 'PhortuneOrderView',
'PhortuneOrderSummaryView' => 'PhortuneOrderView',
'PhortuneOrderTableView' => 'AphrontView',
'PhortuneOrderView' => 'AphrontView',
'PhortunePayPalPaymentProvider' => 'PhortunePaymentProvider',
'PhortunePaymentMethod' => array(
'PhortuneDAO',

View file

@ -481,7 +481,7 @@ abstract class PhabricatorController extends AphrontController {
protected function buildTransactionTimeline(
PhabricatorApplicationTransactionInterface $object,
PhabricatorApplicationTransactionQuery $query,
PhabricatorApplicationTransactionQuery $query = null,
PhabricatorMarkupEngine $engine = null,
$view_data = array()) {
@ -489,6 +489,17 @@ abstract class PhabricatorController extends AphrontController {
$viewer = $this->getViewer();
$xaction = $object->getApplicationTransactionTemplate();
if (!$query) {
$query = PhabricatorApplicationTransactionQuery::newQueryForObject(
$object);
if (!$query) {
throw new Exception(
pht(
'Unable to find transaction query for object of class "%s".',
get_class($object)));
}
}
$pager = id(new AphrontCursorPagerView())
->readFromRequest($request)
->setURI(new PhutilURI(

View file

@ -113,7 +113,10 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
'' => 'PhortuneExternalOverviewController',
'unsubscribe/' => 'PhortuneExternalUnsubscribeController',
'order/' => array(
'(?P<orderID>[^/]+)/' => 'PhortuneExternalOrderController',
'(?P<orderID>[^/]+)/' => array(
'' => 'PhortuneExternalOrderController',
'(?P<action>print)/' => 'PhortuneExternalOrderController',
),
),
),
'merchant/' => array(

View file

@ -207,7 +207,9 @@ final class PhortuneCartCheckoutController
->appendChild($form)
->appendChild($provider_form);
$description_box = $this->renderCartDescription($cart);
$description_view = id(new PhortuneOrderDescriptionView())
->setViewer($viewer)
->setOrder($cart);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Checkout'));
@ -220,11 +222,12 @@ final class PhortuneCartCheckoutController
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter(array(
$cart_box,
$description_box,
$payment_box,
));
->setFooter(
array(
$description_view,
$cart_box,
$payment_box,
));
return $this->newPage()
->setTitle($title)

View file

@ -74,61 +74,4 @@ abstract class PhortuneCartController
PhabricatorPolicyCapability::CAN_EDIT);
}
protected function buildCartContentTable(PhortuneCart $cart) {
$rows = array();
foreach ($cart->getPurchases() as $purchase) {
$rows[] = array(
$purchase->getFullDisplayName(),
$purchase->getBasePriceAsCurrency()->formatForDisplay(),
$purchase->getQuantity(),
$purchase->getTotalPriceAsCurrency()->formatForDisplay(),
);
}
$rows[] = array(
phutil_tag('strong', array(), pht('Total')),
'',
'',
phutil_tag('strong', array(),
$cart->getTotalPriceAsCurrency()->formatForDisplay()),
);
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
pht('Item'),
pht('Price'),
pht('Qty.'),
pht('Total'),
));
$table->setColumnClasses(
array(
'wide',
'right',
'right',
'right',
));
return $table;
}
protected function renderCartDescription(PhortuneCart $cart) {
$description = $cart->getDescription();
if (!strlen($description)) {
return null;
}
$output = new PHUIRemarkupView($this->getViewer(), $description);
$box = id(new PHUIBoxView())
->addMargin(PHUI::MARGIN_LARGE)
->appendChild($output);
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Description'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($box);
}
}

View file

@ -3,8 +3,6 @@
final class PhortuneCartViewController
extends PhortuneCartController {
private $action = null;
protected function shouldRequireAccountAuthority() {
return false;
}
@ -15,214 +13,93 @@ final class PhortuneCartViewController
protected function handleCartRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$cart = $this->getCart();
$order = $this->getCart();
$authority = $this->getMerchantAuthority();
$can_edit = $this->hasAccountAuthority();
$this->action = $request->getURIData('action');
$is_printable = ($request->getURIData('action') === 'print');
$cart_table = $this->buildCartContentTable($cart);
$errors = array();
$error_view = null;
$resume_uri = null;
switch ($cart->getStatus()) {
case PhortuneCart::STATUS_READY:
if ($cart->getIsInvoice()) {
$error_view = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
->appendChild(pht('This invoice is ready for payment.'));
}
break;
case PhortuneCart::STATUS_PURCHASING:
if ($can_edit) {
$resume_uri = $cart->getMetadataValue('provider.checkoutURI');
if ($resume_uri) {
$errors[] = pht(
'The checkout process has been started, but not yet completed. '.
'You can continue checking out by clicking %s, or cancel the '.
'order, or contact the merchant for assistance.',
phutil_tag('strong', array(), pht('Continue Checkout')));
} else {
$errors[] = pht(
'The checkout process has been started, but an error occurred. '.
'You can cancel the order or contact the merchant for '.
'assistance.');
}
}
break;
case PhortuneCart::STATUS_CHARGED:
if ($can_edit) {
$errors[] = pht(
'You have been charged, but processing could not be completed. '.
'You can cancel your order, or contact the merchant for '.
'assistance.');
}
break;
case PhortuneCart::STATUS_HOLD:
if ($can_edit) {
$errors[] = pht(
'Payment for this order is on hold. You can click %s to check '.
'for updates, cancel the order, or contact the merchant for '.
'assistance.',
phutil_tag('strong', array(), pht('Update Status')));
}
break;
case PhortuneCart::STATUS_REVIEW:
if ($authority) {
$errors[] = pht(
'This order has been flagged for manual review. Review the order '.
'and choose %s to accept it or %s to reject it.',
phutil_tag('strong', array(), pht('Accept Order')),
phutil_tag('strong', array(), pht('Refund Order')));
} else if ($can_edit) {
$errors[] = pht(
'This order requires manual processing and will complete once '.
'the merchant accepts it.');
}
break;
case PhortuneCart::STATUS_PURCHASED:
$error_view = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_SUCCESS)
->appendChild(pht('This purchase has been completed.'));
break;
if ($order->getStatus() === PhortuneCart::STATUS_PURCHASING) {
if ($can_edit) {
$resume_uri = $order->getMetadataValue('provider.checkoutURI');
}
}
if ($errors) {
$error_view = id(new PHUIInfoView())
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
->appendChild($errors);
}
$details = $this->buildDetailsView($cart);
$curtain = $this->buildCurtainView(
$cart,
$can_edit,
$authority,
$resume_uri);
$header = id(new PHUIHeaderView())
->setUser($viewer)
->setHeader($cart->getName())
->setHeader($order->getName())
->setHeaderIcon('fa-shopping-bag');
if ($cart->getStatus() == PhortuneCart::STATUS_PURCHASED) {
$done_uri = $cart->getDoneURI();
if ($order->getStatus() == PhortuneCart::STATUS_PURCHASED) {
$done_uri = $order->getDoneURI();
if ($done_uri) {
$header->addActionLink(
id(new PHUIButtonView())
->setTag('a')
->setHref($done_uri)
->setIcon('fa-check-square green')
->setText($cart->getDoneActionName()));
->setText($order->getDoneActionName()));
}
}
$cart_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Cart Items'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($cart_table);
$description = $this->renderCartDescription($cart);
$charges = id(new PhortuneChargeQuery())
$order_view = id(new PhortuneOrderSummaryView())
->setViewer($viewer)
->withCartPHIDs(array($cart->getPHID()))
->needCarts(true)
->execute();
->setOrder($order)
->setResumeURI($resume_uri)
->setPrintable($is_printable);
$charges_table = id(new PhortuneChargeTableView())
->setUser($viewer)
->setCharges($charges)
->setShowOrder(false);
$crumbs = null;
$curtain = null;
$charges = id(new PHUIObjectBoxView())
->setHeaderText(pht('Charges'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($charges_table);
$main = array();
$tail = array();
$account = $cart->getAccount();
require_celerity_resource('phortune-invoice-css');
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb($account->getName(), $account->getURI())
->addTextCrumb(pht('Orders'), $account->getOrdersURI())
->addTextCrumb(pht('Cart %d', $cart->getID()))
->setBorder(true);
require_celerity_resource('phortune-css');
if (!$this->action) {
$class = 'phortune-cart-page';
$timeline = $this->buildTransactionTimeline(
$cart,
new PhortuneCartTransactionQuery());
$timeline
->setShouldTerminate(true);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->setMainColumn(array(
$error_view,
$details,
$cart_box,
$description,
$charges,
$timeline,
));
if ($is_printable) {
$body_class = 'phortune-invoice-view';
$tail[] = $order_view;
} else {
$class = 'phortune-invoice-view';
$crumbs = null;
$merchant_phid = $cart->getMerchantPHID();
$buyer_phid = $cart->getAuthorPHID();
$merchant = id(new PhortuneMerchantQuery())
->setViewer($viewer)
->withPHIDs(array($merchant_phid))
->needProfileImage(true)
->executeOne();
$buyer = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withPHIDs(array($buyer_phid))
->needProfileImage(true)
->executeOne();
$body_class = 'phortune-cart-page';
$merchant_contact = new PHUIRemarkupView(
$viewer,
$merchant->getContactInfo());
$curtain = $this->buildCurtainView(
$order,
$can_edit,
$authority,
$resume_uri);
$account_name = $account->getBillingName();
if (!strlen($account_name)) {
$account_name = $buyer->getRealName();
}
$account = $order->getAccount();
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb($account->getName(), $account->getURI())
->addTextCrumb(pht('Orders'), $account->getOrdersURI())
->addTextCrumb($order->getObjectName())
->setBorder(true);
$account_contact = $account->getBillingAddress();
if (strlen($account_contact)) {
$account_contact = new PHUIRemarkupView(
$viewer,
$account_contact);
}
$timeline = $this->buildTransactionTimeline($order)
->setShouldTerminate(true);
$view = id(new PhortuneInvoiceView())
->setMerchantName($merchant->getName())
->setMerchantLogo($merchant->getProfileImageURI())
->setMerchantContact($merchant_contact)
->setMerchantFooter($merchant->getInvoiceFooter())
->setAccountName($account_name)
->setAccountContact($account_contact)
->setStatus($error_view)
->setContent(
array(
$details,
$cart_box,
$charges,
));
$main[] = $order_view;
$main[] = $timeline;
}
$column_view = id(new PHUITwoColumnView())
->setMainColumn($main)
->setFooter($tail);
if ($curtain) {
$column_view->setCurtain($curtain);
}
$page = $this->newPage()
->setTitle(pht('Cart %d', $cart->getID()))
->addClass($class)
->appendChild($view);
->addClass($body_class)
->setTitle(
array(
$order->getObjectName(),
$order->getName(),
))
->appendChild($column_view);
if ($crumbs) {
$page->setCrumbs($crumbs);
@ -231,45 +108,6 @@ final class PhortuneCartViewController
return $page;
}
private function buildDetailsView(PhortuneCart $cart) {
$viewer = $this->getViewer();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setObject($cart);
$handles = $this->loadViewerHandles(
array(
$cart->getAccountPHID(),
$cart->getAuthorPHID(),
$cart->getMerchantPHID(),
));
if ($this->action == 'print') {
$view->addProperty(pht('Order Name'), $cart->getName());
}
$view->addProperty(
pht('Account'),
$handles[$cart->getAccountPHID()]->renderLink());
$view->addProperty(
pht('Authorized By'),
$handles[$cart->getAuthorPHID()]->renderLink());
$view->addProperty(
pht('Merchant'),
$handles[$cart->getMerchantPHID()]->renderLink());
$view->addProperty(
pht('Status'),
PhortuneCart::getNameForStatus($cart->getStatus()));
$view->addProperty(
pht('Updated'),
phabricator_datetime($cart->getDateModified(), $viewer));
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Details'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($view);
}
private function buildCurtainView(
PhortuneCart $cart,
$can_edit,
@ -297,6 +135,18 @@ final class PhortuneCartViewController
$checkout_uri = $cart->getCheckoutURI();
$void_uri = $this->getApplicationURI("cart/{$id}/void/");
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Printable Version'))
->setHref($print_uri)
->setOpenInNewWindow(true)
->setIcon('fa-print'));
$curtain->addAction(
id(new PhabricatorActionView())
->setType(PhabricatorActionView::TYPE_DIVIDER));
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Pay Now'))
@ -327,13 +177,6 @@ final class PhortuneCartViewController
->setHref($resume_uri));
}
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Printable Version'))
->setHref($print_uri)
->setOpenInNewWindow(true)
->setIcon('fa-print'));
if ($authority) {
$curtain->addAction(
id(new PhabricatorActionView())

View file

@ -17,24 +17,82 @@ final class PhortuneExternalOrderController
return new Aphront404Response();
}
$timeline = $this->buildTransactionTimeline(
$order,
new PhortuneCartTransactionQuery());
$timeline->setShouldTerminate(true);
$is_printable = ($request->getURIData('action') === 'print');
$crumbs = $this->newExternalCrumbs()
->addTextCrumb($order->getObjectName());
$order_view = id(new PhortuneOrderSummaryView())
->setViewer($xviewer)
->setOrder($order)
->setPrintable($is_printable);
$view = id(new PHUITwoColumnView())
->setMainColumn(
$crumbs = null;
$curtain = null;
$main = array();
$tail = array();
require_celerity_resource('phortune-invoice-css');
if ($is_printable) {
$body_class = 'phortune-invoice-view';
$tail[] = $order_view;
} else {
$body_class = 'phortune-cart-page';
$curtain = $this->newCurtain($order);
$crumbs = $this->newExternalCrumbs()
->addTextCrumb($order->getObjectName())
->setBorder(true);
$timeline = $this->buildTransactionTimeline($order)
->setShouldTerminate(true);
$main[] = $order_view;
$main[] = $timeline;
}
$column_view = id(new PHUITwoColumnView())
->setMainColumn($main)
->setFooter($tail);
if ($curtain) {
$column_view->setCurtain($curtain);
}
$page = $this->newPage()
->addClass($body_class)
->setTitle(
array(
$timeline,
));
$order->getObjectName(),
$order->getName(),
))
->appendChild($column_view);
return $this->newPage()
->setTitle(pht('Order %d', $order->getID()))
->setCrumbs($crumbs)
->appendChild($view);
}
if ($crumbs) {
$page->setCrumbs($crumbs);
}
return $page;
}
private function newCurtain(PhortuneCart $order) {
$xviewer = $this->getExternalViewer();
$email = $this->getAccountEmail();
$curtain = $this->newCurtainView($order);
$print_uri = $email->getExternalOrderPrintURI($order);
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Printable Version'))
->setHref($print_uri)
->setOpenInNewWindow(true)
->setIcon('fa-print'));
return $curtain;
}
}

View file

@ -100,6 +100,14 @@ final class PhortuneAccountEmail
$cart->getID());
}
public function getExternalOrderPrintURI(PhortuneCart $cart) {
return urisprintf(
'/phortune/external/%s/%s/order/%d/print/',
$this->getAddressKey(),
$this->getAccessKey(),
$cart->getID());
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -1,159 +0,0 @@
<?php
final class PhortuneInvoiceView extends AphrontTagView {
private $merchantName;
private $merchantLogo;
private $merchantContact;
private $merchantFooter;
private $accountName;
private $accountContact;
private $status;
private $content;
public function setMerchantName($name) {
$this->merchantName = $name;
return $this;
}
public function setMerchantLogo($logo) {
$this->merchantLogo = $logo;
return $this;
}
public function setMerchantContact($contact) {
$this->merchantContact = $contact;
return $this;
}
public function setMerchantFooter($footer) {
$this->merchantFooter = $footer;
return $this;
}
public function setAccountName($name) {
$this->accountName = $name;
return $this;
}
public function setAccountContact($contact) {
$this->accountContact = $contact;
return $this;
}
public function setStatus($status) {
$this->status = $status;
return $this;
}
public function setContent($content) {
$this->content = $content;
return $this;
}
protected function getTagAttributes() {
$classes = array();
$classes[] = 'phortune-invoice-view';
return array(
'class' => implode(' ', $classes),
);
}
protected function getTagContent() {
require_celerity_resource('phortune-invoice-css');
$logo = phutil_tag(
'div',
array(
'class' => 'phortune-invoice-logo',
),
phutil_tag(
'img',
array(
'height' => '50',
'width' => '50',
'alt' => $this->merchantName,
'src' => $this->merchantLogo,
)));
$to_title = phutil_tag(
'div',
array(
'class' => 'phortune-mini-header',
),
pht('Bill To:'));
$bill_to = phutil_tag(
'td',
array(
'class' => 'phortune-invoice-to',
'width' => '50%',
),
array(
$to_title,
phutil_tag('strong', array(), $this->accountName),
phutil_tag('br', array()),
$this->accountContact,
));
$from_title = phutil_tag(
'div',
array(
'class' => 'phortune-mini-header',
),
pht('From:'));
$bill_from = phutil_tag(
'td',
array(
'class' => 'phortune-invoice-from',
'width' => '50%',
),
array(
$from_title,
phutil_tag('strong', array(), $this->merchantName),
phutil_tag('br', array()),
$this->merchantContact,
));
$contact = phutil_tag(
'table',
array(
'class' => 'phortune-invoice-contact',
'width' => '100%',
),
phutil_tag(
'tr',
array(),
array(
$bill_to,
$bill_from,
)));
$status = null;
if ($this->status) {
$status = phutil_tag(
'div',
array(
'class' => 'phortune-invoice-status',
),
$this->status);
}
$footer = phutil_tag(
'div',
array(
'class' => 'phortune-invoice-footer',
),
$this->merchantFooter);
return array(
$logo,
$contact,
$status,
$this->content,
$footer,
);
}
}

View file

@ -0,0 +1,39 @@
<?php
final class PhortuneOrderDescriptionView
extends AphrontView {
private $order;
public function setOrder(PhortuneCart $order) {
$this->order = $order;
return $this;
}
public function getOrder() {
return $this->order;
}
public function render() {
$viewer = $this->getViewer();
$order = $this->getOrder();
$description = $order->getDescription();
if (!strlen($description)) {
return null;
}
$output = new PHUIRemarkupView($viewer, $description);
$description_box = id(new PHUIBoxView())
->addMargin(PHUI::MARGIN_LARGE)
->appendChild($output);
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Description'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($description_box);
}
}

View file

@ -0,0 +1,58 @@
<?php
final class PhortuneOrderItemsView
extends PhortuneOrderView {
public function render() {
$viewer = $this->getViewer();
$order = $this->getOrder();
$purchases = id(new PhortunePurchaseQuery())
->setViewer($viewer)
->withCartPHIDs(array($order->getPHID()))
->execute();
$order->attachPurchases($purchases);
$rows = array();
foreach ($purchases as $purchase) {
$rows[] = array(
$purchase->getFullDisplayName(),
$purchase->getBasePriceAsCurrency()->formatForDisplay(),
$purchase->getQuantity(),
$purchase->getTotalPriceAsCurrency()->formatForDisplay(),
);
}
$rows[] = array(
phutil_tag('strong', array(), pht('Total')),
'',
'',
phutil_tag('strong', array(),
$order->getTotalPriceAsCurrency()->formatForDisplay()),
);
$table = new AphrontTableView($rows);
$table->setHeaders(
array(
pht('Item'),
pht('Price'),
pht('Qty.'),
pht('Total'),
));
$table->setColumnClasses(
array(
'wide',
'right',
'right',
'right',
));
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Items'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($table);
}
}

View file

@ -0,0 +1,370 @@
<?php
final class PhortuneOrderSummaryView
extends PhortuneOrderView {
private $resumeURI;
private $printable;
public function setResumeURI($resume_uri) {
$this->resumeURI = $resume_uri;
return $this;
}
public function getResumeURI() {
return $this->resumeURI;
}
public function setPrintable($printable) {
$this->printable = $printable;
return $this;
}
public function getPrintable() {
return $this->printable;
}
public function render() {
$is_printable = $this->getPrintable();
$content = array();
if ($is_printable) {
$content[] = $this->newContactHeader();
}
$content[] = $this->newMessagesView();
$content[] = $this->newDetailsView();
$content[] = $this->newDescriptionView();
$content[] = $this->newItemsView();
$content[] = $this->newChargesView();
if ($is_printable) {
$content[] = $this->newContactFooter();
}
return $content;
}
private function newMessagesView() {
$viewer = $this->getViewer();
$order = $this->getOrder();
$messages = array();
$severity = null;
$resume_uri = $this->getResumeURI();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$order,
PhabricatorPolicyCapability::CAN_EDIT);
$can_merchant = PhabricatorPolicyFilter::hasCapability(
$viewer,
$order->getMerchant(),
PhabricatorPolicyCapability::CAN_EDIT);
switch ($order->getStatus()) {
case PhortuneCart::STATUS_READY:
if ($order->getIsInvoice()) {
$severity = PHUIInfoView::SEVERITY_NOTICE;
$messages[] = pht('This invoice is ready for payment.');
}
break;
case PhortuneCart::STATUS_PURCHASING:
if ($can_edit) {
if ($resume_uri) {
$messages[] = pht(
'The checkout process has been started, but not yet completed. '.
'You can continue checking out by clicking %s, or cancel the '.
'order, or contact the merchant for assistance.',
phutil_tag('strong', array(), pht('Continue Checkout')));
} else {
$messages[] = pht(
'The checkout process has been started, but an error occurred. '.
'You can cancel the order or contact the merchant for '.
'assistance.');
}
}
break;
case PhortuneCart::STATUS_CHARGED:
if ($can_edit) {
$messages[] = pht(
'You have been charged, but processing could not be completed. '.
'You can cancel your order, or contact the merchant for '.
'assistance.');
}
break;
case PhortuneCart::STATUS_HOLD:
if ($can_edit) {
$messages[] = pht(
'Payment for this order is on hold. You can click %s to check '.
'for updates, cancel the order, or contact the merchant for '.
'assistance.',
phutil_tag('strong', array(), pht('Update Status')));
}
break;
case PhortuneCart::STATUS_REVIEW:
if ($can_merchant) {
$messages[] = pht(
'This order has been flagged for manual review. Review the order '.
'and choose %s to accept it or %s to reject it.',
phutil_tag('strong', array(), pht('Accept Order')),
phutil_tag('strong', array(), pht('Refund Order')));
} else if ($can_edit) {
$messages[] = pht(
'This order requires manual processing and will complete once '.
'the merchant accepts it.');
}
break;
case PhortuneCart::STATUS_PURCHASED:
$severity = PHUIInfoView::SEVERITY_SUCCESS;
$messages[] = pht('This purchase has been completed.');
break;
}
if (!$messages) {
return null;
}
if ($severity === null) {
$severity = PHUIInfoView::SEVERITY_WARNING;
}
$messages_view = id(new PHUIInfoView())
->setSeverity($severity)
->appendChild($messages);
$is_printable = $this->getPrintable();
if ($is_printable) {
$messages_view = phutil_tag(
'div',
array(
'class' => 'phortune-invoice-status',
),
$messages_view);
}
return $messages_view;
}
private function newDetailsView() {
$viewer = $this->getViewer();
$order = $this->getOrder();
$is_printable = $this->getPrintable();
$view = id(new PHUIPropertyListView())
->setViewer($viewer)
->setObject($order);
$account_phid = $order->getAccountPHID();
$author_phid = $order->getAuthorPHID();
$merchant_phid = $order->getMerchantPHID();
$handles = $viewer->loadHandles(
array(
$account_phid,
$author_phid,
$merchant_phid,
));
if ($is_printable) {
$account_link = $handles[$account_phid]->getFullName();
$author_link = $handles[$author_phid]->getFullName();
$merchant_link = $handles[$merchant_phid]->getFullName();
} else {
$account_link = $handles[$account_phid]->renderLink();
$author_link = $handles[$author_phid]->renderLink();
$merchant_link = $handles[$merchant_phid]->renderLink();
}
if ($is_printable) {
$view->addProperty(pht('Order Name'), $order->getName());
}
$view->addProperty(pht('Account'), $account_link);
$view->addProperty(pht('Authorized By'), $author_link);
$view->addProperty(pht('Merchant'), $merchant_link);
$view->addProperty(
pht('Order Status'),
PhortuneCart::getNameForStatus($order->getStatus()));
$view->addProperty(
pht('Created'),
phabricator_datetime($order->getDateCreated(), $viewer));
$view->addProperty(
pht('Updated'),
phabricator_datetime($order->getDateModified(), $viewer));
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Details'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($view);
}
private function newChargesView() {
$viewer = $this->getViewer();
$order = $this->getOrder();
$charges = id(new PhortuneChargeQuery())
->setViewer($viewer)
->withCartPHIDs(array($order->getPHID()))
->needCarts(true)
->execute();
$charges_table = id(new PhortuneChargeTableView())
->setUser($viewer)
->setCharges($charges)
->setShowOrder(false);
$charges_view = id(new PHUIObjectBoxView())
->setHeaderText(pht('Charges'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->setTable($charges_table);
return $charges_view;
}
private function newDescriptionView() {
$viewer = $this->getViewer();
$order = $this->getOrder();
return id(new PhortuneOrderDescriptionView())
->setViewer($viewer)
->setOrder($order);
}
private function newItemsView() {
$viewer = $this->getViewer();
$order = $this->getOrder();
return id(new PhortuneOrderItemsView())
->setViewer($viewer)
->setOrder($order);
}
private function newContactHeader() {
$viewer = $this->getViewer();
$order = $this->getOrder();
$merchant = id(new PhortuneMerchantQuery())
->setViewer($viewer)
->withPHIDs(array($order->getMerchant()->getPHID()))
->needProfileImage(true)
->executeOne();
$merchant_name = $merchant->getName();
$merchant_image = $merchant->getProfileImageURI();
$account = $order->getAccount();
$account_name = $account->getBillingName();
$account_contact = $account->getBillingAddress();
if (strlen($account_contact)) {
$account_contact = new PHUIRemarkupView(
$viewer,
$account_contact);
}
$merchant_contact = $merchant->getContactInfo();
if (strlen($merchant_contact)) {
$merchant_contact = new PHUIRemarkupView(
$viewer,
$merchant->getContactInfo());
}
$logo = phutil_tag(
'div',
array(
'class' => 'phortune-invoice-logo',
),
phutil_tag(
'img',
array(
'height' => '50',
'width' => '50',
'alt' => $merchant_name,
'src' => $merchant_image,
)));
$to_title = phutil_tag(
'div',
array(
'class' => 'phortune-mini-header',
),
pht('Bill To:'));
$bill_to = phutil_tag(
'td',
array(
'class' => 'phortune-invoice-to',
'width' => '50%',
),
array(
$to_title,
phutil_tag('strong', array(), $account_name),
phutil_tag('br', array()),
$account_contact,
));
$from_title = phutil_tag(
'div',
array(
'class' => 'phortune-mini-header',
),
pht('From:'));
$bill_from = phutil_tag(
'td',
array(
'class' => 'phortune-invoice-from',
'width' => '50%',
),
array(
$from_title,
phutil_tag('strong', array(), $merchant_name),
phutil_tag('br', array()),
$merchant_contact,
));
$contact = phutil_tag(
'table',
array(
'class' => 'phortune-invoice-contact',
'width' => '100%',
),
phutil_tag(
'tr',
array(),
array(
$bill_to,
$bill_from,
)));
return array(
$logo,
$contact,
);
}
private function newContactFooter() {
$viewer = $this->getViewer();
$order = $this->getOrder();
$merchant = $order->getMerchant();
$footer = $merchant->getInvoiceFooter();
if (!strlen($footer)) {
return null;
}
return phutil_tag(
'div',
array(
'class' => 'phortune-invoice-footer',
),
$footer);
}
}

View file

@ -0,0 +1,17 @@
<?php
abstract class PhortuneOrderView
extends AphrontView {
private $order;
final public function setOrder(PhortuneCart $order) {
$this->order = $order;
return $this;
}
final public function getOrder() {
return $this->order;
}
}