/** * * Completely reverse an invoice by creating a credit receipt * @param string $receiptId */ public function reverseInvoice($receiptId, $orderPositionData) { \org\sopen\dev\DebugLogger::openLogFileOverwrite(CSopen::instance()->getCustomerPath() . '/conf/logs/revinvoice.log'); if (!is_array($orderPositionData)) { $orderPositionData = Zend_Json::decode($orderPositionData); } $rController = Billing_Controller_Receipt::getInstance(); $receipt = $rController->get($receiptId); if ($receipt->__get('receipt_state') !== 'VALID') { throw new Billing_Exception_Receipt('Receipt cannot be reverted twice'); } $order = $receipt->getForeignRecord('order_id', $this); $rpController = Billing_Controller_ReceiptPosition::getInstance(); $opController = Billing_Controller_OrderPosition::getInstance(); $receiptPositions = $rpController->getByReceiptId($receiptId); $creditReceipt = Billing_Model_Receipt::createCredit(); $creditReceipt->__set('order_id', $order->getId()); $creditReceipt->__set('invoice_nr', $receipt->__get('invoice_nr')); $creditReceipt->__set('credit_date', $receipt->__get('invoice_date')); $creditReceipt->__set('invoice_date', $receipt->__get('invoice_date')); // take same payment method for credit receipt $creditReceipt->__set('payment_method_id', $receipt->getForeignId('payment_method_id')); $creditReceipt->__set('is_cancellation', true); $receipt->__set('is_cancelled', true); \org\sopen\dev\DebugLogger::log('RECHNUNG ' . print_r($receipt, true)); $creditReceipt = $rController->create($creditReceipt); $creditReceipt = $rController->get($creditReceipt->getId()); $countPos = count($receiptPositions); $creditPositions = array(); $opCount = count($orderPositionData); $aOrderPosData = null; if (is_array($orderPositionData)) { $aOrderPosData = org\sopen\app\util\arrays\ArrayHelper::getIndexedWithPropertyFromList($orderPositionData, 'id'); } $partReverse = false; foreach ($receiptPositions as $invoicePosition) { //print_r($invoicePosition); if (is_array($aOrderPosData) && $opCount > 0 && (!array_key_exists($invoicePosition->getId(), $aOrderPosData) || !$aOrderPosData[$invoicePosition->getId()]['invert_amount'])) { $partReverse = true; continue; } $creditPosition = clone $invoicePosition; $creditPosition->__set('id', null); $creditPosition->__set('position_nr', ++$countPos); $creditPosition->__set('name', $creditPosition->__get('name') . ' -STORNO'); if (is_array($aOrderPosData) && array_key_exists($invoicePosition->getId(), $aOrderPosData) && $aOrderPosData[$invoicePosition->getId()]['invert_amount']) { $creditPosition->__set('amount', $aOrderPosData[$invoicePosition->getId()]['invert_amount']); } $opController->invert($creditPosition); $creditPosition->flatten(); $creditPositions[] = $opController->create($creditPosition); } $rpController->addOrderPositions($creditReceipt, $creditPositions); $creditReceipt = Billing_Controller_Receipt::getInstance()->get($creditReceipt->getId()); /* <value>REVERTED</value> <value>PARTLYREVERTED</value> <value>ISREVERSION</value> <value>ISPARTREVERSION</value> */ $receipt->__set('receipt_state', 'REVERTED'); $creditReceipt->__set('receipt_state', 'ISREVERSION'); $receipt->__set('revision_receipt_id', $creditReceipt->getId()); $creditReceipt->__set('revision_receipt_id', $receipt->getId()); //$creditReceipt->__set('payment_state', 'PAYED'); $creditReceipt->__set('open_sum', -1 * (double) $receipt->__get('open_sum')); //$creditReceipt->__set('payed_sum',$creditReceipt->__get('total_brutto')); $creditReceipt->payTotal(); if ($partReverse) { $receipt->__set('payment_state', 'PARTLYPAYED'); $receipt->__set('receipt_state', 'PARTLYREVERTED'); $creditReceipt->__set('receipt_state', 'ISPARTREVERSION'); $receipt->payValue($creditReceipt->__get('total_brutto')); } else { try { $receipt->payTotal(); } catch (Exception $e) { // @todo: silent failure: check OK } } $creditReceipt->__set('donation_id', $receipt->getForeignId('donation_id')); $creditReceipt->__set('reversion_record_id', $receipt->getId()); $creditReceipt->__set('revision_receipt_id', $receipt->getId()); $receipt->__set('reversion_record_id', $creditReceipt->getId()); $receipt->__set('revision_receipt_id', $creditReceipt->getId()); $receipt = $rController->update($receipt); $tags = $receipt->__get('tags'); if ($tags) { $creditReceipt->__set('tags', $tags->toArray()); } $creditReceipt = $rController->update($creditReceipt); \org\sopen\dev\DebugLogger::log('RECHNUNG_update ' . print_r($receipt, true)); \org\sopen\dev\DebugLogger::log('GUTSCHRIFT ' . print_r($creditReceipt, true)); Tinebase_Event::fireEvent(new Billing_Events_BillableReceiptCreated($creditReceipt)); Tinebase_Event::fireEvent(new Billing_Events_BillableReceiptReverted($receipt, $creditReceipt)); \org\sopen\dev\DebugLogger::close(); return $creditReceipt; }