From 01c99335fdd73979a1011b9468e22be7c08cde49 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 20 Apr 2015 10:05:44 -0700 Subject: [PATCH] Give Phortune carts a proper `isInvoice` flag Summary: See some earlier discussion in D11593: > One thing I'm vaguely thinking about is the possibilty that users may be able to invoice one another directly, eventually. For example, we might invoice a contracting client. > We might need an `isInvoice` flag eventually, but `subscriptionPHID` is a reasonable stand-in for now. This adds such a flag. Test Plan: - Generated an ad-hoc invoice and verified it showed up in the right place. - Used `bin/phortune invoice` to invoice a subscription and verified it worked correctly. - Paid an invoice and saw it leave "pending invoices" status. {F377029} Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D12480 --- resources/celerity/map.php | 47 ++++++++++--------- .../sql/autopatches/20150420.invoice.1.sql | 2 + .../sql/autopatches/20150420.invoice.2.sql | 2 + .../controller/PhortuneCartViewController.php | 2 +- ...hortuneMerchantInvoiceCreateController.php | 7 +-- .../phortune/query/PhortuneCartQuery.php | 4 +- .../phortune/storage/PhortuneCart.php | 3 ++ .../worker/PhortuneSubscriptionWorker.php | 6 ++- 8 files changed, 43 insertions(+), 30 deletions(-) create mode 100644 resources/sql/autopatches/20150420.invoice.1.sql create mode 100644 resources/sql/autopatches/20150420.invoice.2.sql diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 996a6d44d3..3d0e8814a0 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -7,8 +7,8 @@ */ return array( 'names' => array( - 'core.pkg.css' => 'bf29d341', - 'core.pkg.js' => 'a626d14c', + 'core.pkg.css' => '7d05ad2a', + 'core.pkg.js' => 'dfea788f', 'darkconsole.pkg.js' => '8ab24e01', 'differential.pkg.css' => '3500921f', 'differential.pkg.js' => 'c0506961', @@ -27,7 +27,7 @@ return array( 'rsrc/css/aphront/panel-view.css' => '8427b78d', 'rsrc/css/aphront/phabricator-nav-view.css' => '7aeaf435', 'rsrc/css/aphront/table-view.css' => '59e2c0f8', - 'rsrc/css/aphront/tokenizer.css' => 'c10c061e', + 'rsrc/css/aphront/tokenizer.css' => '86a13f7f', 'rsrc/css/aphront/tooltip.css' => '7672b60f', 'rsrc/css/aphront/two-column.css' => '16ab3ad2', 'rsrc/css/aphront/typeahead-browse.css' => 'efe293a0', @@ -147,7 +147,7 @@ return array( 'rsrc/css/phui/phui-remarkup-preview.css' => '19ad512b', 'rsrc/css/phui/phui-spacing.css' => '042804d6', 'rsrc/css/phui/phui-status.css' => '888cedb8', - 'rsrc/css/phui/phui-tag-view.css' => 'ea469f3a', + 'rsrc/css/phui/phui-tag-view.css' => '402691cc', 'rsrc/css/phui/phui-text.css' => 'cf019f54', 'rsrc/css/phui/phui-timeline-view.css' => 'b0fbc4d7', 'rsrc/css/phui/phui-workboard-view.css' => '3279cbbf', @@ -450,7 +450,7 @@ return array( 'rsrc/js/core/KeyboardShortcutManager.js' => 'c1700f6f', 'rsrc/js/core/MultirowRowManager.js' => 'b5d57730', 'rsrc/js/core/Notification.js' => '0c6946e7', - 'rsrc/js/core/Prefab.js' => 'b972bdcd', + 'rsrc/js/core/Prefab.js' => '6920d200', 'rsrc/js/core/ShapedRequest.js' => '7cbe244b', 'rsrc/js/core/TextAreaUtils.js' => '5c93c52c', 'rsrc/js/core/Title.js' => 'df5e11d2', @@ -510,7 +510,7 @@ return array( 'aphront-pager-view-css' => '2e3539af', 'aphront-panel-view-css' => '8427b78d', 'aphront-table-view-css' => '59e2c0f8', - 'aphront-tokenizer-control-css' => 'c10c061e', + 'aphront-tokenizer-control-css' => '86a13f7f', 'aphront-tooltip-css' => '7672b60f', 'aphront-two-column-view-css' => '16ab3ad2', 'aphront-typeahead-control-css' => '0e403212', @@ -744,7 +744,7 @@ return array( 'phabricator-notification-menu-css' => '3c9d8aa1', 'phabricator-object-selector-css' => '029a133d', 'phabricator-phtize' => 'd254d646', - 'phabricator-prefab' => 'b972bdcd', + 'phabricator-prefab' => '6920d200', 'phabricator-profile-css' => '1a20dcbf', 'phabricator-remarkup-css' => 'e10512ff', 'phabricator-search-results-css' => '15c71110', @@ -806,7 +806,7 @@ return array( 'phui-remarkup-preview-css' => '19ad512b', 'phui-spacing-css' => '042804d6', 'phui-status-list-view-css' => '888cedb8', - 'phui-tag-view-css' => 'ea469f3a', + 'phui-tag-view-css' => '402691cc', 'phui-text-css' => 'cf019f54', 'phui-timeline-view-css' => 'b0fbc4d7', 'phui-workboard-view-css' => '3279cbbf', @@ -1296,6 +1296,18 @@ return array( '6882e80a' => array( 'javelin-dom', ), + '6920d200' => array( + 'javelin-install', + 'javelin-util', + 'javelin-dom', + 'javelin-typeahead', + 'javelin-tokenizer', + 'javelin-typeahead-preloaded-source', + 'javelin-typeahead-ondemand-source', + 'javelin-dom', + 'javelin-stratcom', + 'javelin-util', + ), '69adf288' => array( 'javelin-install', ), @@ -1469,6 +1481,10 @@ return array( 'phabricator-tooltip', 'changeset-view-manager', ), + '86a13f7f' => array( + 'aphront-typeahead-control-css', + 'phui-tag-view-css', + ), '87cb6b51' => array( 'javelin-behavior', 'javelin-dom', @@ -1707,18 +1723,6 @@ return array( 'javelin-dom', 'javelin-util', ), - 'b972bdcd' => array( - 'javelin-install', - 'javelin-util', - 'javelin-dom', - 'javelin-typeahead', - 'javelin-tokenizer', - 'javelin-typeahead-preloaded-source', - 'javelin-typeahead-ondemand-source', - 'javelin-dom', - 'javelin-stratcom', - 'javelin-util', - ), 'bba9eedf' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1764,9 +1768,6 @@ return array( 'javelin-util', 'phabricator-shaped-request', ), - 'c10c061e' => array( - 'aphront-typeahead-control-css', - ), 'c1700f6f' => array( 'javelin-install', 'javelin-util', diff --git a/resources/sql/autopatches/20150420.invoice.1.sql b/resources/sql/autopatches/20150420.invoice.1.sql new file mode 100644 index 0000000000..3986b344ad --- /dev/null +++ b/resources/sql/autopatches/20150420.invoice.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_phortune.phortune_cart + ADD isInvoice BOOL NOT NULL; diff --git a/resources/sql/autopatches/20150420.invoice.2.sql b/resources/sql/autopatches/20150420.invoice.2.sql new file mode 100644 index 0000000000..dfbe39de46 --- /dev/null +++ b/resources/sql/autopatches/20150420.invoice.2.sql @@ -0,0 +1,2 @@ +UPDATE {$NAMESPACE}_phortune.phortune_cart + SET isInvoice = 1 WHERE subscriptionPHID IS NOT NULL; diff --git a/src/applications/phortune/controller/PhortuneCartViewController.php b/src/applications/phortune/controller/PhortuneCartViewController.php index a0bfd1779c..956196a3bb 100644 --- a/src/applications/phortune/controller/PhortuneCartViewController.php +++ b/src/applications/phortune/controller/PhortuneCartViewController.php @@ -41,7 +41,7 @@ final class PhortuneCartViewController $resume_uri = null; switch ($cart->getStatus()) { case PhortuneCart::STATUS_READY: - if ($authority && $request->getStr('invoice')) { + if ($authority && $cart->getIsInvoice()) { // We arrived here by following the ad-hoc invoice workflow, and // are acting with merchant authority. diff --git a/src/applications/phortune/controller/PhortuneMerchantInvoiceCreateController.php b/src/applications/phortune/controller/PhortuneMerchantInvoiceCreateController.php index 9fefdc5ae4..eeb376b3cf 100644 --- a/src/applications/phortune/controller/PhortuneMerchantInvoiceCreateController.php +++ b/src/applications/phortune/controller/PhortuneMerchantInvoiceCreateController.php @@ -167,13 +167,14 @@ final class PhortuneMerchantInvoiceCreateController ->setMetadataValue('adhoc.name', $v_name) ->save(); - // TODO: Actually mark these as invoices. Right now, there's no easy - // way to do that. + $cart + ->setIsInvoice(1) + ->save(); $cart->activateCart(); $cart_id = $cart->getID(); - $uri = "/merchant/{$merchant_id}/cart/{$cart_id}/?invoice=true"; + $uri = "/merchant/{$merchant_id}/cart/{$cart_id}/"; $uri = $this->getApplicationURI($uri); return id(new AphrontRedirectResponse())->setURI($uri); diff --git a/src/applications/phortune/query/PhortuneCartQuery.php b/src/applications/phortune/query/PhortuneCartQuery.php index e324d3f7c0..4897ad7f22 100644 --- a/src/applications/phortune/query/PhortuneCartQuery.php +++ b/src/applications/phortune/query/PhortuneCartQuery.php @@ -203,12 +203,12 @@ final class PhortuneCartQuery if ($this->invoices) { $where[] = qsprintf( $conn, - 'cart.status = %s AND cart.subscriptionPHID IS NOT NULL', + 'cart.status = %s AND cart.isInvoice = 1', PhortuneCart::STATUS_READY); } else { $where[] = qsprintf( $conn, - 'cart.status != %s OR cart.subscriptionPHID IS NULL', + 'cart.status != %s OR cart.isInvoice = 0', PhortuneCart::STATUS_READY); } } diff --git a/src/applications/phortune/storage/PhortuneCart.php b/src/applications/phortune/storage/PhortuneCart.php index 9cf7c51e0b..46d474cc93 100644 --- a/src/applications/phortune/storage/PhortuneCart.php +++ b/src/applications/phortune/storage/PhortuneCart.php @@ -21,6 +21,7 @@ final class PhortuneCart extends PhortuneDAO protected $status; protected $metadata = array(); protected $mailKey; + protected $isInvoice; private $account = self::ATTACHABLE; private $purchases = self::ATTACHABLE; @@ -35,6 +36,7 @@ final class PhortuneCart extends PhortuneDAO ->setAuthorPHID($actor->getPHID()) ->setStatus(self::STATUS_BUILDING) ->setAccountPHID($account->getPHID()) + ->setIsInvoice(0) ->attachAccount($account) ->setMerchantPHID($merchant->getPHID()) ->attachMerchant($merchant); @@ -531,6 +533,7 @@ final class PhortuneCart extends PhortuneDAO 'cartClass' => 'text128', 'mailKey' => 'bytes20', 'subscriptionPHID' => 'phid?', + 'isInvoice' => 'bool', ), self::CONFIG_KEY_SCHEMA => array( 'key_account' => array( diff --git a/src/applications/phortune/worker/PhortuneSubscriptionWorker.php b/src/applications/phortune/worker/PhortuneSubscriptionWorker.php index 23cab0386f..a3235d464f 100644 --- a/src/applications/phortune/worker/PhortuneSubscriptionWorker.php +++ b/src/applications/phortune/worker/PhortuneSubscriptionWorker.php @@ -59,7 +59,11 @@ final class PhortuneSubscriptionWorker extends PhabricatorWorker { ->setMetadataValue('epoch.end', $next_epoch) ->save(); - $cart->setSubscriptionPHID($subscription->getPHID()); + $cart + ->setSubscriptionPHID($subscription->getPHID()) + ->setIsInvoice(1) + ->save(); + $cart->activateCart(); try {