@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Make Fund transactions more informative and complete

Summary: Ref T5835. Show backing amounts in transactions. Account for and show refunds.

Test Plan: {F215869}

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T5835

Differential Revision: https://secure.phabricator.com/D10676

+125 -36
+2 -1
src/applications/fund/controller/FundInitiativeViewController.php
··· 63 63 $timeline = id(new PhabricatorApplicationTransactionView()) 64 64 ->setUser($viewer) 65 65 ->setObjectPHID($initiative->getPHID()) 66 - ->setTransactions($xactions); 66 + ->setTransactions($xactions) 67 + ->setShouldTerminate(true); 67 68 68 69 return $this->buildApplicationPage( 69 70 array(
+8
src/applications/fund/editor/FundBackerEditor.php
··· 13 13 14 14 public function getTransactionTypes() { 15 15 $types = parent::getTransactionTypes(); 16 + 16 17 $types[] = FundBackerTransaction::TYPE_STATUS; 18 + $types[] = FundBackerTransaction::TYPE_REFUND; 17 19 18 20 return $types; 19 21 } ··· 24 26 switch ($xaction->getTransactionType()) { 25 27 case FundBackerTransaction::TYPE_STATUS: 26 28 return $object->getStatus(); 29 + case FundBackerTransaction::TYPE_REFUND: 30 + return null; 27 31 } 28 32 29 33 return parent::getCustomTransactionOldValue($object, $xaction); ··· 35 39 36 40 switch ($xaction->getTransactionType()) { 37 41 case FundBackerTransaction::TYPE_STATUS: 42 + case FundBackerTransaction::TYPE_REFUND: 38 43 return $xaction->getNewValue(); 39 44 } 40 45 ··· 49 54 case FundBackerTransaction::TYPE_STATUS: 50 55 $object->setStatus($xaction->getNewValue()); 51 56 return; 57 + case FundBackerTransaction::TYPE_REFUND: 58 + return; 52 59 } 53 60 54 61 return parent::applyCustomInternalTransaction($object, $xaction); ··· 60 67 61 68 switch ($xaction->getTransactionType()) { 62 69 case FundBackerTransaction::TYPE_STATUS: 70 + case FundBackerTransaction::TYPE_REFUND: 63 71 return; 64 72 } 65 73
+47 -12
src/applications/fund/editor/FundInitiativeEditor.php
··· 19 19 $types[] = FundInitiativeTransaction::TYPE_RISKS; 20 20 $types[] = FundInitiativeTransaction::TYPE_STATUS; 21 21 $types[] = FundInitiativeTransaction::TYPE_BACKER; 22 + $types[] = FundInitiativeTransaction::TYPE_REFUND; 22 23 $types[] = FundInitiativeTransaction::TYPE_MERCHANT; 23 24 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 24 25 $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; ··· 39 40 case FundInitiativeTransaction::TYPE_STATUS: 40 41 return $object->getStatus(); 41 42 case FundInitiativeTransaction::TYPE_BACKER: 43 + case FundInitiativeTransaction::TYPE_REFUND: 42 44 return null; 43 45 case FundInitiativeTransaction::TYPE_MERCHANT: 44 46 return $object->getMerchantPHID(); ··· 57 59 case FundInitiativeTransaction::TYPE_RISKS: 58 60 case FundInitiativeTransaction::TYPE_STATUS: 59 61 case FundInitiativeTransaction::TYPE_BACKER: 62 + case FundInitiativeTransaction::TYPE_REFUND: 60 63 case FundInitiativeTransaction::TYPE_MERCHANT: 61 64 return $xaction->getNewValue(); 62 65 } ··· 68 71 PhabricatorLiskDAO $object, 69 72 PhabricatorApplicationTransaction $xaction) { 70 73 71 - switch ($xaction->getTransactionType()) { 74 + $type = $xaction->getTransactionType(); 75 + switch ($type) { 72 76 case FundInitiativeTransaction::TYPE_NAME: 73 77 $object->setName($xaction->getNewValue()); 74 78 return; ··· 85 89 $object->setStatus($xaction->getNewValue()); 86 90 return; 87 91 case FundInitiativeTransaction::TYPE_BACKER: 88 - $backer = id(new FundBackerQuery()) 89 - ->setViewer($this->requireActor()) 90 - ->withPHIDs(array($xaction->getNewValue())) 91 - ->executeOne(); 92 - if (!$backer) { 93 - throw new Exception(pht('No such backer!')); 92 + case FundInitiativeTransaction::TYPE_REFUND: 93 + $amount = $xaction->getMetadataValue( 94 + FundInitiativeTransaction::PROPERTY_AMOUNT); 95 + $amount = PhortuneCurrency::newFromString($amount); 96 + 97 + if ($type == FundInitiativeTransaction::TYPE_REFUND) { 98 + $total = $object->getTotalAsCurrency()->subtract($amount); 99 + } else { 100 + $total = $object->getTotalAsCurrency()->add($amount); 94 101 } 95 102 96 - $backer_amount = $backer->getAmountAsCurrency(); 97 - $total = $object->getTotalAsCurrency()->add($backer_amount); 98 103 $object->setTotalAsCurrency($total); 99 - 100 104 return; 101 105 case PhabricatorTransactions::TYPE_SUBSCRIBERS: 102 106 case PhabricatorTransactions::TYPE_EDGE: ··· 110 114 PhabricatorLiskDAO $object, 111 115 PhabricatorApplicationTransaction $xaction) { 112 116 113 - switch ($xaction->getTransactionType()) { 117 + $type = $xaction->getTransactionType(); 118 + switch ($type) { 114 119 case FundInitiativeTransaction::TYPE_NAME: 115 120 case FundInitiativeTransaction::TYPE_DESCRIPTION: 116 121 case FundInitiativeTransaction::TYPE_RISKS: 117 122 case FundInitiativeTransaction::TYPE_STATUS: 118 123 case FundInitiativeTransaction::TYPE_MERCHANT: 124 + return; 119 125 case FundInitiativeTransaction::TYPE_BACKER: 120 - // TODO: Maybe we should apply the backer transaction from here? 126 + case FundInitiativeTransaction::TYPE_REFUND: 127 + $backer = id(new FundBackerQuery()) 128 + ->setViewer($this->requireActor()) 129 + ->withPHIDs(array($xaction->getNewValue())) 130 + ->executeOne(); 131 + if (!$backer) { 132 + throw new Exception(pht('Unable to load FundBacker!')); 133 + } 134 + 135 + $subx = array(); 136 + 137 + if ($type == FundInitiativeTransaction::TYPE_BACKER) { 138 + $subx[] = id(new FundBackerTransaction()) 139 + ->setTransactionType(FundBackerTransaction::TYPE_STATUS) 140 + ->setNewValue(FundBacker::STATUS_PURCHASED); 141 + } else { 142 + $amount = $xaction->getMetadataValue( 143 + FundInitiativeTransaction::PROPERTY_AMOUNT); 144 + $subx[] = id(new FundBackerTransaction()) 145 + ->setTransactionType(FundBackerTransaction::TYPE_STATUS) 146 + ->setNewValue($amount); 147 + } 148 + 149 + $editor = id(new FundBackerEditor()) 150 + ->setActor($this->requireActor()) 151 + ->setContentSource($this->getContentSource()) 152 + ->setContinueOnMissingFields(true) 153 + ->setContinueOnNoEffect(true); 154 + 155 + $editor->applyTransactions($backer, $subx); 121 156 return; 122 157 case PhabricatorTransactions::TYPE_SUBSCRIBERS: 123 158 case PhabricatorTransactions::TYPE_EDGE:
+31 -16
src/applications/fund/phortune/FundBackerProduct.php
··· 89 89 throw new Exception(pht('Unable to load FundBacker!')); 90 90 } 91 91 92 - // Load the actual backing user --they may not be the curent viewer if this 92 + // Load the actual backing user -- they may not be the curent viewer if this 93 93 // product purchase is completing from a background worker or a merchant 94 94 // action. 95 95 ··· 99 99 ->executeOne(); 100 100 101 101 $xactions = array(); 102 - $xactions[] = id(new FundBackerTransaction()) 103 - ->setTransactionType(FundBackerTransaction::TYPE_STATUS) 104 - ->setNewValue(FundBacker::STATUS_PURCHASED); 105 - 106 - $editor = id(new FundBackerEditor()) 107 - ->setActor($actor) 108 - ->setContentSource($this->getContentSource()); 109 - 110 - $editor->applyTransactions($backer, $xactions); 111 - 112 - $xactions = array(); 113 102 $xactions[] = id(new FundInitiativeTransaction()) 114 103 ->setTransactionType(FundInitiativeTransaction::TYPE_BACKER) 104 + ->setMetadataValue( 105 + FundInitiativeTransaction::PROPERTY_AMOUNT, 106 + $backer->getAmountAsCurrency()->serializeForStorage()) 115 107 ->setNewValue($backer->getPHID()); 116 108 117 109 $editor = id(new FundInitiativeEditor()) ··· 119 111 ->setContentSource($this->getContentSource()); 120 112 121 113 $editor->applyTransactions($this->getInitiative(), $xactions); 122 - 123 - return; 124 114 } 125 115 126 116 public function didRefundProduct( 127 117 PhortuneProduct $product, 128 - PhortunePurchase $purchase) { 118 + PhortunePurchase $purchase, 119 + PhortuneCurrency $amount) { 129 120 $viewer = $this->getViewer(); 130 - // TODO: Undonate. 121 + 122 + $backer = id(new FundBackerQuery()) 123 + ->setViewer($viewer) 124 + ->withPHIDs(array($purchase->getMetadataValue('backerPHID'))) 125 + ->executeOne(); 126 + if (!$backer) { 127 + throw new Exception(pht('Unable to load FundBacker!')); 128 + } 129 + 130 + $xactions = array(); 131 + $xactions[] = id(new FundInitiativeTransaction()) 132 + ->setTransactionType(FundInitiativeTransaction::TYPE_REFUND) 133 + ->setMetadataValue( 134 + FundInitiativeTransaction::PROPERTY_AMOUNT, 135 + $amount->serializeForStorage()) 136 + ->setMetadataValue( 137 + FundInitiativeTransaction::PROPERTY_BACKER, 138 + $backer->getBackerPHID()) 139 + ->setNewValue($backer->getPHID()); 140 + 141 + $editor = id(new FundInitiativeEditor()) 142 + ->setActor($viewer) 143 + ->setContentSource($this->getContentSource()); 144 + 145 + $editor->applyTransactions($this->getInitiative(), $xactions); 131 146 } 132 147 133 148 }
+1
src/applications/fund/storage/FundBackerTransaction.php
··· 4 4 extends PhabricatorApplicationTransaction { 5 5 6 6 const TYPE_STATUS = 'fund:backer:status'; 7 + const TYPE_REFUND = 'fund:backer:refund'; 7 8 8 9 public function getApplicationName() { 9 10 return 'fund';
+23 -2
src/applications/fund/storage/FundInitiativeTransaction.php
··· 8 8 const TYPE_RISKS = 'fund:risks'; 9 9 const TYPE_STATUS = 'fund:status'; 10 10 const TYPE_BACKER = 'fund:backer'; 11 + const TYPE_REFUND = 'fund:refund'; 11 12 const TYPE_MERCHANT = 'fund:merchant'; 13 + 14 + const PROPERTY_AMOUNT = 'fund.amount'; 15 + const PROPERTY_BACKER = 'fund.backer'; 12 16 13 17 public function getApplicationName() { 14 18 return 'fund'; ··· 37 41 if ($new) { 38 42 $phids[] = $new; 39 43 } 44 + break; 45 + case FundInitiativeTransaction::TYPE_REFUND: 46 + $phids[] = $this->getMetadataValue(self::PROPERTY_BACKER); 40 47 break; 41 48 } 42 49 ··· 86 93 } 87 94 break; 88 95 case FundInitiativeTransaction::TYPE_BACKER: 96 + $amount = $this->getMetadataValue(self::PROPERTY_AMOUNT); 97 + $amount = PhortuneCurrency::newFromString($amount); 89 98 return pht( 90 - '%s backed this initiative.', 91 - $this->renderHandleLink($author_phid)); 99 + '%s backed this initiative with %s.', 100 + $this->renderHandleLink($author_phid), 101 + $amount->formatForDisplay()); 102 + case FundInitiativeTransaction::TYPE_REFUND: 103 + $amount = $this->getMetadataValue(self::PROPERTY_AMOUNT); 104 + $amount = PhortuneCurrency::newFromString($amount); 105 + 106 + $backer_phid = $this->getMetadataValue(self::PROPERTY_BACKER); 107 + 108 + return pht( 109 + '%s refunded %s to %s.', 110 + $this->renderHandleLink($author_phid), 111 + $amount->formatForDisplay(), 112 + $this->renderHandleLink($backer_phid)); 92 113 case FundInitiativeTransaction::TYPE_MERCHANT: 93 114 if ($old === null) { 94 115 return pht(
+2 -1
src/applications/phortune/controller/PhortuneCartCancelController.php
··· 87 87 $request->getStr('refund')); 88 88 $refund->assertInRange('0.00 USD', $maximum->formatForDisplay()); 89 89 } catch (Exception $ex) { 90 - $errors[] = $ex; 90 + $errors[] = $ex->getMessage(); 91 91 $e_refund = pht('Invalid'); 92 92 } 93 93 } else { ··· 199 199 200 200 return $this->newDialog() 201 201 ->setTitle($title) 202 + ->setErrors($errors) 202 203 ->appendChild($body) 203 204 ->appendChild($form) 204 205 ->addSubmitButton($button)
+2 -1
src/applications/phortune/product/PhortuneProductImplementation.php
··· 30 30 31 31 public function didRefundProduct( 32 32 PhortuneProduct $product, 33 - PhortunePurchase $purchase) { 33 + PhortunePurchase $purchase, 34 + PhortuneCurrency $amount) { 34 35 return; 35 36 } 36 37
+2 -1
src/applications/phortune/storage/PhortuneCart.php
··· 351 351 $this->endReadLocking(); 352 352 $this->saveTransaction(); 353 353 354 + $amount = $refund->getAmountAsCurrency()->negate(); 354 355 foreach ($this->purchases as $purchase) { 355 - $purchase->getProduct()->didRefundProduct($purchase); 356 + $purchase->getProduct()->didRefundProduct($purchase, $amount); 356 357 } 357 358 358 359 return $this;
+7 -2
src/applications/phortune/storage/PhortuneProduct.php
··· 78 78 return $this->getImplementation()->didPurchaseProduct($this, $purchase); 79 79 } 80 80 81 - public function didRefundProduct(PhortunePurchase $purchase) { 82 - return $this->getImplementation()->didRefundProduct($this, $purchase); 81 + public function didRefundProduct( 82 + PhortunePurchase $purchase, 83 + PhortuneCurrency $amount) { 84 + return $this->getImplementation()->didRefundProduct( 85 + $this, 86 + $purchase, 87 + $amount); 83 88 } 84 89 85 90