{"record":{"id":"f359aea54a2b3129","repo":"phacility/phabricator","slug":"this-order-can-not-be-refunded-because-it-has-not","errorCode":null,"errorMessage":"This order can not be refunded because it has not been placed.","messagePattern":"This order can not be refunded because it has not been placed\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"warning","filePath":"src/applications/phortune/storage/PhortuneCart.php","lineNumber":535,"sourceCode":"            'finished building it yet.'));\n      case self::STATUS_READY:\n        throw new Exception(\n          pht(\n            'This order can not be cancelled because it has not been placed.'));\n    }\n\n    return $this->getImplementation()->assertCanCancelOrder($this);\n  }\n\n  public function assertCanRefundOrder() {\n    switch ($this->getStatus()) {\n      case self::STATUS_BUILDING:\n        throw new Exception(\n          pht(\n            'This order can not be refunded because the application has not '.\n            'finished building it yet.'));\n      case self::STATUS_READY:\n        throw new Exception(\n          pht(\n            'This order can not be refunded because it has not been placed.'));\n    }\n\n    return $this->getImplementation()->assertCanRefundOrder($this);\n  }\n\n  public function assertCanVoidOrder() {\n    if (!$this->getIsInvoice()) {\n      throw new Exception(\n        pht(\n          'This order can not be voided because it is not an invoice.'));\n    }\n\n    switch ($this->getStatus()) {\n      case self::STATUS_READY:\n        break;\n      default:","sourceCodeStart":517,"sourceCodeEnd":553,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/phortune/storage/PhortuneCart.php#L517-L553","documentation":"assertCanRefundOrder() throws when the cart is STATUS_READY: the order exists but was never placed or paid, so a refund is meaningless. Only carts that have actually been charged can be refunded. Use canRefundOrder() to test the condition without the exception.","triggerScenarios":"Calling assertCanRefundOrder() on a cart in PhortuneCart::STATUS_READY, such as an abandoned checkout that was never completed.","commonSituations":"Support staff trying to 'undo' an unpaid order; refund UI shown uniformly across all order statuses; stale order links.","solutions":["Check $cart->canRefundOrder() before showing or executing refund actions.","Treat unplaced READY orders as cancellable/ignorable rather than refundable.","Ensure order lists distinguish placed from unplaced carts."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if ($cart->getStatus() === PhortuneCart::STATUS_READY) {\n  // never placed: use cancel/abandon semantics, not refund\n}\nif (!$cart->canRefundOrder()) {\n  return $this->newDialog()->setTitle(pht('Unable to Refund Order'));\n}","typeGuard":"function isPlacedCart(PhortuneCart $cart) {\n  return !in_array(\n    $cart->getStatus(),\n    array(PhortuneCart::STATUS_BUILDING, PhortuneCart::STATUS_READY));\n}","tryCatchPattern":null,"preventionTips":["Check canRefundOrder() before offering refunds.","Distinguish placed from unplaced orders in UI labels.","Train support flows: unpaid orders are abandoned, not refunded."],"tags":["phortune","phabricator","php","payments","cart","refund","order-lifecycle"],"backgroundTag":"invalid-cart-status","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}