1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-19 12:00:55 +01:00

Allow merchant controllers to review orders in Phortune

Summary: Ref T2787. Sets the stage for administrating / cancelling / refunding orders and hold orders.

Test Plan:
{F215140}

{F215141}

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T2787

Differential Revision: https://secure.phabricator.com/D10663
This commit is contained in:
epriestley 2014-10-08 14:40:02 -07:00
parent 19db3fbb60
commit b6c65719e4
10 changed files with 293 additions and 4 deletions

View file

@ -2557,8 +2557,10 @@ phutil_register_library_map(array(
'PhortuneCartCheckoutController' => 'applications/phortune/controller/PhortuneCartCheckoutController.php', 'PhortuneCartCheckoutController' => 'applications/phortune/controller/PhortuneCartCheckoutController.php',
'PhortuneCartController' => 'applications/phortune/controller/PhortuneCartController.php', 'PhortuneCartController' => 'applications/phortune/controller/PhortuneCartController.php',
'PhortuneCartImplementation' => 'applications/phortune/cart/PhortuneCartImplementation.php', 'PhortuneCartImplementation' => 'applications/phortune/cart/PhortuneCartImplementation.php',
'PhortuneCartListController' => 'applications/phortune/controller/PhortuneCartListController.php',
'PhortuneCartPHIDType' => 'applications/phortune/phid/PhortuneCartPHIDType.php', 'PhortuneCartPHIDType' => 'applications/phortune/phid/PhortuneCartPHIDType.php',
'PhortuneCartQuery' => 'applications/phortune/query/PhortuneCartQuery.php', 'PhortuneCartQuery' => 'applications/phortune/query/PhortuneCartQuery.php',
'PhortuneCartSearchEngine' => 'applications/phortune/query/PhortuneCartSearchEngine.php',
'PhortuneCartViewController' => 'applications/phortune/controller/PhortuneCartViewController.php', 'PhortuneCartViewController' => 'applications/phortune/controller/PhortuneCartViewController.php',
'PhortuneCharge' => 'applications/phortune/storage/PhortuneCharge.php', 'PhortuneCharge' => 'applications/phortune/storage/PhortuneCharge.php',
'PhortuneChargePHIDType' => 'applications/phortune/phid/PhortuneChargePHIDType.php', 'PhortuneChargePHIDType' => 'applications/phortune/phid/PhortuneChargePHIDType.php',
@ -5608,8 +5610,10 @@ phutil_register_library_map(array(
), ),
'PhortuneCartCheckoutController' => 'PhortuneCartController', 'PhortuneCartCheckoutController' => 'PhortuneCartController',
'PhortuneCartController' => 'PhortuneController', 'PhortuneCartController' => 'PhortuneController',
'PhortuneCartListController' => 'PhortuneController',
'PhortuneCartPHIDType' => 'PhabricatorPHIDType', 'PhortuneCartPHIDType' => 'PhabricatorPHIDType',
'PhortuneCartQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneCartQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhortuneCartSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhortuneCartViewController' => 'PhortuneCartController', 'PhortuneCartViewController' => 'PhortuneCartController',
'PhortuneCharge' => array( 'PhortuneCharge' => array(
'PhortuneDAO', 'PhortuneDAO',

View file

@ -23,7 +23,7 @@ final class FundBackerCart extends PhortuneCartImplementation {
return $this->initiative; return $this->initiative;
} }
public function getName() { public function getName(PhortuneCart $cart) {
return pht('Fund Initiative'); return pht('Fund Initiative');
} }

View file

@ -67,6 +67,8 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
'merchant/' => array( 'merchant/' => array(
'(?:query/(?P<queryKey>[^/]+)/)?' => 'PhortuneMerchantListController', '(?:query/(?P<queryKey>[^/]+)/)?' => 'PhortuneMerchantListController',
'edit/(?:(?P<id>\d+)/)?' => 'PhortuneMerchantEditController', 'edit/(?:(?P<id>\d+)/)?' => 'PhortuneMerchantEditController',
'orders/(?P<merchantID>\d+)/(?:query/(?P<querKey>[^/]+)/)?'
=> 'PhortuneCartListController',
'(?P<id>\d+)/' => 'PhortuneMerchantViewController', '(?P<id>\d+)/' => 'PhortuneMerchantViewController',
), ),
), ),

View file

@ -12,8 +12,7 @@ abstract class PhortuneCartImplementation {
PhabricatorUser $viewer, PhabricatorUser $viewer,
array $carts); array $carts);
abstract public function getName(); abstract public function getName(PhortuneCart $cart);
abstract public function getCancelURI(PhortuneCart $cart); abstract public function getCancelURI(PhortuneCart $cart);
abstract public function getDoneURI(PhortuneCart $cart); abstract public function getDoneURI(PhortuneCart $cart);

View file

@ -0,0 +1,79 @@
<?php
final class PhortuneCartListController
extends PhortuneController {
private $merchantID;
private $queryKey;
private $merchant;
public function willProcessRequest(array $data) {
$this->merchantID = idx($data, 'merchantID');
$this->queryKey = idx($data, 'queryKey');
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$engine = new PhortuneCartSearchEngine();
if ($this->merchantID) {
$merchant = id(new PhortuneMerchantQuery())
->setViewer($viewer)
->withIDs(array($this->merchantID))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$merchant) {
return new Aphront404Response();
}
$this->merchant = $merchant;
$engine->setMerchant($merchant);
}
$controller = id(new PhabricatorApplicationSearchController($request))
->setQueryKey($this->queryKey)
->setSearchEngine($engine)
->setNavigation($this->buildSideNavView());
return $this->delegateToController($controller);
}
public function buildSideNavView() {
$viewer = $this->getRequest()->getUser();
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
id(new PhortuneCartSearchEngine())
->setViewer($viewer)
->addNavigationItems($nav->getMenu());
$nav->selectFilter(null);
return $nav;
}
public function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$merchant = $this->merchant;
if ($merchant) {
$id = $merchant->getID();
$crumbs->addTextCrumb(
$merchant->getName(),
$this->getApplicationURI("merchant/{$id}/"));
$crumbs->addTextCrumb(
pht('Orders'),
$this->getApplicationURI("merchant/orders/{$id}/"));
}
return $crumbs;
}
}

View file

@ -177,6 +177,14 @@ final class PhortuneMerchantViewController
->setWorkflow(!$can_edit) ->setWorkflow(!$can_edit)
->setHref($this->getApplicationURI("merchant/edit/{$id}/"))); ->setHref($this->getApplicationURI("merchant/edit/{$id}/")));
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('View Orders'))
->setIcon('fa-shopping-cart')
->setHref($this->getApplicationURI("merchant/orders/{$id}/"))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
return $view; return $view;
} }

View file

@ -29,7 +29,7 @@ final class PhortuneCartPHIDType extends PhabricatorPHIDType {
$cart = $objects[$phid]; $cart = $objects[$phid];
$id = $cart->getID(); $id = $cart->getID();
$name = $cart->getImplementation()->getName(); $name = $cart->getName();
$handle->setName($name); $handle->setName($name);
$handle->setURI("/phortune/cart/{$id}/"); $handle->setURI("/phortune/cart/{$id}/");

View file

@ -6,6 +6,7 @@ final class PhortuneCartQuery
private $ids; private $ids;
private $phids; private $phids;
private $accountPHIDs; private $accountPHIDs;
private $merchantPHIDs;
private $statuses; private $statuses;
private $needPurchases; private $needPurchases;
@ -25,6 +26,11 @@ final class PhortuneCartQuery
return $this; return $this;
} }
public function withMerchantPHIDs(array $merchant_phids) {
$this->merchantPHIDs = $merchant_phids;
return $this;
}
public function withStatuses(array $statuses) { public function withStatuses(array $statuses) {
$this->statuses = $statuses; $this->statuses = $statuses;
return $this; return $this;
@ -145,6 +151,13 @@ final class PhortuneCartQuery
$this->accountPHIDs); $this->accountPHIDs);
} }
if ($this->merchantPHIDs !== null) {
$where[] = qsprintf(
$conn,
'cart.merchantPHID IN (%Ls)',
$this->merchantPHIDs);
}
if ($this->statuses !== null) { if ($this->statuses !== null) {
$where[] = qsprintf( $where[] = qsprintf(
$conn, $conn,

View file

@ -0,0 +1,167 @@
<?php
final class PhortuneCartSearchEngine
extends PhabricatorApplicationSearchEngine {
private $merchant;
public function setMerchant(PhortuneMerchant $merchant) {
$this->merchant = $merchant;
return $this;
}
public function getMerchant() {
return $this->merchant;
}
public function getResultTypeDescription() {
return pht('Phortune Orders');
}
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhortuneCartQuery())
->needPurchases(true)
->withStatuses(
array(
PhortuneCart::STATUS_PURCHASING,
PhortuneCart::STATUS_CHARGED,
PhortuneCart::STATUS_PURCHASED,
));
$viewer = $this->requireViewer();
$merchant = $this->getMerchant();
if ($merchant) {
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$merchant,
PhabricatorPolicyCapability::CAN_EDIT);
if (!$can_edit) {
throw new Exception(
pht('You can not query orders for a merchant you do not control.'));
}
$query->withMerchantPHIDs(array($merchant->getPHID()));
} else {
$accounts = id(new PhortuneAccountQuery())
->withMemberPHIDs($viewer->getPHID())
->execute();
if ($accounts) {
$query->withAccountPHIDs(mpull($accounts, 'getPHID'));
} else {
throw new Exception(pht('You have no accounts!'));
}
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved_query) {}
protected function getURI($path) {
$merchant = $this->getMerchant();
if ($merchant) {
return '/phortune/merchant/'.$merchant->getID().'/order/'.$path;
} else {
return '/phortune/order/'.$path;
}
}
public function getBuiltinQueryNames() {
$names = array(
'all' => pht('All Orders'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
protected function getRequiredHandlePHIDsForResultList(
array $carts,
PhabricatorSavedQuery $query) {
$phids = array();
foreach ($carts as $cart) {
$phids[] = $cart->getPHID();
$phids[] = $cart->getMerchantPHID();
$phids[] = $cart->getAuthorPHID();
}
return $phids;
}
protected function renderResultList(
array $carts,
PhabricatorSavedQuery $query,
array $handles) {
assert_instances_of($carts, 'PhortuneCart');
$viewer = $this->requireViewer();
$rows = array();
foreach ($carts as $cart) {
$merchant = $cart->getMerchant();
$rows[] = array(
$cart->getID(),
$handles[$cart->getPHID()]->renderLink(),
$handles[$merchant->getPHID()]->renderLink(),
$handles[$cart->getAuthorPHID()]->renderLink(),
$cart->getTotalPriceAsCurrency()->formatForDisplay(),
PhortuneCart::getNameForStatus($cart->getStatus()),
phabricator_datetime($cart->getDateModified(), $viewer),
);
}
$table = id(new AphrontTableView($rows))
->setNoDataString(pht('No orders match the query.'))
->setHeaders(
array(
pht('ID'),
pht('Order'),
pht('Merchant'),
pht('Authorized By'),
pht('Amount'),
pht('Status'),
pht('Updated'),
))
->setColumnClasses(
array(
'',
'pri',
'',
'',
'wide right',
'',
'right',
));
$merchant = $this->getMerchant();
if ($merchant) {
$header = pht('Orders for %s', $merchant->getName());
} else {
$header = pht('Your Orders');
}
return id(new PHUIObjectBoxView())
->setHeaderText($header)
->appendChild($table);
}
}

View file

@ -51,6 +51,20 @@ final class PhortuneCart extends PhortuneDAO
return $purchase; return $purchase;
} }
public static function getStatusNameMap() {
return array(
self::STATUS_BUILDING => pht('Building'),
self::STATUS_READY => pht('Ready'),
self::STATUS_PURCHASING => pht('Purchasing'),
self::STATUS_CHARGED => pht('Charged'),
self::STATUS_PURCHASED => pht('Purchased'),
);
}
public static function getNameForStatus($status) {
return idx(self::getStatusNameMap(), $status, $status);
}
public function activateCart() { public function activateCart() {
$this->setStatus(self::STATUS_READY)->save(); $this->setStatus(self::STATUS_READY)->save();
return $this; return $this;
@ -128,6 +142,9 @@ final class PhortuneCart extends PhortuneDAO
return $this; return $this;
} }
public function getName() {
return $this->getImplementation()->getName($this);
}
public function getDoneURI() { public function getDoneURI() {
return $this->getImplementation()->getDoneURI($this); return $this->getImplementation()->getDoneURI($this);