[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/phortune/controller/ -> PhortuneCartCancelController.php (source)

   1  <?php
   2  
   3  final class PhortuneCartCancelController
   4    extends PhortuneCartController {
   5  
   6    private $id;
   7    private $action;
   8  
   9    public function willProcessRequest(array $data) {
  10      $this->id = $data['id'];
  11      $this->action = $data['action'];
  12    }
  13  
  14    public function processRequest() {
  15      $request = $this->getRequest();
  16      $viewer = $request->getUser();
  17  
  18      $cart = id(new PhortuneCartQuery())
  19        ->setViewer($viewer)
  20        ->withIDs(array($this->id))
  21        ->needPurchases(true)
  22        ->executeOne();
  23      if (!$cart) {
  24        return new Aphront404Response();
  25      }
  26  
  27      switch ($this->action) {
  28        case 'cancel':
  29          // You must be able to edit the account to cancel an order.
  30          PhabricatorPolicyFilter::requireCapability(
  31            $viewer,
  32            $cart->getAccount(),
  33            PhabricatorPolicyCapability::CAN_EDIT);
  34          $is_refund = false;
  35          break;
  36        case 'refund':
  37          // You must be able to control the merchant to refund an order.
  38          PhabricatorPolicyFilter::requireCapability(
  39            $viewer,
  40            $cart->getMerchant(),
  41            PhabricatorPolicyCapability::CAN_EDIT);
  42          $is_refund = true;
  43          break;
  44        default:
  45          return new Aphront404Response();
  46      }
  47  
  48      $cancel_uri = $cart->getDetailURI();
  49      $merchant = $cart->getMerchant();
  50  
  51      try {
  52        if ($is_refund) {
  53          $title = pht('Unable to Refund Order');
  54          $cart->assertCanRefundOrder();
  55        } else {
  56          $title = pht('Unable to Cancel Order');
  57          $cart->assertCanCancelOrder();
  58        }
  59      } catch (Exception $ex) {
  60        return $this->newDialog()
  61          ->setTitle($title)
  62          ->appendChild($ex->getMessage())
  63          ->addCancelButton($cancel_uri);
  64      }
  65  
  66      $charges = id(new PhortuneChargeQuery())
  67        ->setViewer($viewer)
  68        ->withCartPHIDs(array($cart->getPHID()))
  69        ->withStatuses(
  70          array(
  71            PhortuneCharge::STATUS_HOLD,
  72            PhortuneCharge::STATUS_CHARGED,
  73          ))
  74        ->execute();
  75  
  76      $amounts = mpull($charges, 'getAmountAsCurrency');
  77      $maximum = PhortuneCurrency::newFromList($amounts);
  78      $v_refund = $maximum->formatForDisplay();
  79  
  80      $errors = array();
  81      $e_refund = true;
  82      if ($request->isFormPost()) {
  83        if ($is_refund) {
  84          try {
  85            $refund = PhortuneCurrency::newFromUserInput(
  86              $viewer,
  87              $request->getStr('refund'));
  88            $refund->assertInRange('0.00 USD', $maximum->formatForDisplay());
  89          } catch (Exception $ex) {
  90            $errors[] = $ex->getMessage();
  91            $e_refund = pht('Invalid');
  92          }
  93        } else {
  94          $refund = $maximum;
  95        }
  96  
  97        if (!$errors) {
  98          $charges = msort($charges, 'getID');
  99          $charges = array_reverse($charges);
 100  
 101          if ($charges) {
 102            $providers = id(new PhortunePaymentProviderConfigQuery())
 103              ->setViewer($viewer)
 104              ->withPHIDs(mpull($charges, 'getProviderPHID'))
 105              ->execute();
 106            $providers = mpull($providers, null, 'getPHID');
 107          } else {
 108            $providers = array();
 109          }
 110  
 111          foreach ($charges as $charge) {
 112            $refundable = $charge->getAmountRefundableAsCurrency();
 113            if (!$refundable->isPositive()) {
 114              // This charge is a refund, or has already been fully refunded.
 115              continue;
 116            }
 117  
 118            if ($refund->isGreaterThan($refundable)) {
 119              $refund_amount = $refundable;
 120            } else {
 121              $refund_amount = $refund;
 122            }
 123  
 124            $provider_config = idx($providers, $charge->getProviderPHID());
 125            if (!$provider_config) {
 126              throw new Exception(pht('Unable to load provider for charge!'));
 127            }
 128  
 129            $provider = $provider_config->buildProvider();
 130  
 131            $refund_charge = $cart->willRefundCharge(
 132              $viewer,
 133              $provider,
 134              $charge,
 135              $refund_amount);
 136  
 137            $refunded = false;
 138            try {
 139              $provider->refundCharge($charge, $refund_charge);
 140              $refunded = true;
 141            } catch (Exception $ex) {
 142              phlog($ex);
 143              $cart->didFailRefund($charge, $refund_charge);
 144            }
 145  
 146            if ($refunded) {
 147              $cart->didRefundCharge($charge, $refund_charge);
 148              $refund = $refund->subtract($refund_amount);
 149            }
 150  
 151            if (!$refund->isPositive()) {
 152              break;
 153            }
 154          }
 155  
 156          if ($refund->isPositive()) {
 157            throw new Exception(pht('Unable to refund some charges!'));
 158          }
 159  
 160          // TODO: If every HOLD and CHARGING transaction has been fully refunded
 161          // and we're in a HOLD, REVIEW, PURCHASING or CHARGED cart state we
 162          // probably need to kick the cart back to READY here (or maybe kill
 163          // it if it was in REVIEW)?
 164  
 165          return id(new AphrontRedirectResponse())->setURI($cancel_uri);
 166        }
 167      }
 168  
 169      if ($is_refund) {
 170        $title = pht('Refund Order?');
 171        $body = pht(
 172          'Really refund this order?');
 173        $button = pht('Refund Order');
 174        $cancel_text = pht('Cancel');
 175  
 176        $form = id(new AphrontFormView())
 177          ->setUser($viewer)
 178          ->appendChild(
 179            id(new AphrontFormTextControl())
 180              ->setName('refund')
 181              ->setLabel(pht('Amount'))
 182              ->setError($e_refund)
 183              ->setValue($v_refund));
 184  
 185        $form = $form->buildLayoutView();
 186  
 187      } else {
 188        $title = pht('Cancel Order?');
 189        $body = pht(
 190          'Really cancel this order? Any payment will be refunded.');
 191        $button = pht('Cancel Order');
 192  
 193        // Don't give the user a "Cancel" button in response to a "Cancel?"
 194        // prompt, as it's confusing.
 195        $cancel_text = pht('Do Not Cancel Order');
 196  
 197        $form = null;
 198      }
 199  
 200      return $this->newDialog()
 201        ->setTitle($title)
 202        ->setErrors($errors)
 203        ->appendChild($body)
 204        ->appendChild($form)
 205        ->addSubmitButton($button)
 206        ->addCancelButton($cancel_uri, $cancel_text);
 207    }
 208  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1