mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-16 16:58:38 +01:00
Update the Phortune cart/invoice workflow for policy changes
Summary: Depends on D20734. Ref T13366. This makes the cart/order flow work under the new policy scheme with no "grantAuthority()" calls. It prepares for a "Void Invoice" action, although the action doesn't actually do anything yet. Test Plan: With and without merchant authority, viewed and paid invoices and went through the other invoice interaction workflows. Maniphest Tasks: T13366 Differential Revision: https://secure.phabricator.com/D20735
This commit is contained in:
parent
b3f8045b87
commit
a39a37fc0e
20 changed files with 300 additions and 564 deletions
|
@ -5279,6 +5279,7 @@ phutil_register_library_map(array(
|
|||
'PhortuneCartTransactionQuery' => 'applications/phortune/query/PhortuneCartTransactionQuery.php',
|
||||
'PhortuneCartUpdateController' => 'applications/phortune/controller/cart/PhortuneCartUpdateController.php',
|
||||
'PhortuneCartViewController' => 'applications/phortune/controller/cart/PhortuneCartViewController.php',
|
||||
'PhortuneCartVoidController' => 'applications/phortune/controller/cart/PhortuneCartVoidController.php',
|
||||
'PhortuneCharge' => 'applications/phortune/storage/PhortuneCharge.php',
|
||||
'PhortuneChargePHIDType' => 'applications/phortune/phid/PhortuneChargePHIDType.php',
|
||||
'PhortuneChargeQuery' => 'applications/phortune/query/PhortuneChargeQuery.php',
|
||||
|
@ -5372,10 +5373,8 @@ phutil_register_library_map(array(
|
|||
'PhortuneSubscription' => 'applications/phortune/storage/PhortuneSubscription.php',
|
||||
'PhortuneSubscriptionAutopayTransaction' => 'applications/phortune/xaction/subscription/PhortuneSubscriptionAutopayTransaction.php',
|
||||
'PhortuneSubscriptionCart' => 'applications/phortune/cart/PhortuneSubscriptionCart.php',
|
||||
'PhortuneSubscriptionEditController' => 'applications/phortune/controller/subscription/PhortuneSubscriptionEditController.php',
|
||||
'PhortuneSubscriptionEditor' => 'applications/phortune/editor/PhortuneSubscriptionEditor.php',
|
||||
'PhortuneSubscriptionImplementation' => 'applications/phortune/subscription/PhortuneSubscriptionImplementation.php',
|
||||
'PhortuneSubscriptionListController' => 'applications/phortune/controller/subscription/PhortuneSubscriptionListController.php',
|
||||
'PhortuneSubscriptionPHIDType' => 'applications/phortune/phid/PhortuneSubscriptionPHIDType.php',
|
||||
'PhortuneSubscriptionPolicyCodex' => 'applications/phortune/codex/PhortuneSubscriptionPolicyCodex.php',
|
||||
'PhortuneSubscriptionProduct' => 'applications/phortune/product/PhortuneSubscriptionProduct.php',
|
||||
|
@ -11861,6 +11860,7 @@ phutil_register_library_map(array(
|
|||
'PhortuneCartTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'PhortuneCartUpdateController' => 'PhortuneCartController',
|
||||
'PhortuneCartViewController' => 'PhortuneCartController',
|
||||
'PhortuneCartVoidController' => 'PhortuneCartController',
|
||||
'PhortuneCharge' => array(
|
||||
'PhortuneDAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
|
@ -11984,10 +11984,8 @@ phutil_register_library_map(array(
|
|||
),
|
||||
'PhortuneSubscriptionAutopayTransaction' => 'PhortuneSubscriptionTransactionType',
|
||||
'PhortuneSubscriptionCart' => 'PhortuneCartImplementation',
|
||||
'PhortuneSubscriptionEditController' => 'PhortuneController',
|
||||
'PhortuneSubscriptionEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'PhortuneSubscriptionImplementation' => 'Phobject',
|
||||
'PhortuneSubscriptionListController' => 'PhortuneController',
|
||||
'PhortuneSubscriptionPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhortuneSubscriptionPolicyCodex' => 'PhabricatorPolicyCodex',
|
||||
'PhortuneSubscriptionProduct' => 'PhortuneProductImplementation',
|
||||
|
|
|
@ -43,6 +43,8 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
|
|||
'checkout/' => 'PhortuneCartCheckoutController',
|
||||
'(?P<action>print)/' => 'PhortuneCartViewController',
|
||||
'(?P<action>cancel|refund)/' => 'PhortuneCartCancelController',
|
||||
'accept/' => 'PhortuneCartAcceptController',
|
||||
'void/' => 'PhortuneCartVoidController',
|
||||
'update/' => 'PhortuneCartUpdateController',
|
||||
),
|
||||
'account/' => array(
|
||||
|
|
|
@ -2,42 +2,6 @@
|
|||
|
||||
abstract class PhortuneController extends PhabricatorController {
|
||||
|
||||
protected function addAccountCrumb(
|
||||
$crumbs,
|
||||
PhortuneAccount $account,
|
||||
$link = true) {
|
||||
|
||||
$name = $account->getName();
|
||||
$href = null;
|
||||
|
||||
if ($link) {
|
||||
$href = $this->getApplicationURI($account->getID().'/');
|
||||
$crumbs->addTextCrumb($name, $href);
|
||||
} else {
|
||||
$crumbs->addTextCrumb($name);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addMerchantCrumb(
|
||||
$crumbs,
|
||||
PhortuneMerchant $merchant,
|
||||
$link = true) {
|
||||
|
||||
$name = $merchant->getName();
|
||||
$href = null;
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Merchants'),
|
||||
$this->getApplicationURI('merchant/'));
|
||||
|
||||
if ($link) {
|
||||
$href = $this->getApplicationURI('merchant/'.$merchant->getID().'/');
|
||||
$crumbs->addTextCrumb($name, $href);
|
||||
} else {
|
||||
$crumbs->addTextCrumb($name);
|
||||
}
|
||||
}
|
||||
|
||||
private function loadEnabledProvidersForMerchant(PhortuneMerchant $merchant) {
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
|
||||
|
@ -84,30 +48,4 @@ abstract class PhortuneController extends PhabricatorController {
|
|||
return $providers;
|
||||
}
|
||||
|
||||
protected function loadMerchantAuthority() {
|
||||
$request = $this->getRequest();
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$is_merchant = (bool)$request->getURIData('merchantID');
|
||||
if (!$is_merchant) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$merchant = id(new PhortuneMerchantQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($request->getURIData('merchantID')))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$merchant) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$viewer->grantAuthority($merchant);
|
||||
return $merchant;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ final class PhortuneAccountChargesController
|
|||
$title = $account->getName();
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb(pht('Order History'))
|
||||
->addTextCrumb(pht('Orders'))
|
||||
->setBorder(true);
|
||||
|
||||
$header = $this->buildHeaderView();
|
||||
|
@ -46,22 +46,11 @@ final class PhortuneAccountChargesController
|
|||
->setLimit(100)
|
||||
->execute();
|
||||
|
||||
$phids = array();
|
||||
foreach ($charges as $charge) {
|
||||
$phids[] = $charge->getProviderPHID();
|
||||
$phids[] = $charge->getCartPHID();
|
||||
$phids[] = $charge->getMerchantPHID();
|
||||
$phids[] = $charge->getPaymentMethodPHID();
|
||||
}
|
||||
|
||||
$handles = $this->loadViewerHandles($phids);
|
||||
|
||||
$charges_uri = $account->getChargeListURI();
|
||||
|
||||
$table = id(new PhortuneChargeTableView())
|
||||
->setUser($viewer)
|
||||
->setCharges($charges)
|
||||
->setHandles($handles);
|
||||
->setCharges($charges);
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Recent Charges'))
|
||||
|
|
|
@ -12,7 +12,7 @@ final class PhortuneAccountOrdersController
|
|||
$title = $account->getName();
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb(pht('Order History'))
|
||||
->addTextCrumb(pht('Orders'))
|
||||
->setBorder(true);
|
||||
|
||||
$header = $this->buildHeaderView();
|
||||
|
|
|
@ -66,13 +66,13 @@ abstract class PhortuneAccountProfileController
|
|||
|
||||
$nav->addFilter(
|
||||
'orders',
|
||||
pht('Order History'),
|
||||
pht('Orders'),
|
||||
$account->getOrdersURI(),
|
||||
'fa-shopping-bag');
|
||||
|
||||
$nav->addFilter(
|
||||
'charges',
|
||||
pht('Charge History'),
|
||||
pht('Charges'),
|
||||
$account->getChargesURI(),
|
||||
'fa-calculator');
|
||||
|
||||
|
|
|
@ -3,27 +3,19 @@
|
|||
final class PhortuneCartAcceptController
|
||||
extends PhortuneCartController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
protected function shouldRequireAccountAuthority() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function shouldRequireMerchantAuthority() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function handleCartRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$id = $request->getURIData('id');
|
||||
$cart = $this->getCart();
|
||||
|
||||
// You must control the merchant to accept orders.
|
||||
$authority = $this->loadMerchantAuthority();
|
||||
if (!$authority) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$cart = id(new PhortuneCartQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->withMerchantPHIDs(array($authority->getPHID()))
|
||||
->needPurchases(true)
|
||||
->executeOne();
|
||||
if (!$cart) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$cancel_uri = $cart->getDetailURI($authority);
|
||||
$cancel_uri = $cart->getDetailURI();
|
||||
|
||||
if ($cart->getStatus() !== PhortuneCart::STATUS_REVIEW) {
|
||||
return $this->newDialog()
|
||||
|
|
|
@ -3,26 +3,21 @@
|
|||
final class PhortuneCartCancelController
|
||||
extends PhortuneCartController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
protected function shouldRequireAccountAuthority() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function shouldRequireMerchantAuthority() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function handleCartRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$id = $request->getURIData('id');
|
||||
$action = $request->getURIData('action');
|
||||
|
||||
$authority = $this->loadMerchantAuthority();
|
||||
|
||||
$cart_query = id(new PhortuneCartQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->needPurchases(true);
|
||||
|
||||
if ($authority) {
|
||||
$cart_query->withMerchantPHIDs(array($authority->getPHID()));
|
||||
}
|
||||
|
||||
$cart = $cart_query->executeOne();
|
||||
if (!$cart) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$cart = $this->getCart();
|
||||
$authority = $this->getMerchantAuthority();
|
||||
|
||||
switch ($action) {
|
||||
case 'cancel':
|
||||
|
@ -45,7 +40,7 @@ final class PhortuneCartCancelController
|
|||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$cancel_uri = $cart->getDetailURI($authority);
|
||||
$cancel_uri = $cart->getDetailURI();
|
||||
$merchant = $cart->getMerchant();
|
||||
|
||||
try {
|
||||
|
@ -60,7 +55,7 @@ final class PhortuneCartCancelController
|
|||
return $this->newDialog()
|
||||
->setTitle($title)
|
||||
->appendChild($ex->getMessage())
|
||||
->addCancelButton($cancel_uri);
|
||||
->addCancelButton($cancel_uri, pht('Rats'));
|
||||
}
|
||||
|
||||
$charges = id(new PhortuneChargeQuery())
|
||||
|
|
|
@ -3,18 +3,17 @@
|
|||
final class PhortuneCartCheckoutController
|
||||
extends PhortuneCartController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$id = $request->getURIData('id');
|
||||
protected function shouldRequireAccountAuthority() {
|
||||
return true;
|
||||
}
|
||||
|
||||
$cart = id(new PhortuneCartQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->needPurchases(true)
|
||||
->executeOne();
|
||||
if (!$cart) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
protected function shouldRequireMerchantAuthority() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function handleCartRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$cart = $this->getCart();
|
||||
|
||||
$cancel_uri = $cart->getCancelURI();
|
||||
$merchant = $cart->getMerchant();
|
||||
|
@ -139,7 +138,10 @@ final class PhortuneCartCheckoutController
|
|||
'cartID' => $cart->getID(),
|
||||
);
|
||||
|
||||
$payment_method_uri = $this->getApplicationURI("{$account_id}/card/new/");
|
||||
$payment_method_uri = urisprintf(
|
||||
'account/%d/methods/new/',
|
||||
$account->getID());
|
||||
$payment_method_uri = $this->getApplicationURI($payment_method_uri);
|
||||
$payment_method_uri = new PhutilURI($payment_method_uri, $params);
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
|
|
|
@ -3,6 +3,77 @@
|
|||
abstract class PhortuneCartController
|
||||
extends PhortuneController {
|
||||
|
||||
private $cart;
|
||||
private $merchantAuthority;
|
||||
|
||||
abstract protected function shouldRequireAccountAuthority();
|
||||
abstract protected function shouldRequireMerchantAuthority();
|
||||
abstract protected function handleCartRequest(AphrontRequest $request);
|
||||
|
||||
final public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
if ($this->shouldRequireAccountAuthority()) {
|
||||
$capabilities = array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
);
|
||||
} else {
|
||||
$capabilities = array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
);
|
||||
}
|
||||
|
||||
$cart = id(new PhortuneCartQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($request->getURIData('id')))
|
||||
->needPurchases(true)
|
||||
->requireCapabilities($capabilities)
|
||||
->executeOne();
|
||||
if (!$cart) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
if ($this->shouldRequireMerchantAuthority()) {
|
||||
PhabricatorPolicyFilter::requireCapability(
|
||||
$viewer,
|
||||
$cart->getMerchant(),
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
}
|
||||
|
||||
$this->cart = $cart;
|
||||
|
||||
$can_edit = PhortuneMerchantQuery::canViewersEditMerchants(
|
||||
array($viewer->getPHID()),
|
||||
array($cart->getMerchantPHID()));
|
||||
if ($can_edit) {
|
||||
$this->merchantAuthority = $cart->getMerchant();
|
||||
} else {
|
||||
$this->merchantAuthority = null;
|
||||
}
|
||||
|
||||
return $this->handleCartRequest($request);
|
||||
}
|
||||
|
||||
final protected function getCart() {
|
||||
return $this->cart;
|
||||
}
|
||||
|
||||
final protected function getMerchantAuthority() {
|
||||
return $this->merchantAuthority;
|
||||
}
|
||||
|
||||
final protected function hasMerchantAuthority() {
|
||||
return (bool)$this->merchantAuthority;
|
||||
}
|
||||
|
||||
final protected function hasAccountAuthority() {
|
||||
return (bool)PhabricatorPolicyFilter::hasCapability(
|
||||
$this->getViewer(),
|
||||
$this->getCart(),
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
}
|
||||
|
||||
protected function buildCartContentTable(PhortuneCart $cart) {
|
||||
|
||||
$rows = array();
|
||||
|
|
|
@ -3,25 +3,20 @@
|
|||
final class PhortuneCartUpdateController
|
||||
extends PhortuneCartController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
protected function shouldRequireAccountAuthority() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function shouldRequireMerchantAuthority() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function handleCartRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$id = $request->getURIData('id');
|
||||
|
||||
$authority = $this->loadMerchantAuthority();
|
||||
|
||||
$cart_query = id(new PhortuneCartQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->needPurchases(true);
|
||||
|
||||
if ($authority) {
|
||||
$cart_query->withMerchantPHIDs(array($authority->getPHID()));
|
||||
}
|
||||
|
||||
$cart = $cart_query->executeOne();
|
||||
if (!$cart) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$cart = $this->getCart();
|
||||
$authority = $this->getMerchantAuthority();
|
||||
|
||||
$charges = id(new PhortuneChargeQuery())
|
||||
->setViewer($viewer)
|
||||
|
@ -60,7 +55,7 @@ final class PhortuneCartUpdateController
|
|||
}
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($cart->getDetailURI($authority));
|
||||
->setURI($cart->getDetailURI());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,62 +5,33 @@ final class PhortuneCartViewController
|
|||
|
||||
private $action = null;
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
protected function shouldRequireAccountAuthority() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function shouldRequireMerchantAuthority() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function handleCartRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$id = $request->getURIData('id');
|
||||
$cart = $this->getCart();
|
||||
$authority = $this->getMerchantAuthority();
|
||||
$can_edit = $this->hasAccountAuthority();
|
||||
|
||||
$this->action = $request->getURIData('action');
|
||||
|
||||
$authority = $this->loadMerchantAuthority();
|
||||
require_celerity_resource('phortune-css');
|
||||
|
||||
$query = id(new PhortuneCartQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->needPurchases(true);
|
||||
|
||||
if ($authority) {
|
||||
$query->withMerchantPHIDs(array($authority->getPHID()));
|
||||
}
|
||||
|
||||
$cart = $query->executeOne();
|
||||
if (!$cart) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$cart_table = $this->buildCartContentTable($cart);
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$cart,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$errors = array();
|
||||
$error_view = null;
|
||||
$resume_uri = null;
|
||||
switch ($cart->getStatus()) {
|
||||
case PhortuneCart::STATUS_READY:
|
||||
if ($authority && $cart->getIsInvoice()) {
|
||||
// We arrived here by following the ad-hoc invoice workflow, and
|
||||
// are acting with merchant authority.
|
||||
|
||||
$checkout_uri = PhabricatorEnv::getURI($cart->getCheckoutURI());
|
||||
|
||||
$invoice_message = array(
|
||||
pht(
|
||||
'Manual invoices do not automatically notify recipients yet. '.
|
||||
'Send the payer this checkout link:'),
|
||||
' ',
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $checkout_uri,
|
||||
),
|
||||
$checkout_uri),
|
||||
);
|
||||
|
||||
if ($cart->getIsInvoice()) {
|
||||
$error_view = id(new PHUIInfoView())
|
||||
->setSeverity(PHUIInfoView::SEVERITY_WARNING)
|
||||
->setErrors(array($invoice_message));
|
||||
->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
|
||||
->appendChild(pht('This invoice is ready for payment.'));
|
||||
}
|
||||
break;
|
||||
case PhortuneCart::STATUS_PURCHASING:
|
||||
|
@ -133,7 +104,7 @@ final class PhortuneCartViewController
|
|||
$header = id(new PHUIHeaderView())
|
||||
->setUser($viewer)
|
||||
->setHeader($cart->getName())
|
||||
->setHeaderIcon('fa-shopping-cart');
|
||||
->setHeaderIcon('fa-shopping-bag');
|
||||
|
||||
if ($cart->getStatus() == PhortuneCart::STATUS_PURCHASED) {
|
||||
$done_uri = $cart->getDoneURI();
|
||||
|
@ -160,18 +131,8 @@ final class PhortuneCartViewController
|
|||
->needCarts(true)
|
||||
->execute();
|
||||
|
||||
$phids = array();
|
||||
foreach ($charges as $charge) {
|
||||
$phids[] = $charge->getProviderPHID();
|
||||
$phids[] = $charge->getCartPHID();
|
||||
$phids[] = $charge->getMerchantPHID();
|
||||
$phids[] = $charge->getPaymentMethodPHID();
|
||||
}
|
||||
$handles = $this->loadViewerHandles($phids);
|
||||
|
||||
$charges_table = id(new PhortuneChargeTableView())
|
||||
->setUser($viewer)
|
||||
->setHandles($handles)
|
||||
->setCharges($charges)
|
||||
->setShowOrder(false);
|
||||
|
||||
|
@ -182,14 +143,13 @@ final class PhortuneCartViewController
|
|||
|
||||
$account = $cart->getAccount();
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
if ($authority) {
|
||||
$this->addMerchantCrumb($crumbs, $authority);
|
||||
} else {
|
||||
$this->addAccountCrumb($crumbs, $cart->getAccount());
|
||||
}
|
||||
$crumbs->addTextCrumb(pht('Cart %d', $cart->getID()));
|
||||
$crumbs->setBorder(true);
|
||||
$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';
|
||||
|
@ -267,6 +227,7 @@ final class PhortuneCartViewController
|
|||
if ($crumbs) {
|
||||
$page->setCrumbs($crumbs);
|
||||
}
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
|
@ -318,20 +279,31 @@ final class PhortuneCartViewController
|
|||
$viewer = $this->getViewer();
|
||||
$id = $cart->getID();
|
||||
$curtain = $this->newCurtainView($cart);
|
||||
$status = $cart->getStatus();
|
||||
|
||||
$is_ready = ($status === PhortuneCart::STATUS_READY);
|
||||
|
||||
$can_cancel = ($can_edit && $cart->canCancelOrder());
|
||||
$can_checkout = ($can_edit && $is_ready);
|
||||
$can_accept = ($status === PhortuneCart::STATUS_REVIEW);
|
||||
$can_refund = ($authority && $cart->canRefundOrder());
|
||||
$can_void = ($authority && $cart->canVoidOrder());
|
||||
|
||||
if ($authority) {
|
||||
$prefix = 'merchant/'.$authority->getID().'/';
|
||||
} else {
|
||||
$prefix = '';
|
||||
}
|
||||
$cancel_uri = $this->getApplicationURI("cart/{$id}/cancel/");
|
||||
$refund_uri = $this->getApplicationURI("cart/{$id}/refund/");
|
||||
$update_uri = $this->getApplicationURI("cart/{$id}/update/");
|
||||
$accept_uri = $this->getApplicationURI("cart/{$id}/accept/");
|
||||
$print_uri = $this->getApplicationURI("cart/{$id}/print/");
|
||||
$checkout_uri = $cart->getCheckoutURI();
|
||||
$void_uri = $this->getApplicationURI("cart/{$id}/void/");
|
||||
|
||||
$cancel_uri = $this->getApplicationURI("{$prefix}cart/{$id}/cancel/");
|
||||
$refund_uri = $this->getApplicationURI("{$prefix}cart/{$id}/refund/");
|
||||
$update_uri = $this->getApplicationURI("{$prefix}cart/{$id}/update/");
|
||||
$accept_uri = $this->getApplicationURI("{$prefix}cart/{$id}/accept/");
|
||||
$print_uri = $this->getApplicationURI("{$prefix}cart/{$id}/print/");
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Pay Now'))
|
||||
->setIcon('fa-credit-card')
|
||||
->setDisabled(!$can_checkout)
|
||||
->setWorkflow(!$can_checkout)
|
||||
->setHref($checkout_uri));
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
|
@ -341,24 +313,6 @@ final class PhortuneCartViewController
|
|||
->setWorkflow(true)
|
||||
->setHref($cancel_uri));
|
||||
|
||||
if ($authority) {
|
||||
if ($cart->getStatus() == PhortuneCart::STATUS_REVIEW) {
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Accept Order'))
|
||||
->setIcon('fa-check')
|
||||
->setWorkflow(true)
|
||||
->setHref($accept_uri));
|
||||
}
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Refund Order'))
|
||||
->setIcon('fa-reply')
|
||||
->setWorkflow(true)
|
||||
->setHref($refund_uri));
|
||||
}
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Update Status'))
|
||||
|
@ -369,7 +323,7 @@ final class PhortuneCartViewController
|
|||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Continue Checkout'))
|
||||
->setIcon('fa-shopping-cart')
|
||||
->setIcon('fa-shopping-bag')
|
||||
->setHref($resume_uri));
|
||||
}
|
||||
|
||||
|
@ -380,6 +334,36 @@ final class PhortuneCartViewController
|
|||
->setOpenInNewWindow(true)
|
||||
->setIcon('fa-print'));
|
||||
|
||||
if ($authority) {
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setType(PhabricatorActionView::TYPE_DIVIDER));
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Accept Order'))
|
||||
->setIcon('fa-check')
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_accept)
|
||||
->setHref($accept_uri));
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Refund Order'))
|
||||
->setIcon('fa-reply')
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_refund)
|
||||
->setHref($refund_uri));
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Void Invoice'))
|
||||
->setIcon('fa-times')
|
||||
->setWorkflow(true)
|
||||
->setDisabled(!$can_void)
|
||||
->setHref($void_uri));
|
||||
}
|
||||
|
||||
return $curtain;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneCartVoidController
|
||||
extends PhortuneCartController {
|
||||
|
||||
protected function shouldRequireAccountAuthority() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function shouldRequireMerchantAuthority() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function handleCartRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$cart = $this->getCart();
|
||||
|
||||
$cancel_uri = $cart->getDetailURI();
|
||||
|
||||
try {
|
||||
$title = pht('Unable to Void Invoice');
|
||||
$cart->assertCanVoidOrder();
|
||||
} catch (Exception $ex) {
|
||||
return $this->newDialog()
|
||||
->setTitle($title)
|
||||
->appendChild($ex->getMessage())
|
||||
->addCancelButton($cancel_uri);
|
||||
}
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
return id(new AphrontRedirectResponse())->setURI($cancel_uri);
|
||||
}
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('Void Invoice?'))
|
||||
->appendParagraph(
|
||||
pht(
|
||||
'Really void this invoice? The customer will no longer be asked '.
|
||||
'to submit payment for it.'))
|
||||
->addCancelButton($cancel_uri)
|
||||
->addSubmitButton(pht('Void Invoice'));
|
||||
}
|
||||
}
|
|
@ -1,185 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneSubscriptionEditController extends PhortuneController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
$added = $request->getBool('added');
|
||||
|
||||
$subscription = id(new PhortuneSubscriptionQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($request->getURIData('id')))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$subscription) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
|
||||
$viewer,
|
||||
$request,
|
||||
$subscription->getURI());
|
||||
$merchant = $subscription->getMerchant();
|
||||
$account = $subscription->getAccount();
|
||||
|
||||
$title = pht('Subscription: %s', $subscription->getSubscriptionName());
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader($subscription->getSubscriptionName());
|
||||
|
||||
$view_uri = $subscription->getURI();
|
||||
|
||||
$valid_methods = id(new PhortunePaymentMethodQuery())
|
||||
->setViewer($viewer)
|
||||
->withAccountPHIDs(array($account->getPHID()))
|
||||
->withStatuses(
|
||||
array(
|
||||
PhortunePaymentMethod::STATUS_ACTIVE,
|
||||
))
|
||||
->withMerchantPHIDs(array($merchant->getPHID()))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->execute();
|
||||
$valid_methods = mpull($valid_methods, null, 'getPHID');
|
||||
|
||||
$current_phid = $subscription->getDefaultPaymentMethodPHID();
|
||||
|
||||
$e_method = null;
|
||||
if ($current_phid && empty($valid_methods[$current_phid])) {
|
||||
$e_method = pht('Needs Update');
|
||||
}
|
||||
|
||||
$errors = array();
|
||||
if ($request->isFormPost()) {
|
||||
|
||||
$default_method_phid = $request->getStr('defaultPaymentMethodPHID');
|
||||
if (!$default_method_phid) {
|
||||
$default_method_phid = null;
|
||||
$e_method = null;
|
||||
} else if (empty($valid_methods[$default_method_phid])) {
|
||||
$e_method = pht('Invalid');
|
||||
if ($default_method_phid == $current_phid) {
|
||||
$errors[] = pht(
|
||||
'This subscription is configured to autopay with a payment method '.
|
||||
'that has been deleted. Choose a valid payment method or disable '.
|
||||
'autopay.');
|
||||
} else {
|
||||
$errors[] = pht('You must select a valid default payment method.');
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: We should use transactions here, and move the validation logic
|
||||
// inside the Editor.
|
||||
|
||||
if (!$errors) {
|
||||
$subscription->setDefaultPaymentMethodPHID($default_method_phid);
|
||||
$subscription->save();
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($view_uri);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the option to disable autopay.
|
||||
$disable_options = array(
|
||||
'' => pht('(Disable Autopay)'),
|
||||
);
|
||||
|
||||
// Don't require the user to make a valid selection if the current method
|
||||
// has become invalid.
|
||||
if ($current_phid && empty($valid_methods[$current_phid])) {
|
||||
$current_options = array(
|
||||
$current_phid => pht('<Deleted Payment Method>'),
|
||||
);
|
||||
} else {
|
||||
$current_options = array();
|
||||
}
|
||||
|
||||
// Add any available options.
|
||||
$valid_options = mpull($valid_methods, 'getFullDisplayName', 'getPHID');
|
||||
|
||||
$options = $disable_options + $current_options + $valid_options;
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$this->addAccountCrumb($crumbs, $account);
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Subscription %d', $subscription->getID()),
|
||||
$view_uri);
|
||||
$crumbs->addTextCrumb(pht('Edit'));
|
||||
$crumbs->setBorder(true);
|
||||
|
||||
|
||||
$uri = $this->getApplicationURI($account->getID().'/card/new/');
|
||||
$uri = new PhutilURI($uri);
|
||||
$uri->replaceQueryParam('merchantID', $merchant->getID());
|
||||
$uri->replaceQueryParam('subscriptionID', $subscription->getID());
|
||||
|
||||
$add_method_button = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $uri,
|
||||
'class' => 'button button-grey',
|
||||
),
|
||||
pht('Add Payment Method...'));
|
||||
|
||||
$radio = id(new AphrontFormRadioButtonControl())
|
||||
->setName('defaultPaymentMethodPHID')
|
||||
->setLabel(pht('Autopay With'))
|
||||
->setValue($current_phid)
|
||||
->setError($e_method);
|
||||
|
||||
foreach ($options as $key => $value) {
|
||||
$radio->addButton($key, $value, null);
|
||||
}
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($viewer)
|
||||
->appendChild($radio)
|
||||
->appendChild(
|
||||
id(new AphrontFormMarkupControl())
|
||||
->setValue($add_method_button))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue(pht('Save Changes'))
|
||||
->addCancelButton($view_uri));
|
||||
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setUser($viewer)
|
||||
->setHeaderText(pht('Subscription'))
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->setFormErrors($errors)
|
||||
->appendChild($form);
|
||||
|
||||
if ($added) {
|
||||
$info_view = id(new PHUIInfoView())
|
||||
->setSeverity(PHUIInfoView::SEVERITY_SUCCESS)
|
||||
->appendChild(pht('Payment method has been successfully added.'));
|
||||
$box->setInfoView($info_view);
|
||||
}
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Edit %s', $subscription->getSubscriptionName()))
|
||||
->setHeaderIcon('fa-pencil');
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter(array(
|
||||
$box,
|
||||
));
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild($view);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneSubscriptionListController
|
||||
extends PhortuneController {
|
||||
|
||||
private $merchant;
|
||||
private $account;
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$querykey = $request->getURIData('queryKey');
|
||||
$merchant_id = $request->getURIData('merchantID');
|
||||
$account_id = $request->getURIData('accountID');
|
||||
|
||||
$engine = new PhortuneSubscriptionSearchEngine();
|
||||
|
||||
if ($merchant_id) {
|
||||
$merchant = id(new PhortuneMerchantQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($merchant_id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$merchant) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$this->merchant = $merchant;
|
||||
$viewer->grantAuthority($merchant);
|
||||
$engine->setMerchant($merchant);
|
||||
} else if ($account_id) {
|
||||
$account = id(new PhortuneAccountQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($account_id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$account) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$this->account = $account;
|
||||
$engine->setAccount($account);
|
||||
} else {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$controller = id(new PhabricatorApplicationSearchController())
|
||||
->setQueryKey($querykey)
|
||||
->setSearchEngine($engine)
|
||||
->setNavigation($this->buildSideNavView());
|
||||
|
||||
return $this->delegateToController($controller);
|
||||
}
|
||||
|
||||
public function buildSideNavView() {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$nav = new AphrontSideNavFilterView();
|
||||
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
|
||||
|
||||
id(new PhortuneSubscriptionSearchEngine())
|
||||
->setViewer($viewer)
|
||||
->addNavigationItems($nav->getMenu());
|
||||
|
||||
$nav->selectFilter(null);
|
||||
|
||||
return $nav;
|
||||
}
|
||||
|
||||
protected function buildApplicationCrumbs() {
|
||||
$crumbs = parent::buildApplicationCrumbs();
|
||||
|
||||
$merchant = $this->merchant;
|
||||
if ($merchant) {
|
||||
$id = $merchant->getID();
|
||||
$this->addMerchantCrumb($crumbs, $merchant);
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Subscriptions'),
|
||||
$this->getApplicationURI("merchant/subscriptions/{$id}/"));
|
||||
}
|
||||
|
||||
$account = $this->account;
|
||||
if ($account) {
|
||||
$id = $account->getID();
|
||||
$this->addAccountCrumb($crumbs, $account);
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Subscriptions'),
|
||||
$this->getApplicationURI("{$id}/subscription/"));
|
||||
}
|
||||
|
||||
return $crumbs;
|
||||
}
|
||||
|
||||
}
|
|
@ -105,7 +105,7 @@ final class PhortuneCartSearchEngine
|
|||
$merchant = $this->getMerchant();
|
||||
$account = $this->getAccount();
|
||||
if ($merchant) {
|
||||
return '/phortune/merchant/orders/'.$merchant->getID().'/'.$path;
|
||||
return $merchant->getOrderListURI($path);
|
||||
} else if ($account) {
|
||||
return $account->getOrderListURI($path);
|
||||
} else {
|
||||
|
|
|
@ -62,7 +62,7 @@ final class PhortuneChargeSearchEngine
|
|||
protected function getURI($path) {
|
||||
$account = $this->getAccount();
|
||||
if ($account) {
|
||||
return '/phortune/'.$account->getID().'/charge/';
|
||||
return $account->getChargeListURI($path);
|
||||
} else {
|
||||
return '/phortune/charge/'.$path;
|
||||
}
|
||||
|
@ -89,20 +89,6 @@ final class PhortuneChargeSearchEngine
|
|||
return parent::buildSavedQueryFromBuiltin($query_key);
|
||||
}
|
||||
|
||||
protected function getRequiredHandlePHIDsForResultList(
|
||||
array $charges,
|
||||
PhabricatorSavedQuery $query) {
|
||||
|
||||
$phids = array();
|
||||
foreach ($charges as $charge) {
|
||||
$phids[] = $charge->getProviderPHID();
|
||||
$phids[] = $charge->getCartPHID();
|
||||
$phids[] = $charge->getMerchantPHID();
|
||||
$phids[] = $charge->getPaymentMethodPHID();
|
||||
}
|
||||
|
||||
return $phids;
|
||||
}
|
||||
|
||||
protected function renderResultList(
|
||||
array $charges,
|
||||
|
@ -114,8 +100,7 @@ final class PhortuneChargeSearchEngine
|
|||
|
||||
$table = id(new PhortuneChargeTableView())
|
||||
->setUser($viewer)
|
||||
->setCharges($charges)
|
||||
->setHandles($handles);
|
||||
->setCharges($charges);
|
||||
|
||||
$result = new PhabricatorApplicationSearchResultView();
|
||||
$result->setTable($table);
|
||||
|
|
|
@ -96,9 +96,9 @@ final class PhortuneSubscriptionSearchEngine
|
|||
$merchant = $this->getMerchant();
|
||||
$account = $this->getAccount();
|
||||
if ($merchant) {
|
||||
return '/phortune/merchant/'.$merchant->getID().'/subscription/'.$path;
|
||||
return $merchant->getSubscriptionListURI($path);
|
||||
} else if ($account) {
|
||||
return '/phortune/'.$account->getID().'/subscription/';
|
||||
return $account->getSubscriptionListURI($path);
|
||||
} else {
|
||||
return '/phortune/subscription/'.$path;
|
||||
}
|
||||
|
|
|
@ -471,13 +471,10 @@ final class PhortuneCart extends PhortuneDAO
|
|||
return $this->getImplementation()->getDescription($this);
|
||||
}
|
||||
|
||||
public function getDetailURI(PhortuneMerchant $authority = null) {
|
||||
if ($authority) {
|
||||
$prefix = 'merchant/'.$authority->getID().'/';
|
||||
} else {
|
||||
$prefix = '';
|
||||
}
|
||||
return '/phortune/'.$prefix.'cart/'.$this->getID().'/';
|
||||
public function getDetailURI() {
|
||||
return urisprintf(
|
||||
'/phortune/cart/%d/',
|
||||
$this->getID());
|
||||
}
|
||||
|
||||
public function getCheckoutURI() {
|
||||
|
@ -502,6 +499,15 @@ final class PhortuneCart extends PhortuneDAO
|
|||
}
|
||||
}
|
||||
|
||||
public function canVoidOrder() {
|
||||
try {
|
||||
$this->assertCanVoidOrder();
|
||||
return true;
|
||||
} catch (Exception $ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function assertCanCancelOrder() {
|
||||
switch ($this->getStatus()) {
|
||||
case self::STATUS_BUILDING:
|
||||
|
@ -534,6 +540,27 @@ final class PhortuneCart extends PhortuneDAO
|
|||
return $this->getImplementation()->assertCanRefundOrder($this);
|
||||
}
|
||||
|
||||
public function assertCanVoidOrder() {
|
||||
if (!$this->getIsInvoice()) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'This order can not be voided because it is not an invoice.'));
|
||||
}
|
||||
|
||||
switch ($this->getStatus()) {
|
||||
case self::STATUS_READY:
|
||||
break;
|
||||
default:
|
||||
throw new Exception(
|
||||
pht(
|
||||
'This order can not be voided because it is not ready for '.
|
||||
'payment.'));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_AUX_PHID => true,
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
final class PhortuneChargeTableView extends AphrontView {
|
||||
|
||||
private $charges;
|
||||
private $handles;
|
||||
private $showOrder;
|
||||
|
||||
public function setShowOrder($show_order) {
|
||||
|
@ -15,15 +14,6 @@ final class PhortuneChargeTableView extends AphrontView {
|
|||
return $this->showOrder;
|
||||
}
|
||||
|
||||
public function setHandles(array $handles) {
|
||||
$this->handles = $handles;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHandles() {
|
||||
return $this->handles;
|
||||
}
|
||||
|
||||
public function setCharges(array $charges) {
|
||||
$this->charges = $charges;
|
||||
return $this;
|
||||
|
@ -35,8 +25,17 @@ final class PhortuneChargeTableView extends AphrontView {
|
|||
|
||||
public function render() {
|
||||
$charges = $this->getCharges();
|
||||
$handles = $this->getHandles();
|
||||
$viewer = $this->getUser();
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$phids = array();
|
||||
foreach ($charges as $charge) {
|
||||
$phids[] = $charge->getCartPHID();
|
||||
$phids[] = $charge->getProviderPHID();
|
||||
$phids[] = $charge->getPaymentMethodPHID();
|
||||
$phids[] = $charge->getMerchantPHID();
|
||||
}
|
||||
|
||||
$handles = $viewer->loadHandles($phids);
|
||||
|
||||
$rows = array();
|
||||
foreach ($charges as $charge) {
|
||||
|
|
Loading…
Add table
Reference in a new issue