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

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
This commit is contained in:
epriestley 2014-10-10 11:29:31 -07:00
parent 38927d5704
commit 44415c5473
10 changed files with 125 additions and 36 deletions

View file

@ -63,7 +63,8 @@ final class FundInitiativeViewController
$timeline = id(new PhabricatorApplicationTransactionView())
->setUser($viewer)
->setObjectPHID($initiative->getPHID())
->setTransactions($xactions);
->setTransactions($xactions)
->setShouldTerminate(true);
return $this->buildApplicationPage(
array(

View file

@ -13,7 +13,9 @@ final class FundBackerEditor
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
$types[] = FundBackerTransaction::TYPE_STATUS;
$types[] = FundBackerTransaction::TYPE_REFUND;
return $types;
}
@ -24,6 +26,8 @@ final class FundBackerEditor
switch ($xaction->getTransactionType()) {
case FundBackerTransaction::TYPE_STATUS:
return $object->getStatus();
case FundBackerTransaction::TYPE_REFUND:
return null;
}
return parent::getCustomTransactionOldValue($object, $xaction);
@ -35,6 +39,7 @@ final class FundBackerEditor
switch ($xaction->getTransactionType()) {
case FundBackerTransaction::TYPE_STATUS:
case FundBackerTransaction::TYPE_REFUND:
return $xaction->getNewValue();
}
@ -49,6 +54,8 @@ final class FundBackerEditor
case FundBackerTransaction::TYPE_STATUS:
$object->setStatus($xaction->getNewValue());
return;
case FundBackerTransaction::TYPE_REFUND:
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
@ -60,6 +67,7 @@ final class FundBackerEditor
switch ($xaction->getTransactionType()) {
case FundBackerTransaction::TYPE_STATUS:
case FundBackerTransaction::TYPE_REFUND:
return;
}

View file

@ -19,6 +19,7 @@ final class FundInitiativeEditor
$types[] = FundInitiativeTransaction::TYPE_RISKS;
$types[] = FundInitiativeTransaction::TYPE_STATUS;
$types[] = FundInitiativeTransaction::TYPE_BACKER;
$types[] = FundInitiativeTransaction::TYPE_REFUND;
$types[] = FundInitiativeTransaction::TYPE_MERCHANT;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
@ -39,6 +40,7 @@ final class FundInitiativeEditor
case FundInitiativeTransaction::TYPE_STATUS:
return $object->getStatus();
case FundInitiativeTransaction::TYPE_BACKER:
case FundInitiativeTransaction::TYPE_REFUND:
return null;
case FundInitiativeTransaction::TYPE_MERCHANT:
return $object->getMerchantPHID();
@ -57,6 +59,7 @@ final class FundInitiativeEditor
case FundInitiativeTransaction::TYPE_RISKS:
case FundInitiativeTransaction::TYPE_STATUS:
case FundInitiativeTransaction::TYPE_BACKER:
case FundInitiativeTransaction::TYPE_REFUND:
case FundInitiativeTransaction::TYPE_MERCHANT:
return $xaction->getNewValue();
}
@ -68,7 +71,8 @@ final class FundInitiativeEditor
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
$type = $xaction->getTransactionType();
switch ($type) {
case FundInitiativeTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
return;
@ -85,18 +89,18 @@ final class FundInitiativeEditor
$object->setStatus($xaction->getNewValue());
return;
case FundInitiativeTransaction::TYPE_BACKER:
$backer = id(new FundBackerQuery())
->setViewer($this->requireActor())
->withPHIDs(array($xaction->getNewValue()))
->executeOne();
if (!$backer) {
throw new Exception(pht('No such backer!'));
case FundInitiativeTransaction::TYPE_REFUND:
$amount = $xaction->getMetadataValue(
FundInitiativeTransaction::PROPERTY_AMOUNT);
$amount = PhortuneCurrency::newFromString($amount);
if ($type == FundInitiativeTransaction::TYPE_REFUND) {
$total = $object->getTotalAsCurrency()->subtract($amount);
} else {
$total = $object->getTotalAsCurrency()->add($amount);
}
$backer_amount = $backer->getAmountAsCurrency();
$total = $object->getTotalAsCurrency()->add($backer_amount);
$object->setTotalAsCurrency($total);
return;
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
case PhabricatorTransactions::TYPE_EDGE:
@ -110,14 +114,45 @@ final class FundInitiativeEditor
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
$type = $xaction->getTransactionType();
switch ($type) {
case FundInitiativeTransaction::TYPE_NAME:
case FundInitiativeTransaction::TYPE_DESCRIPTION:
case FundInitiativeTransaction::TYPE_RISKS:
case FundInitiativeTransaction::TYPE_STATUS:
case FundInitiativeTransaction::TYPE_MERCHANT:
return;
case FundInitiativeTransaction::TYPE_BACKER:
// TODO: Maybe we should apply the backer transaction from here?
case FundInitiativeTransaction::TYPE_REFUND:
$backer = id(new FundBackerQuery())
->setViewer($this->requireActor())
->withPHIDs(array($xaction->getNewValue()))
->executeOne();
if (!$backer) {
throw new Exception(pht('Unable to load FundBacker!'));
}
$subx = array();
if ($type == FundInitiativeTransaction::TYPE_BACKER) {
$subx[] = id(new FundBackerTransaction())
->setTransactionType(FundBackerTransaction::TYPE_STATUS)
->setNewValue(FundBacker::STATUS_PURCHASED);
} else {
$amount = $xaction->getMetadataValue(
FundInitiativeTransaction::PROPERTY_AMOUNT);
$subx[] = id(new FundBackerTransaction())
->setTransactionType(FundBackerTransaction::TYPE_STATUS)
->setNewValue($amount);
}
$editor = id(new FundBackerEditor())
->setActor($this->requireActor())
->setContentSource($this->getContentSource())
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true);
$editor->applyTransactions($backer, $subx);
return;
case PhabricatorTransactions::TYPE_SUBSCRIBERS:
case PhabricatorTransactions::TYPE_EDGE:

View file

@ -89,7 +89,7 @@ final class FundBackerProduct extends PhortuneProductImplementation {
throw new Exception(pht('Unable to load FundBacker!'));
}
// Load the actual backing user --they may not be the curent viewer if this
// Load the actual backing user -- they may not be the curent viewer if this
// product purchase is completing from a background worker or a merchant
// action.
@ -98,20 +98,12 @@ final class FundBackerProduct extends PhortuneProductImplementation {
->withPHIDs(array($backer->getBackerPHID()))
->executeOne();
$xactions = array();
$xactions[] = id(new FundBackerTransaction())
->setTransactionType(FundBackerTransaction::TYPE_STATUS)
->setNewValue(FundBacker::STATUS_PURCHASED);
$editor = id(new FundBackerEditor())
->setActor($actor)
->setContentSource($this->getContentSource());
$editor->applyTransactions($backer, $xactions);
$xactions = array();
$xactions[] = id(new FundInitiativeTransaction())
->setTransactionType(FundInitiativeTransaction::TYPE_BACKER)
->setMetadataValue(
FundInitiativeTransaction::PROPERTY_AMOUNT,
$backer->getAmountAsCurrency()->serializeForStorage())
->setNewValue($backer->getPHID());
$editor = id(new FundInitiativeEditor())
@ -119,15 +111,38 @@ final class FundBackerProduct extends PhortuneProductImplementation {
->setContentSource($this->getContentSource());
$editor->applyTransactions($this->getInitiative(), $xactions);
return;
}
public function didRefundProduct(
PhortuneProduct $product,
PhortunePurchase $purchase) {
PhortunePurchase $purchase,
PhortuneCurrency $amount) {
$viewer = $this->getViewer();
// TODO: Undonate.
$backer = id(new FundBackerQuery())
->setViewer($viewer)
->withPHIDs(array($purchase->getMetadataValue('backerPHID')))
->executeOne();
if (!$backer) {
throw new Exception(pht('Unable to load FundBacker!'));
}
$xactions = array();
$xactions[] = id(new FundInitiativeTransaction())
->setTransactionType(FundInitiativeTransaction::TYPE_REFUND)
->setMetadataValue(
FundInitiativeTransaction::PROPERTY_AMOUNT,
$amount->serializeForStorage())
->setMetadataValue(
FundInitiativeTransaction::PROPERTY_BACKER,
$backer->getBackerPHID())
->setNewValue($backer->getPHID());
$editor = id(new FundInitiativeEditor())
->setActor($viewer)
->setContentSource($this->getContentSource());
$editor->applyTransactions($this->getInitiative(), $xactions);
}
}

View file

@ -4,6 +4,7 @@ final class FundBackerTransaction
extends PhabricatorApplicationTransaction {
const TYPE_STATUS = 'fund:backer:status';
const TYPE_REFUND = 'fund:backer:refund';
public function getApplicationName() {
return 'fund';

View file

@ -8,8 +8,12 @@ final class FundInitiativeTransaction
const TYPE_RISKS = 'fund:risks';
const TYPE_STATUS = 'fund:status';
const TYPE_BACKER = 'fund:backer';
const TYPE_REFUND = 'fund:refund';
const TYPE_MERCHANT = 'fund:merchant';
const PROPERTY_AMOUNT = 'fund.amount';
const PROPERTY_BACKER = 'fund.backer';
public function getApplicationName() {
return 'fund';
}
@ -38,6 +42,9 @@ final class FundInitiativeTransaction
$phids[] = $new;
}
break;
case FundInitiativeTransaction::TYPE_REFUND:
$phids[] = $this->getMetadataValue(self::PROPERTY_BACKER);
break;
}
return $phids;
@ -86,9 +93,23 @@ final class FundInitiativeTransaction
}
break;
case FundInitiativeTransaction::TYPE_BACKER:
$amount = $this->getMetadataValue(self::PROPERTY_AMOUNT);
$amount = PhortuneCurrency::newFromString($amount);
return pht(
'%s backed this initiative.',
$this->renderHandleLink($author_phid));
'%s backed this initiative with %s.',
$this->renderHandleLink($author_phid),
$amount->formatForDisplay());
case FundInitiativeTransaction::TYPE_REFUND:
$amount = $this->getMetadataValue(self::PROPERTY_AMOUNT);
$amount = PhortuneCurrency::newFromString($amount);
$backer_phid = $this->getMetadataValue(self::PROPERTY_BACKER);
return pht(
'%s refunded %s to %s.',
$this->renderHandleLink($author_phid),
$amount->formatForDisplay(),
$this->renderHandleLink($backer_phid));
case FundInitiativeTransaction::TYPE_MERCHANT:
if ($old === null) {
return pht(

View file

@ -87,7 +87,7 @@ final class PhortuneCartCancelController
$request->getStr('refund'));
$refund->assertInRange('0.00 USD', $maximum->formatForDisplay());
} catch (Exception $ex) {
$errors[] = $ex;
$errors[] = $ex->getMessage();
$e_refund = pht('Invalid');
}
} else {
@ -199,6 +199,7 @@ final class PhortuneCartCancelController
return $this->newDialog()
->setTitle($title)
->setErrors($errors)
->appendChild($body)
->appendChild($form)
->addSubmitButton($button)

View file

@ -30,7 +30,8 @@ abstract class PhortuneProductImplementation {
public function didRefundProduct(
PhortuneProduct $product,
PhortunePurchase $purchase) {
PhortunePurchase $purchase,
PhortuneCurrency $amount) {
return;
}

View file

@ -351,8 +351,9 @@ final class PhortuneCart extends PhortuneDAO
$this->endReadLocking();
$this->saveTransaction();
$amount = $refund->getAmountAsCurrency()->negate();
foreach ($this->purchases as $purchase) {
$purchase->getProduct()->didRefundProduct($purchase);
$purchase->getProduct()->didRefundProduct($purchase, $amount);
}
return $this;

View file

@ -78,8 +78,13 @@ final class PhortuneProduct extends PhortuneDAO
return $this->getImplementation()->didPurchaseProduct($this, $purchase);
}
public function didRefundProduct(PhortunePurchase $purchase) {
return $this->getImplementation()->didRefundProduct($this, $purchase);
public function didRefundProduct(
PhortunePurchase $purchase,
PhortuneCurrency $amount) {
return $this->getImplementation()->didRefundProduct(
$this,
$purchase,
$amount);
}