From a65244c4491840f187862b0479637334431229d7 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 30 Jan 2015 11:28:49 -0800 Subject: [PATCH] Build a very basic subscription detail page in Phortune Summary: Ref T6881. - Add a subscription detail page. Minor cosmetics: - Fix glyph, from "X" (old "X marks the spot" icon) to "diamond" (new gem icon). - Name the initial account "Default Account" instead of "Personal Account", since this seems more general. Test Plan: {F278623} And I got two full days to test that Jan 30/31 -> Feb 28 billing logic! Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T6881 Differential Revision: https://secure.phabricator.com/D11576 --- src/__phutil_library_map__.php | 2 + .../PhabricatorPhortuneApplication.php | 18 ++++-- .../PhortuneAccountViewController.php | 4 +- .../controller/PhortuneController.php | 22 ++++++- .../PhortuneMerchantViewController.php | 2 +- .../PhortuneSubscriptionListController.php | 8 +-- .../PhortuneSubscriptionViewController.php | 59 +++++++++++++++++++ .../query/PhortuneSubscriptionQuery.php | 25 ++++++++ .../PhortuneSubscriptionSearchEngine.php | 1 + .../phortune/storage/PhortuneAccount.php | 2 +- .../phortune/storage/PhortuneSubscription.php | 14 +++++ .../view/PhortuneSubscriptionTableView.php | 24 ++++++++ 12 files changed, 164 insertions(+), 17 deletions(-) create mode 100644 src/applications/phortune/controller/PhortuneSubscriptionViewController.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 69b36b9578..dc2a9df1b3 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2815,6 +2815,7 @@ phutil_register_library_map(array( 'PhortuneSubscriptionQuery' => 'applications/phortune/query/PhortuneSubscriptionQuery.php', 'PhortuneSubscriptionSearchEngine' => 'applications/phortune/query/PhortuneSubscriptionSearchEngine.php', 'PhortuneSubscriptionTableView' => 'applications/phortune/view/PhortuneSubscriptionTableView.php', + 'PhortuneSubscriptionViewController' => 'applications/phortune/controller/PhortuneSubscriptionViewController.php', 'PhortuneTestPaymentProvider' => 'applications/phortune/provider/PhortuneTestPaymentProvider.php', 'PhortuneWePayPaymentProvider' => 'applications/phortune/provider/PhortuneWePayPaymentProvider.php', 'PhragmentBrowseController' => 'applications/phragment/controller/PhragmentBrowseController.php', @@ -6168,6 +6169,7 @@ phutil_register_library_map(array( 'PhortuneSubscriptionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneSubscriptionSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhortuneSubscriptionTableView' => 'AphrontView', + 'PhortuneSubscriptionViewController' => 'PhortuneController', 'PhortuneTestPaymentProvider' => 'PhortunePaymentProvider', 'PhortuneWePayPaymentProvider' => 'PhortunePaymentProvider', 'PhragmentBrowseController' => 'PhragmentController', diff --git a/src/applications/phortune/application/PhabricatorPhortuneApplication.php b/src/applications/phortune/application/PhabricatorPhortuneApplication.php index c852f18b62..cf0f502ec6 100644 --- a/src/applications/phortune/application/PhabricatorPhortuneApplication.php +++ b/src/applications/phortune/application/PhabricatorPhortuneApplication.php @@ -23,7 +23,7 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication { } public function getTitleGlyph() { - return "\xE2\x9C\x98"; + return "\xE2\x97\x87"; } public function getApplicationGroup() { @@ -45,8 +45,12 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication { ), 'order/(?:query/(?P[^/]+)/)?' => 'PhortuneCartListController', - 'subscription/(?:query/(?P[^/]+)/)?' - => 'PhortuneSubscriptionListController', + 'subscription/' => array( + '(?:query/(?P[^/]+)/)?' + => 'PhortuneSubscriptionListController', + 'view/(?P\d+)/' + => 'PhortuneSubscriptionViewController', + ), 'charge/(?:query/(?P[^/]+)/)?' => 'PhortuneChargeListController', ), @@ -81,8 +85,12 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication { 'edit/(?:(?P\d+)/)?' => 'PhortuneMerchantEditController', 'orders/(?P\d+)/(?:query/(?P[^/]+)/)?' => 'PhortuneCartListController', - 'subscription/(?P\d+)/(?:query/(?P[^/]+)/)?' - => 'PhortuneSubscriptionListController', + '(?P\d+)/subscription/' => array( + '(?:query/(?P[^/]+)/)?' + => 'PhortuneSubscriptionListController', + 'view/(?P\d+)/' + => 'PhortuneSubscriptionViewController', + ), '(?P\d+)/' => 'PhortuneMerchantViewController', ), ), diff --git a/src/applications/phortune/controller/PhortuneAccountViewController.php b/src/applications/phortune/controller/PhortuneAccountViewController.php index 0bd99bd39b..c7f7877844 100644 --- a/src/applications/phortune/controller/PhortuneAccountViewController.php +++ b/src/applications/phortune/controller/PhortuneAccountViewController.php @@ -35,9 +35,7 @@ final class PhortuneAccountViewController extends PhortuneController { $title = $account->getName(); $crumbs = $this->buildApplicationCrumbs(); - $crumbs->addTextCrumb( - $account->getName(), - $request->getRequestURI()); + $this->addAccountCrumb($crumbs, $account, $link = false); $header = id(new PHUIHeaderView()) ->setHeader($title); diff --git a/src/applications/phortune/controller/PhortuneController.php b/src/applications/phortune/controller/PhortuneController.php index f8f85b4d83..2900a3e850 100644 --- a/src/applications/phortune/controller/PhortuneController.php +++ b/src/applications/phortune/controller/PhortuneController.php @@ -7,7 +7,7 @@ abstract class PhortuneController extends PhabricatorController { PhortuneAccount $account, $link = true) { - $name = pht('Account'); + $name = $account->getName(); $href = null; if ($link) { @@ -18,6 +18,26 @@ abstract class PhortuneController extends PhabricatorController { } } + 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(); diff --git a/src/applications/phortune/controller/PhortuneMerchantViewController.php b/src/applications/phortune/controller/PhortuneMerchantViewController.php index cd279084a9..2e1ccdb169 100644 --- a/src/applications/phortune/controller/PhortuneMerchantViewController.php +++ b/src/applications/phortune/controller/PhortuneMerchantViewController.php @@ -190,7 +190,7 @@ final class PhortuneMerchantViewController id(new PhabricatorActionView()) ->setName(pht('View Subscriptions')) ->setIcon('fa-moon-o') - ->setHref($this->getApplicationURI("merchant/subscription/{$id}/")) + ->setHref($this->getApplicationURI("merchant/{$id}/subscription/")) ->setDisabled(!$can_edit) ->setWorkflow(!$can_edit)); diff --git a/src/applications/phortune/controller/PhortuneSubscriptionListController.php b/src/applications/phortune/controller/PhortuneSubscriptionListController.php index 5adecac3b9..06fb1115a4 100644 --- a/src/applications/phortune/controller/PhortuneSubscriptionListController.php +++ b/src/applications/phortune/controller/PhortuneSubscriptionListController.php @@ -85,9 +85,7 @@ final class PhortuneSubscriptionListController $merchant = $this->merchant; if ($merchant) { $id = $merchant->getID(); - $crumbs->addTextCrumb( - $merchant->getName(), - $this->getApplicationURI("merchant/{$id}/")); + $this->addMerchantCrumb($crumbs, $merchant); $crumbs->addTextCrumb( pht('Subscriptions'), $this->getApplicationURI("merchant/subscriptions/{$id}/")); @@ -96,9 +94,7 @@ final class PhortuneSubscriptionListController $account = $this->account; if ($account) { $id = $account->getID(); - $crumbs->addTextCrumb( - $account->getName(), - $this->getApplicationURI("{$id}/")); + $this->addAccountCrumb($crumbs, $account); $crumbs->addTextCrumb( pht('Subscriptions'), $this->getApplicationURI("{$id}/subscription/")); diff --git a/src/applications/phortune/controller/PhortuneSubscriptionViewController.php b/src/applications/phortune/controller/PhortuneSubscriptionViewController.php new file mode 100644 index 0000000000..e396eb9339 --- /dev/null +++ b/src/applications/phortune/controller/PhortuneSubscriptionViewController.php @@ -0,0 +1,59 @@ +getViewer(); + + $subscription = id(new PhortuneSubscriptionQuery()) + ->setViewer($viewer) + ->withIDs(array($request->getURIData('id'))) + ->needTriggers(true) + ->executeOne(); + if (!$subscription) { + return new Aphront404Response(); + } + + $is_merchant = (bool)$request->getURIData('merchantID'); + + $title = pht('Subscription: %s', $subscription->getSubscriptionName()); + + $header = id(new PHUIHeaderView()) + ->setHeader($subscription->getSubscriptionName()); + + $actions = id(new PhabricatorActionListView()) + ->setUser($viewer) + ->setObjectURI($request->getRequestURI()); + + $crumbs = $this->buildApplicationCrumbs(); + if ($is_merchant) { + $this->addMerchantCrumb($crumbs, $subscription->getMerchant()); + } else { + $this->addAccountCrumb($crumbs, $subscription->getAccount()); + } + $crumbs->addTextCrumb(pht('Subscription %d', $subscription->getID())); + + $properties = id(new PHUIPropertyListView()) + ->setUser($viewer) + ->setActionList($actions); + + $next_invoice = $subscription->getTrigger()->getNextEventPrediction(); + $properties->addProperty( + pht('Next Invoice'), + phabricator_datetime($next_invoice, $viewer)); + + $object_box = id(new PHUIObjectBoxView()) + ->setHeader($header) + ->addPropertyList($properties); + + return $this->buildApplicationPage( + array( + $crumbs, + $object_box, + ), + array( + 'title' => $title, + )); + } + +} diff --git a/src/applications/phortune/query/PhortuneSubscriptionQuery.php b/src/applications/phortune/query/PhortuneSubscriptionQuery.php index 91c3f07034..b789030dca 100644 --- a/src/applications/phortune/query/PhortuneSubscriptionQuery.php +++ b/src/applications/phortune/query/PhortuneSubscriptionQuery.php @@ -9,6 +9,8 @@ final class PhortuneSubscriptionQuery private $merchantPHIDs; private $statuses; + private $needTriggers; + public function withIDs(array $ids) { $this->ids = $ids; return $this; @@ -34,6 +36,11 @@ final class PhortuneSubscriptionQuery return $this; } + public function needTriggers($need_triggers) { + $this->needTriggers = $need_triggers; + return $this; + } + protected function loadPage() { $table = new PhortuneSubscription(); $conn = $table->establishConnection('r'); @@ -102,6 +109,24 @@ final class PhortuneSubscriptionQuery $subscription->attachImplementation($implementation); } + if ($this->needTriggers) { + $trigger_phids = mpull($subscriptions, 'getTriggerPHID'); + $triggers = id(new PhabricatorWorkerTriggerQuery()) + ->setViewer($this->getViewer()) + ->withPHIDs($trigger_phids) + ->needEvents(true) + ->execute(); + $triggers = mpull($triggers, null, 'getPHID'); + foreach ($subscriptions as $key => $subscription) { + $trigger = idx($triggers, $subscription->getTriggerPHID()); + if (!$trigger) { + unset($subscriptions[$key]); + continue; + } + $subscription->attachTrigger($trigger); + } + } + return $subscriptions; } diff --git a/src/applications/phortune/query/PhortuneSubscriptionSearchEngine.php b/src/applications/phortune/query/PhortuneSubscriptionSearchEngine.php index 5baa6acc45..90ea7f82fa 100644 --- a/src/applications/phortune/query/PhortuneSubscriptionSearchEngine.php +++ b/src/applications/phortune/query/PhortuneSubscriptionSearchEngine.php @@ -144,6 +144,7 @@ final class PhortuneSubscriptionSearchEngine $merchant = $this->getMerchant(); if ($merchant) { $header = pht('Subscriptions for %s', $merchant->getName()); + $table->setIsMerchantView(true); } else { $header = pht('Your Subscriptions'); } diff --git a/src/applications/phortune/storage/PhortuneAccount.php b/src/applications/phortune/storage/PhortuneAccount.php index d57746ec85..c53aa002e0 100644 --- a/src/applications/phortune/storage/PhortuneAccount.php +++ b/src/applications/phortune/storage/PhortuneAccount.php @@ -32,7 +32,7 @@ final class PhortuneAccount extends PhortuneDAO $xactions = array(); $xactions[] = id(new PhortuneAccountTransaction()) ->setTransactionType(PhortuneAccountTransaction::TYPE_NAME) - ->setNewValue(pht('Personal Account')); + ->setNewValue(pht('Default Account')); $xactions[] = id(new PhortuneAccountTransaction()) ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) diff --git a/src/applications/phortune/storage/PhortuneSubscription.php b/src/applications/phortune/storage/PhortuneSubscription.php index 498ef2f9ea..7b1666260a 100644 --- a/src/applications/phortune/storage/PhortuneSubscription.php +++ b/src/applications/phortune/storage/PhortuneSubscription.php @@ -153,6 +153,7 @@ final class PhortuneSubscription extends PhortuneDAO ), )); + $trigger->setPHID($trigger_phid); $trigger->setAction($trigger_action); $trigger->save(); } @@ -165,6 +166,19 @@ final class PhortuneSubscription extends PhortuneDAO return $this->getImplementation()->getName($this); } + public function getURI() { + $account_id = $this->getAccount()->getID(); + $id = $this->getID(); + + return "/phortune/{$account_id}/subscription/view/{$id}/"; + } + + public function getMerchantURI() { + $merchant_id = $this->getMerchant()->getID(); + $id = $this->getID(); + return "/phortune/merchant/{$merchant_id}/subscription/view/{$id}/"; + } + /* -( PhabricatorPolicyInterface )----------------------------------------- */ diff --git a/src/applications/phortune/view/PhortuneSubscriptionTableView.php b/src/applications/phortune/view/PhortuneSubscriptionTableView.php index 39064dbb4c..e9a80a9dfb 100644 --- a/src/applications/phortune/view/PhortuneSubscriptionTableView.php +++ b/src/applications/phortune/view/PhortuneSubscriptionTableView.php @@ -4,6 +4,7 @@ final class PhortuneSubscriptionTableView extends AphrontView { private $subscriptions; private $handles; + private $isMerchantView; public function setHandles(array $handles) { $this->handles = $handles; @@ -23,6 +24,15 @@ final class PhortuneSubscriptionTableView extends AphrontView { return $this->subscriptions; } + public function setIsMerchantView($is_merchant_view) { + $this->isMerchantView = $is_merchant_view; + return $this; + } + + public function getIsMerchantView() { + return $this->isMerchantView; + } + public function render() { $subscriptions = $this->getSubscriptions(); $handles = $this->getHandles(); @@ -31,9 +41,21 @@ final class PhortuneSubscriptionTableView extends AphrontView { $rows = array(); $rowc = array(); foreach ($subscriptions as $subscription) { + if ($this->getIsMerchantView()) { + $uri = $subscription->getMerchantURI(); + } else { + $uri = $subscription->getURI(); + } + $subscription_link = $handles[$subscription->getPHID()]->renderLink(); $rows[] = array( $subscription->getID(), + phutil_tag( + 'a', + array( + 'href' => $uri, + ), + $subscription->getSubscriptionName()), phabricator_datetime($subscription->getDateCreated(), $viewer), ); } @@ -42,11 +64,13 @@ final class PhortuneSubscriptionTableView extends AphrontView { ->setHeaders( array( pht('ID'), + pht('Name'), pht('Created'), )) ->setColumnClasses( array( '', + 'wide', 'right', ));