mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-20 11:41:08 +01:00
Mail account owners when they have an invoice due
Summary: Ref T6881. If we can't automatically bill an invoice, send the account owners a mail explaining why and asking them to pay it. Test Plan: {F279596} Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T6881 Differential Revision: https://secure.phabricator.com/D11602
This commit is contained in:
parent
f6015dbb56
commit
58b3c5614b
4 changed files with 114 additions and 12 deletions
|
@ -3,6 +3,21 @@
|
||||||
final class PhortuneCartEditor
|
final class PhortuneCartEditor
|
||||||
extends PhabricatorApplicationTransactionEditor {
|
extends PhabricatorApplicationTransactionEditor {
|
||||||
|
|
||||||
|
private $invoiceIssues;
|
||||||
|
|
||||||
|
public function setInvoiceIssues(array $invoice_issues) {
|
||||||
|
$this->invoiceIssues = $invoice_issues;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInvoiceIssues() {
|
||||||
|
return $this->invoiceIssues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isInvoice() {
|
||||||
|
return (bool)$this->invoiceIssues;
|
||||||
|
}
|
||||||
|
|
||||||
public function getEditorApplicationClass() {
|
public function getEditorApplicationClass() {
|
||||||
return 'PhabricatorPhortuneApplication';
|
return 'PhabricatorPhortuneApplication';
|
||||||
}
|
}
|
||||||
|
@ -20,6 +35,7 @@ final class PhortuneCartEditor
|
||||||
$types[] = PhortuneCartTransaction::TYPE_REVIEW;
|
$types[] = PhortuneCartTransaction::TYPE_REVIEW;
|
||||||
$types[] = PhortuneCartTransaction::TYPE_CANCEL;
|
$types[] = PhortuneCartTransaction::TYPE_CANCEL;
|
||||||
$types[] = PhortuneCartTransaction::TYPE_REFUND;
|
$types[] = PhortuneCartTransaction::TYPE_REFUND;
|
||||||
|
$types[] = PhortuneCartTransaction::TYPE_INVOICED;
|
||||||
|
|
||||||
return $types;
|
return $types;
|
||||||
}
|
}
|
||||||
|
@ -35,6 +51,7 @@ final class PhortuneCartEditor
|
||||||
case PhortuneCartTransaction::TYPE_REVIEW:
|
case PhortuneCartTransaction::TYPE_REVIEW:
|
||||||
case PhortuneCartTransaction::TYPE_CANCEL:
|
case PhortuneCartTransaction::TYPE_CANCEL:
|
||||||
case PhortuneCartTransaction::TYPE_REFUND:
|
case PhortuneCartTransaction::TYPE_REFUND:
|
||||||
|
case PhortuneCartTransaction::TYPE_INVOICED:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +69,7 @@ final class PhortuneCartEditor
|
||||||
case PhortuneCartTransaction::TYPE_REVIEW:
|
case PhortuneCartTransaction::TYPE_REVIEW:
|
||||||
case PhortuneCartTransaction::TYPE_CANCEL:
|
case PhortuneCartTransaction::TYPE_CANCEL:
|
||||||
case PhortuneCartTransaction::TYPE_REFUND:
|
case PhortuneCartTransaction::TYPE_REFUND:
|
||||||
|
case PhortuneCartTransaction::TYPE_INVOICED:
|
||||||
return $xaction->getNewValue();
|
return $xaction->getNewValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +87,7 @@ final class PhortuneCartEditor
|
||||||
case PhortuneCartTransaction::TYPE_REVIEW:
|
case PhortuneCartTransaction::TYPE_REVIEW:
|
||||||
case PhortuneCartTransaction::TYPE_CANCEL:
|
case PhortuneCartTransaction::TYPE_CANCEL:
|
||||||
case PhortuneCartTransaction::TYPE_REFUND:
|
case PhortuneCartTransaction::TYPE_REFUND:
|
||||||
|
case PhortuneCartTransaction::TYPE_INVOICED:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +105,7 @@ final class PhortuneCartEditor
|
||||||
case PhortuneCartTransaction::TYPE_REVIEW:
|
case PhortuneCartTransaction::TYPE_REVIEW:
|
||||||
case PhortuneCartTransaction::TYPE_CANCEL:
|
case PhortuneCartTransaction::TYPE_CANCEL:
|
||||||
case PhortuneCartTransaction::TYPE_REFUND:
|
case PhortuneCartTransaction::TYPE_REFUND:
|
||||||
|
case PhortuneCartTransaction::TYPE_INVOICED:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,6 +133,25 @@ final class PhortuneCartEditor
|
||||||
|
|
||||||
$body = parent::buildMailBody($object, $xactions);
|
$body = parent::buildMailBody($object, $xactions);
|
||||||
|
|
||||||
|
if ($this->isInvoice()) {
|
||||||
|
$issues = $this->getInvoiceIssues();
|
||||||
|
foreach ($issues as $key => $issue) {
|
||||||
|
$issues[$key] = ' - '.$issue;
|
||||||
|
}
|
||||||
|
$issues = implode("\n", $issues);
|
||||||
|
|
||||||
|
$overview = pht(
|
||||||
|
"Payment for this invoice could not be processed automatically:\n\n".
|
||||||
|
"%s",
|
||||||
|
$issues);
|
||||||
|
|
||||||
|
$body->addRemarkupSection($overview);
|
||||||
|
|
||||||
|
$body->addLinkSection(
|
||||||
|
pht('PAY NOW'),
|
||||||
|
PhabricatorEnv::getProductionURI($object->getCheckoutURI()));
|
||||||
|
}
|
||||||
|
|
||||||
$items = array();
|
$items = array();
|
||||||
foreach ($object->getPurchases() as $purchase) {
|
foreach ($object->getPurchases() as $purchase) {
|
||||||
$name = $purchase->getFullDisplayName();
|
$name = $purchase->getFullDisplayName();
|
||||||
|
@ -123,9 +162,26 @@ final class PhortuneCartEditor
|
||||||
|
|
||||||
$body->addTextSection(pht('ORDER CONTENTS'), implode("\n", $items));
|
$body->addTextSection(pht('ORDER CONTENTS'), implode("\n", $items));
|
||||||
|
|
||||||
|
if ($this->isInvoice()) {
|
||||||
|
$subscription = id(new PhortuneSubscriptionQuery())
|
||||||
|
->setViewer($this->requireActor())
|
||||||
|
->withPHIDs(array($object->getSubscriptionPHID()))
|
||||||
|
->executeOne();
|
||||||
|
if ($subscription) {
|
||||||
|
$body->addLinkSection(
|
||||||
|
pht('SUBSCRIPTION'),
|
||||||
|
PhabricatorEnv::getProductionURI($subscription->getURI()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$body->addLinkSection(
|
||||||
|
pht('ORDER DETAIL'),
|
||||||
|
PhabricatorEnv::getProductionURI($object->getDetailURI()));
|
||||||
|
}
|
||||||
|
|
||||||
|
$account_uri = '/phortune/'.$object->getAccount()->getID().'/';
|
||||||
$body->addLinkSection(
|
$body->addLinkSection(
|
||||||
pht('ORDER DETAIL'),
|
pht('ACCOUNT OVERVIEW'),
|
||||||
PhabricatorEnv::getProductionURI('/phortune/cart/'.$object->getID().'/'));
|
PhabricatorEnv::getProductionURI($account_uri));
|
||||||
|
|
||||||
return $body;
|
return $body;
|
||||||
}
|
}
|
||||||
|
@ -156,7 +212,7 @@ final class PhortuneCartEditor
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getMailSubjectPrefix() {
|
protected function getMailSubjectPrefix() {
|
||||||
return 'Order';
|
return '[Phortune]';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
|
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ final class PhortuneCartTransaction
|
||||||
const TYPE_CANCEL = 'cart:cancel';
|
const TYPE_CANCEL = 'cart:cancel';
|
||||||
const TYPE_REFUND = 'cart:refund';
|
const TYPE_REFUND = 'cart:refund';
|
||||||
const TYPE_PURCHASED = 'cart:purchased';
|
const TYPE_PURCHASED = 'cart:purchased';
|
||||||
|
const TYPE_INVOICED = 'cart:invoiced';
|
||||||
|
|
||||||
public function getApplicationName() {
|
public function getApplicationName() {
|
||||||
return 'phortune';
|
return 'phortune';
|
||||||
|
@ -49,9 +50,42 @@ final class PhortuneCartTransaction
|
||||||
return pht('This order was refunded.');
|
return pht('This order was refunded.');
|
||||||
case self::TYPE_PURCHASED:
|
case self::TYPE_PURCHASED:
|
||||||
return pht('Payment for this order was completed.');
|
return pht('Payment for this order was completed.');
|
||||||
|
case self::TYPE_INVOICED:
|
||||||
|
return pht('This order was invoiced.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getTitle();
|
return parent::getTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getTitleForMail() {
|
||||||
|
switch ($this->getTransactionType()) {
|
||||||
|
case self::TYPE_INVOICED:
|
||||||
|
return pht('You have a new invoice due.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getTitleForMail();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getActionName() {
|
||||||
|
switch ($this->getTransactionType()) {
|
||||||
|
case self::TYPE_CREATED:
|
||||||
|
return pht('Created');
|
||||||
|
case self::TYPE_HOLD:
|
||||||
|
return pht('Hold');
|
||||||
|
case self::TYPE_REVIEW:
|
||||||
|
return pht('Review');
|
||||||
|
case self::TYPE_CANCEL:
|
||||||
|
return pht('Cancelled');
|
||||||
|
case self::TYPE_REFUND:
|
||||||
|
return pht('Refunded');
|
||||||
|
case self::TYPE_PURCHASED:
|
||||||
|
return pht('Complete');
|
||||||
|
case self::TYPE_INVOICED:
|
||||||
|
return pht('New Invoice');
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::getActionName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,12 +22,6 @@ abstract class PhortuneSubscriptionImplementation {
|
||||||
$start_epoch,
|
$start_epoch,
|
||||||
$end_epoch);
|
$end_epoch);
|
||||||
|
|
||||||
protected function getContentSource() {
|
|
||||||
return PhabricatorContentSource::newForSource(
|
|
||||||
PhabricatorContentSource::SOURCE_PHORTUNE,
|
|
||||||
array());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCartName(
|
public function getCartName(
|
||||||
PhortuneSubscription $subscription,
|
PhortuneSubscription $subscription,
|
||||||
PhortuneCart $cart) {
|
PhortuneCart $cart) {
|
||||||
|
|
|
@ -73,9 +73,27 @@ final class PhortuneSubscriptionWorker extends PhabricatorWorker {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Send an email telling the user that we weren't able to autopay
|
// We're shoving this through the CartEditor because it has all the logic
|
||||||
// so they need to pay this manually.
|
// for sending mail about carts. This doesn't really affect the state of
|
||||||
throw new Exception(implode("\n", $issues));
|
// the cart, but reduces the amount of code duplication.
|
||||||
|
|
||||||
|
$xactions = array();
|
||||||
|
$xactions[] = id(new PhortuneCartTransaction())
|
||||||
|
->setTransactionType(PhortuneCartTransaction::TYPE_INVOICED)
|
||||||
|
->setNewValue(true);
|
||||||
|
|
||||||
|
$content_source = PhabricatorContentSource::newForSource(
|
||||||
|
PhabricatorContentSource::SOURCE_PHORTUNE,
|
||||||
|
array());
|
||||||
|
|
||||||
|
$acting_phid = id(new PhabricatorPhortuneApplication())->getPHID();
|
||||||
|
$editor = id(new PhortuneCartEditor())
|
||||||
|
->setActor($viewer)
|
||||||
|
->setActingAsPHID($acting_phid)
|
||||||
|
->setContentSource($content_source)
|
||||||
|
->setContinueOnMissingFields(true)
|
||||||
|
->setInvoiceIssues($issues)
|
||||||
|
->applyTransactions($cart, $xactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue