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
			
			
This commit is contained in:
		| @@ -2815,6 +2815,7 @@ phutil_register_library_map(array( | |||||||
|     'PhortuneSubscriptionQuery' => 'applications/phortune/query/PhortuneSubscriptionQuery.php', |     'PhortuneSubscriptionQuery' => 'applications/phortune/query/PhortuneSubscriptionQuery.php', | ||||||
|     'PhortuneSubscriptionSearchEngine' => 'applications/phortune/query/PhortuneSubscriptionSearchEngine.php', |     'PhortuneSubscriptionSearchEngine' => 'applications/phortune/query/PhortuneSubscriptionSearchEngine.php', | ||||||
|     'PhortuneSubscriptionTableView' => 'applications/phortune/view/PhortuneSubscriptionTableView.php', |     'PhortuneSubscriptionTableView' => 'applications/phortune/view/PhortuneSubscriptionTableView.php', | ||||||
|  |     'PhortuneSubscriptionViewController' => 'applications/phortune/controller/PhortuneSubscriptionViewController.php', | ||||||
|     'PhortuneTestPaymentProvider' => 'applications/phortune/provider/PhortuneTestPaymentProvider.php', |     'PhortuneTestPaymentProvider' => 'applications/phortune/provider/PhortuneTestPaymentProvider.php', | ||||||
|     'PhortuneWePayPaymentProvider' => 'applications/phortune/provider/PhortuneWePayPaymentProvider.php', |     'PhortuneWePayPaymentProvider' => 'applications/phortune/provider/PhortuneWePayPaymentProvider.php', | ||||||
|     'PhragmentBrowseController' => 'applications/phragment/controller/PhragmentBrowseController.php', |     'PhragmentBrowseController' => 'applications/phragment/controller/PhragmentBrowseController.php', | ||||||
| @@ -6168,6 +6169,7 @@ phutil_register_library_map(array( | |||||||
|     'PhortuneSubscriptionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', |     'PhortuneSubscriptionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||||
|     'PhortuneSubscriptionSearchEngine' => 'PhabricatorApplicationSearchEngine', |     'PhortuneSubscriptionSearchEngine' => 'PhabricatorApplicationSearchEngine', | ||||||
|     'PhortuneSubscriptionTableView' => 'AphrontView', |     'PhortuneSubscriptionTableView' => 'AphrontView', | ||||||
|  |     'PhortuneSubscriptionViewController' => 'PhortuneController', | ||||||
|     'PhortuneTestPaymentProvider' => 'PhortunePaymentProvider', |     'PhortuneTestPaymentProvider' => 'PhortunePaymentProvider', | ||||||
|     'PhortuneWePayPaymentProvider' => 'PhortunePaymentProvider', |     'PhortuneWePayPaymentProvider' => 'PhortunePaymentProvider', | ||||||
|     'PhragmentBrowseController' => 'PhragmentController', |     'PhragmentBrowseController' => 'PhragmentController', | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function getTitleGlyph() { |   public function getTitleGlyph() { | ||||||
|     return "\xE2\x9C\x98"; |     return "\xE2\x97\x87"; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function getApplicationGroup() { |   public function getApplicationGroup() { | ||||||
| @@ -45,8 +45,12 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication { | |||||||
|           ), |           ), | ||||||
|           'order/(?:query/(?P<queryKey>[^/]+)/)?' |           'order/(?:query/(?P<queryKey>[^/]+)/)?' | ||||||
|             => 'PhortuneCartListController', |             => 'PhortuneCartListController', | ||||||
|           'subscription/(?:query/(?P<queryKey>[^/]+)/)?' |           'subscription/' => array( | ||||||
|  |             '(?:query/(?P<queryKey>[^/]+)/)?' | ||||||
|               => 'PhortuneSubscriptionListController', |               => 'PhortuneSubscriptionListController', | ||||||
|  |             'view/(?P<id>\d+)/' | ||||||
|  |               => 'PhortuneSubscriptionViewController', | ||||||
|  |           ), | ||||||
|           'charge/(?:query/(?P<queryKey>[^/]+)/)?' |           'charge/(?:query/(?P<queryKey>[^/]+)/)?' | ||||||
|             => 'PhortuneChargeListController', |             => 'PhortuneChargeListController', | ||||||
|         ), |         ), | ||||||
| @@ -81,8 +85,12 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication { | |||||||
|           'edit/(?:(?P<id>\d+)/)?' => 'PhortuneMerchantEditController', |           'edit/(?:(?P<id>\d+)/)?' => 'PhortuneMerchantEditController', | ||||||
|           'orders/(?P<merchantID>\d+)/(?:query/(?P<queryKey>[^/]+)/)?' |           'orders/(?P<merchantID>\d+)/(?:query/(?P<queryKey>[^/]+)/)?' | ||||||
|             => 'PhortuneCartListController', |             => 'PhortuneCartListController', | ||||||
|           'subscription/(?P<merchantID>\d+)/(?:query/(?P<queryKey>[^/]+)/)?' |           '(?P<merchantID>\d+)/subscription/' => array( | ||||||
|  |             '(?:query/(?P<queryKey>[^/]+)/)?' | ||||||
|               => 'PhortuneSubscriptionListController', |               => 'PhortuneSubscriptionListController', | ||||||
|  |             'view/(?P<id>\d+)/' | ||||||
|  |               => 'PhortuneSubscriptionViewController', | ||||||
|  |           ), | ||||||
|           '(?P<id>\d+)/' => 'PhortuneMerchantViewController', |           '(?P<id>\d+)/' => 'PhortuneMerchantViewController', | ||||||
|         ), |         ), | ||||||
|       ), |       ), | ||||||
|   | |||||||
| @@ -35,9 +35,7 @@ final class PhortuneAccountViewController extends PhortuneController { | |||||||
|     $title = $account->getName(); |     $title = $account->getName(); | ||||||
|  |  | ||||||
|     $crumbs = $this->buildApplicationCrumbs(); |     $crumbs = $this->buildApplicationCrumbs(); | ||||||
|     $crumbs->addTextCrumb( |     $this->addAccountCrumb($crumbs, $account, $link = false); | ||||||
|       $account->getName(), |  | ||||||
|       $request->getRequestURI()); |  | ||||||
|  |  | ||||||
|     $header = id(new PHUIHeaderView()) |     $header = id(new PHUIHeaderView()) | ||||||
|       ->setHeader($title); |       ->setHeader($title); | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ abstract class PhortuneController extends PhabricatorController { | |||||||
|     PhortuneAccount $account, |     PhortuneAccount $account, | ||||||
|     $link = true) { |     $link = true) { | ||||||
|  |  | ||||||
|     $name = pht('Account'); |     $name = $account->getName(); | ||||||
|     $href = null; |     $href = null; | ||||||
|  |  | ||||||
|     if ($link) { |     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) { |   private function loadEnabledProvidersForMerchant(PhortuneMerchant $merchant) { | ||||||
|     $viewer = $this->getRequest()->getUser(); |     $viewer = $this->getRequest()->getUser(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -190,7 +190,7 @@ final class PhortuneMerchantViewController | |||||||
|       id(new PhabricatorActionView()) |       id(new PhabricatorActionView()) | ||||||
|         ->setName(pht('View Subscriptions')) |         ->setName(pht('View Subscriptions')) | ||||||
|         ->setIcon('fa-moon-o') |         ->setIcon('fa-moon-o') | ||||||
|         ->setHref($this->getApplicationURI("merchant/subscription/{$id}/")) |         ->setHref($this->getApplicationURI("merchant/{$id}/subscription/")) | ||||||
|         ->setDisabled(!$can_edit) |         ->setDisabled(!$can_edit) | ||||||
|         ->setWorkflow(!$can_edit)); |         ->setWorkflow(!$can_edit)); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -85,9 +85,7 @@ final class PhortuneSubscriptionListController | |||||||
|     $merchant = $this->merchant; |     $merchant = $this->merchant; | ||||||
|     if ($merchant) { |     if ($merchant) { | ||||||
|       $id = $merchant->getID(); |       $id = $merchant->getID(); | ||||||
|       $crumbs->addTextCrumb( |       $this->addMerchantCrumb($crumbs, $merchant); | ||||||
|         $merchant->getName(), |  | ||||||
|         $this->getApplicationURI("merchant/{$id}/")); |  | ||||||
|       $crumbs->addTextCrumb( |       $crumbs->addTextCrumb( | ||||||
|         pht('Subscriptions'), |         pht('Subscriptions'), | ||||||
|         $this->getApplicationURI("merchant/subscriptions/{$id}/")); |         $this->getApplicationURI("merchant/subscriptions/{$id}/")); | ||||||
| @@ -96,9 +94,7 @@ final class PhortuneSubscriptionListController | |||||||
|     $account = $this->account; |     $account = $this->account; | ||||||
|     if ($account) { |     if ($account) { | ||||||
|       $id = $account->getID(); |       $id = $account->getID(); | ||||||
|       $crumbs->addTextCrumb( |       $this->addAccountCrumb($crumbs, $account); | ||||||
|         $account->getName(), |  | ||||||
|         $this->getApplicationURI("{$id}/")); |  | ||||||
|       $crumbs->addTextCrumb( |       $crumbs->addTextCrumb( | ||||||
|         pht('Subscriptions'), |         pht('Subscriptions'), | ||||||
|         $this->getApplicationURI("{$id}/subscription/")); |         $this->getApplicationURI("{$id}/subscription/")); | ||||||
|   | |||||||
| @@ -0,0 +1,59 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | final class PhortuneSubscriptionViewController extends PhortuneController { | ||||||
|  |  | ||||||
|  |   public function handleRequest(AphrontRequest $request) { | ||||||
|  |     $viewer = $this->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, | ||||||
|  |       )); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -9,6 +9,8 @@ final class PhortuneSubscriptionQuery | |||||||
|   private $merchantPHIDs; |   private $merchantPHIDs; | ||||||
|   private $statuses; |   private $statuses; | ||||||
|  |  | ||||||
|  |   private $needTriggers; | ||||||
|  |  | ||||||
|   public function withIDs(array $ids) { |   public function withIDs(array $ids) { | ||||||
|     $this->ids = $ids; |     $this->ids = $ids; | ||||||
|     return $this; |     return $this; | ||||||
| @@ -34,6 +36,11 @@ final class PhortuneSubscriptionQuery | |||||||
|     return $this; |     return $this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public function needTriggers($need_triggers) { | ||||||
|  |     $this->needTriggers = $need_triggers; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   protected function loadPage() { |   protected function loadPage() { | ||||||
|     $table = new PhortuneSubscription(); |     $table = new PhortuneSubscription(); | ||||||
|     $conn = $table->establishConnection('r'); |     $conn = $table->establishConnection('r'); | ||||||
| @@ -102,6 +109,24 @@ final class PhortuneSubscriptionQuery | |||||||
|       $subscription->attachImplementation($implementation); |       $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; |     return $subscriptions; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -144,6 +144,7 @@ final class PhortuneSubscriptionSearchEngine | |||||||
|     $merchant = $this->getMerchant(); |     $merchant = $this->getMerchant(); | ||||||
|     if ($merchant) { |     if ($merchant) { | ||||||
|       $header = pht('Subscriptions for %s', $merchant->getName()); |       $header = pht('Subscriptions for %s', $merchant->getName()); | ||||||
|  |       $table->setIsMerchantView(true); | ||||||
|     } else { |     } else { | ||||||
|       $header = pht('Your Subscriptions'); |       $header = pht('Your Subscriptions'); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ final class PhortuneAccount extends PhortuneDAO | |||||||
|     $xactions = array(); |     $xactions = array(); | ||||||
|     $xactions[] = id(new PhortuneAccountTransaction()) |     $xactions[] = id(new PhortuneAccountTransaction()) | ||||||
|       ->setTransactionType(PhortuneAccountTransaction::TYPE_NAME) |       ->setTransactionType(PhortuneAccountTransaction::TYPE_NAME) | ||||||
|       ->setNewValue(pht('Personal Account')); |       ->setNewValue(pht('Default Account')); | ||||||
|  |  | ||||||
|     $xactions[] = id(new PhortuneAccountTransaction()) |     $xactions[] = id(new PhortuneAccountTransaction()) | ||||||
|       ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) |       ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) | ||||||
|   | |||||||
| @@ -153,6 +153,7 @@ final class PhortuneSubscription extends PhortuneDAO | |||||||
|             ), |             ), | ||||||
|           )); |           )); | ||||||
|  |  | ||||||
|  |         $trigger->setPHID($trigger_phid); | ||||||
|         $trigger->setAction($trigger_action); |         $trigger->setAction($trigger_action); | ||||||
|         $trigger->save(); |         $trigger->save(); | ||||||
|       } |       } | ||||||
| @@ -165,6 +166,19 @@ final class PhortuneSubscription extends PhortuneDAO | |||||||
|     return $this->getImplementation()->getName($this); |     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  )----------------------------------------- */ | /* -(  PhabricatorPolicyInterface  )----------------------------------------- */ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ final class PhortuneSubscriptionTableView extends AphrontView { | |||||||
|  |  | ||||||
|   private $subscriptions; |   private $subscriptions; | ||||||
|   private $handles; |   private $handles; | ||||||
|  |   private $isMerchantView; | ||||||
|  |  | ||||||
|   public function setHandles(array $handles) { |   public function setHandles(array $handles) { | ||||||
|     $this->handles = $handles; |     $this->handles = $handles; | ||||||
| @@ -23,6 +24,15 @@ final class PhortuneSubscriptionTableView extends AphrontView { | |||||||
|     return $this->subscriptions; |     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() { |   public function render() { | ||||||
|     $subscriptions = $this->getSubscriptions(); |     $subscriptions = $this->getSubscriptions(); | ||||||
|     $handles = $this->getHandles(); |     $handles = $this->getHandles(); | ||||||
| @@ -31,9 +41,21 @@ final class PhortuneSubscriptionTableView extends AphrontView { | |||||||
|     $rows = array(); |     $rows = array(); | ||||||
|     $rowc = array(); |     $rowc = array(); | ||||||
|     foreach ($subscriptions as $subscription) { |     foreach ($subscriptions as $subscription) { | ||||||
|  |       if ($this->getIsMerchantView()) { | ||||||
|  |         $uri = $subscription->getMerchantURI(); | ||||||
|  |       } else { | ||||||
|  |         $uri = $subscription->getURI(); | ||||||
|  |       } | ||||||
|  |  | ||||||
|       $subscription_link = $handles[$subscription->getPHID()]->renderLink(); |       $subscription_link = $handles[$subscription->getPHID()]->renderLink(); | ||||||
|       $rows[] = array( |       $rows[] = array( | ||||||
|         $subscription->getID(), |         $subscription->getID(), | ||||||
|  |         phutil_tag( | ||||||
|  |           'a', | ||||||
|  |           array( | ||||||
|  |             'href' => $uri, | ||||||
|  |           ), | ||||||
|  |           $subscription->getSubscriptionName()), | ||||||
|         phabricator_datetime($subscription->getDateCreated(), $viewer), |         phabricator_datetime($subscription->getDateCreated(), $viewer), | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
| @@ -42,11 +64,13 @@ final class PhortuneSubscriptionTableView extends AphrontView { | |||||||
|       ->setHeaders( |       ->setHeaders( | ||||||
|         array( |         array( | ||||||
|           pht('ID'), |           pht('ID'), | ||||||
|  |           pht('Name'), | ||||||
|           pht('Created'), |           pht('Created'), | ||||||
|         )) |         )) | ||||||
|       ->setColumnClasses( |       ->setColumnClasses( | ||||||
|         array( |         array( | ||||||
|           '', |           '', | ||||||
|  |           'wide', | ||||||
|           'right', |           'right', | ||||||
|         )); |         )); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 epriestley
					epriestley