protected function _execute() { if (!$this->_transaction_purchase_account_id) { throw new Exception("INTERNAL ERROR: Could not find default PO account."); } if (!$this->_transaction_purchase_line_account_id) { throw new Exception("INTERNAL ERROR: Could not find default PO Line account."); } if (!$this->_transaction_purchase_prepaid_purchase_account_id) { throw new Exception("INTERNAL ERROR: Could not find default deferred asset account."); } if (!$this->_transaction->loaded()) { throw new Exception("Transaction could not be found."); } if (!isset($this->_data->payment_account_id)) { throw new Exception("Invalid payment account ID: none provided."); } $payment_account = $this->_load_account($this->_data->payment_account_id); if (!$payment_account->loaded()) { throw new Exception("Invalid payment account ID: not found."); } if (!$payment_account->payment) { throw new Exception("Invalid payment account ID: account must be marked as payment."); } if (!$this->_data->amount) { throw new Exception("Invalid payment amount: none provided."); } // Formulate data request object for Beans_Account_Transaction_Create $update_transaction_data = new stdClass(); $update_transaction_data->code = $this->_transaction->code; $update_transaction_data->description = isset($this->_data->description) ? $this->_data->description : NULL; $update_transaction_data->date = isset($this->_data->date) ? $this->_data->date : $this->_transaction->date; $update_transaction_data->reference = isset($this->_data->check_number) ? $this->_data->check_number : $this->_transaction->reference; $update_transaction_data->payment = "vendor"; $purchase_account_transfers = array(); $purchase_account_transfers_forms = array(); $purchase_account_transfer_total = 0.0; $writeoff_account_transfer_total = 0.0; $writeoff_account_transfers_forms = array(); // Write once for cleaner code $purchase_account_transfers[$this->_transaction_purchase_account_id] = 0.0; $purchase_account_transfers_forms[$this->_transaction_purchase_account_id] = array(); $purchase_account_transfers[$this->_transaction_purchase_line_account_id] = 0.0; $purchase_account_transfers_forms[$this->_transaction_purchase_line_account_id] = array(); $purchase_account_transfers[$this->_transaction_purchase_prepaid_purchase_account_id] = 0.0; $purchase_account_transfers_forms[$this->_transaction_purchase_prepaid_purchase_account_id] = array(); if (!$this->_data->purchases or !count($this->_data->purchases)) { throw new Exception("Please provide at least one purchase for this payment."); } $vendor_id = FALSE; $handles_purchases_ids = array(); foreach ($this->_data->purchases as $purchase_payment) { if (!isset($purchase_payment->purchase_id) or !$purchase_payment->purchase_id) { throw new Exception("Invalid payment purchase ID: none provided."); } $purchase = $this->_load_vendor_purchase($purchase_payment->purchase_id); if (!$purchase->loaded()) { throw new Exception("Invalid payment purchase: purchase not found."); } if (!$purchase_payment->amount) { throw new Exception("Invalid payment purchase amount: none provided."); } if (in_array($purchase->id, $handles_purchases_ids)) { throw new Exception("Invalid payment purchase: PO ID " . $purchase->id . " cannot be in payment more than once."); } $handles_purchases_ids[] = $purchase->id; if (!$vendor_id) { $vendor_id = $purchase->entity_id; } else { if ($vendor_id != $purchase->entity_id) { throw new Exception("Invalid payment purchase " . $purchase->code . " included: vendor mismatch. All purchase purchases must belong to the same vendor."); } } if (!$purchase->date_billed and !$purchase->invoice_transaction_id and (isset($purchase_payment->invoice_number) and $purchase_payment->invoice_number or isset($purchase_payment->date_billed) and $purchase_payment->date_billed)) { $vendor_purchase_invoice = new Beans_Vendor_Purchase_Invoice($this->_beans_data_auth((object) array('id' => $purchase->id, 'invoice_number' => $purchase_payment->invoice_number, 'date_billed' => $purchase_payment->date_billed, 'validate_only' => $this->_validate_only))); $vendor_purchase_invoice_result = $vendor_purchase_invoice->execute(); if (!$vendor_purchase_invoice_result->success) { throw new Exception("Invalid purchase order invoice information for " . $purchase->code . ": " . $vendor_purchase_invoice_result->error); } // Reload the purchase $purchase = $this->_load_vendor_purchase($purchase_payment->purchase_id); } else { if ($purchase->date_billed and $purchase->invoice_transaction_id and (isset($purchase_payment->invoice_number) and $purchase_payment->invoice_number)) { $vendor_purchase_update_invoice = new Beans_Vendor_Purchase_Update_Invoice($this->_beans_data_auth((object) array('id' => $purchase->id, 'invoice_number' => $purchase_payment->invoice_number, 'validate_only' => $this->_validate_only))); $vendor_purchase_update_invoice_result = $vendor_purchase_update_invoice->execute(); if (!$vendor_purchase_update_invoice_result->success) { throw new Exception("Invalid purchase order invoice information for " . $purchase->code . ": " . $vendor_purchase_update_invoice_result->error); } // Reload the purchase $purchase = $this->_load_vendor_purchase($purchase_payment->purchase_id); } } if ($this->_validate_only) { return (object) array(); } $purchase_id = $purchase->id; $purchase_balance = $this->_get_form_effective_balance($purchase, $update_transaction_data->date, $this->_transaction->id); $purchase_transfer_amount = $purchase_payment->amount; $purchase_writeoff_amount = (isset($purchase_payment->writeoff_balance) and $purchase_payment->writeoff_balance) ? $this->_beans_round($purchase_balance - $purchase_transfer_amount) : FALSE; $purchase_payment_amount = $purchase_writeoff_amount ? $this->_beans_round($purchase_transfer_amount + $purchase_writeoff_amount) : $purchase_transfer_amount; // Apply to Realized Accounts if ($purchase->date_billed and $purchase->invoice_transaction_id and strtotime($purchase->date_billed) <= strtotime($update_transaction_data->date) or $purchase->date_cancelled and $purchase->cancel_transaction_id and strtotime($purchase->date_cancelled) <= strtotime($update_transaction_data->date)) { // AP if (!isset($purchase_account_transfers[$purchase->account_id])) { $purchase_account_transfers[$purchase->account_id] = 0.0; } if (!isset($purchase_account_transfers_forms[$purchase->account_id])) { $purchase_account_transfers_forms[$purchase->account_id] = array(); } $purchase_account_transfers[$purchase->account_id] = $this->_beans_round($purchase_account_transfers[$purchase->account_id] + $purchase_payment_amount); // Writeoff if ($purchase_writeoff_amount) { $writeoff_account_transfer_total = $this->_beans_round($writeoff_account_transfer_total + $purchase_writeoff_amount); } $purchase_account_transfers_forms[$purchase->account_id][] = (object) array("form_id" => $purchase_id, "amount" => $purchase_payment_amount * -1, "writeoff_amount" => $purchase_writeoff_amount ? $purchase_writeoff_amount * -1 : NULL); } else { // Pending AP $purchase_account_transfers[$this->_transaction_purchase_account_id] = $this->_beans_round($purchase_account_transfers[$this->_transaction_purchase_account_id] + $purchase_payment_amount); // Pending AP $purchase_account_transfers[$this->_transaction_purchase_line_account_id] = $this->_beans_round($purchase_account_transfers[$this->_transaction_purchase_line_account_id] - $purchase_payment_amount); // Pending COGS $purchase_account_transfers[$this->_transaction_purchase_prepaid_purchase_account_id] = $this->_beans_round($purchase_account_transfers[$this->_transaction_purchase_prepaid_purchase_account_id] + $purchase_payment_amount); // Writeoff if ($purchase_writeoff_amount) { $writeoff_account_transfer_total = $this->_beans_round($writeoff_account_transfer_total + $purchase_writeoff_amount); } $purchase_account_transfers_forms[$this->_transaction_purchase_account_id][] = (object) array("form_id" => $purchase_id, "amount" => $purchase_payment_amount * -1, "writeoff_amount" => $purchase_writeoff_amount ? $purchase_writeoff_amount * -1 : NULL); } } $vendor = $this->_load_vendor($vendor_id); // Keep the description clean. if ($update_transaction_data->description) { $update_transaction_data->description = strpos($update_transaction_data->description, "Vendor Payment Recorded: ") !== FALSE ? $update_transaction_data->description : "Vendor Payment Recorded: " . $update_transaction_data->description; } else { $update_transaction_data->description = "Vendor Payment Recorded: " . $vendor->company_name; } $writeoff_account = FALSE; if ($writeoff_account_transfer_total != 0.0) { // We need to add in a write-off. if (!isset($this->_data->writeoff_account_id)) { throw new Exception("Invalid payment write-off account ID: none provided."); } $writeoff_account = $this->_load_account($this->_data->writeoff_account_id); if (!$writeoff_account->loaded()) { throw new Exception("Invalid payment write-off account ID: account not found."); } if (!$writeoff_account->writeoff) { throw new Exception("Invalid payment write-off account ID: account must be marked as write-off."); } if (isset($purchase_account_transfers[$writeoff_account->id])) { throw new Exception("Invalid payment write-off account ID: account cannot be tied to any other transaction in the payment."); } $purchase_account_transfers[$writeoff_account->id] = $writeoff_account_transfer_total; $purchase_account_transfers_forms[$writeoff_account->id] = $writeoff_account_transfers_forms; } $adjustment_account = FALSE; if (isset($this->_data->adjustment_amount) and $this->_data->adjustment_amount != 0.0) { if (!isset($this->_data->adjustment_account_id) or !$this->_data->adjustment_account_id) { throw new Exception("Invalid adjustment account ID: none provided."); } $adjustment_account = $this->_load_account($this->_data->adjustment_account_id); if (!$adjustment_account->loaded()) { throw new Exception("Invalid adjustment account ID: account not found."); } if (isset($purchase_account_transfers[$adjustment_account->id])) { throw new Exception("Invalid adjustment account ID: account cannot be tied to any other transaction in the payment."); } $purchase_account_transfers[$adjustment_account->id] = $this->_data->adjustment_amount * -1; } // All of the accounts on purchases are Accounts Payable and should be assets. // But to be on the safe side we're going to do table sign adjustments to be on the safe side. foreach ($purchase_account_transfers as $account_id => $transfer_amount) { $account = $this->_load_account($account_id); if (!$account->loaded()) { throw new Exception("System error: could not load account with ID " . $account_id); } $purchase_account_transfers[$account_id] = ($writeoff_account and $writeoff_account->id == $account_id or $adjustment_account and $adjustment_account->id == $account_id) ? $transfer_amount * -1 * $payment_account->account_type->table_sign : $transfer_amount * $payment_account->account_type->table_sign; } $purchase_account_transfers[$payment_account->id] = $this->_data->amount * -1 * $payment_account->account_type->table_sign; if ($payment_account->account_type->table_sign > 0) { foreach ($purchase_account_transfers as $account_id => $transfer_amount) { $purchase_account_transfers[$account_id] = $transfer_amount * -1; } } $update_transaction_data->account_transactions = array(); foreach ($purchase_account_transfers as $account_id => $amount) { $account_transaction = new stdClass(); $account_transaction->account_id = $account_id; $account_transaction->amount = $amount; if ($account_transaction->account_id == $payment_account->id) { $account_transaction->transfer = TRUE; } if ($writeoff_account and $account_transaction->account_id == $writeoff_account->id) { $account_transaction->writeoff = TRUE; } if ($adjustment_account and $account_transaction->account_id == $adjustment_account->id) { $account_transaction->adjustment = TRUE; } if (isset($purchase_account_transfers_forms[$account_id])) { $account_transaction->forms = array(); foreach ($purchase_account_transfers_forms[$account_id] as $form) { $account_transaction->forms[] = (object) array('form_id' => $form->form_id, 'amount' => $form->amount, 'writeoff_amount' => $form->writeoff_amount); } } $update_transaction_data->account_transactions[] = $account_transaction; } $update_transaction_data->id = $this->_transaction->id; $update_transaction_data->payment_type_handled = 'vendor'; $update_transaction_data->entity_id = $vendor_id; $update_transaction = new Beans_Account_Transaction_Update($this->_beans_data_auth($update_transaction_data)); $update_transaction_result = $update_transaction->execute(); if (!$update_transaction_result->success) { throw new Exception("Update failure - could not convert transaction to payment: " . $update_transaction_result->error); } // Recalibrate Vendor Invoices / Cancellations $vendor_purchase_calibrate_invoice = new Beans_Vendor_Purchase_Calibrate_Invoice($this->_beans_data_auth((object) array('ids' => $handles_purchases_ids))); $vendor_purchase_calibrate_invoice_result = $vendor_purchase_calibrate_invoice->execute(); if (!$vendor_purchase_calibrate_invoice_result->success) { throw new Exception("UNEXPECTED ERROR: COULD NOT CALIBRATE VENDOR PURCHASES: " . $vendor_purchase_calibrate_invoice_result->error); } // Recalibrate Vendor Invoices / Cancellations $vendor_purchase_calibrate_cancel = new Beans_Vendor_Purchase_Calibrate_Cancel($this->_beans_data_auth((object) array('ids' => $handles_purchases_ids))); $vendor_purchase_calibrate_cancel_result = $vendor_purchase_calibrate_cancel->execute(); if (!$vendor_purchase_calibrate_cancel_result->success) { throw new Exception("UNEXPECTED ERROR: COULD NOT CALIBRATE VENDOR PURCHASES: " . $vendor_purchase_calibrate_cancel_result->error); } // Recalibrate any payments tied to these purchases AFTER this transaction. $vendor_payment_calibrate = new Beans_Vendor_Payment_Calibrate($this->_beans_data_auth((object) array('form_ids' => $handles_purchases_ids, 'after_payment_id' => $update_transaction_result->data->transaction->id))); $vendor_payment_calibrate_result = $vendor_payment_calibrate->execute(); if (!$vendor_payment_calibrate_result->success) { throw new Exception("UNEXPECTED ERROR: COULD NOT CALIBRATE VENDOR PAYMENTS: " . $vendor_payment_calibrate_result->error); } return (object) array("payment" => $this->_return_vendor_payment_element($this->_load_vendor_payment($update_transaction_result->data->transaction->id))); }
protected function _calibrate_purchase_cancel($purchase) { // Should be impossible - but catches bugs from the above query... if (!$purchase->date_cancelled) { return; } // If the books have been closed for the active date, we have to assume that due-diligence has been done // to prevent a bad transaction from being put into the journal and simply move on. if ($this->_check_books_closed($purchase->date_cancelled)) { return; } $purchase_cancel_transaction_data = new stdClass(); $purchase_cancel_transaction_data->code = $purchase->code; $purchase_cancel_transaction_data->description = "Purchase Cancelled " . $purchase->code; $purchase_cancel_transaction_data->date = $purchase->date_cancelled; $purchase_cancel_transaction_data->account_transactions = array(); $purchase_cancel_transaction_data->entity_id = $purchase->entity_id; $purchase_cancel_transaction_data->form_type = 'purchase'; $purchase_cancel_transaction_data->form_id = $purchase->id; $account_transactions = array(); $purchase_line_total = $purchase->total; // These two could be moved into the else {} block below $purchase_balance = $this->_get_form_effective_balance($purchase, $purchase->date_cancelled, $purchase->cancel_transaction_id); $purchase_paid = $purchase_line_total - $purchase_balance; // If invoiced - we reverse the AP accounts. if ($purchase->date_billed) { $account_transactions[$purchase->account_id] = $purchase_line_total * -1; foreach ($purchase->form_lines->find_all() as $purchase_line) { if (!isset($account_transactions[$purchase_line->account_id])) { $account_transactions[$purchase_line->account_id] = 0.0; } $account_transactions[$purchase_line->account_id] = $this->_beans_round($account_transactions[$purchase_line->account_id] + $purchase_line->total); } } else { // AP Transfers $account_transactions[$this->_transaction_purchase_account_id] = $purchase_balance * -1; $account_transactions[$purchase->account_id] = $purchase_paid; // Line Item Transfers $account_transactions[$this->_transaction_purchase_line_account_id] = $purchase_balance; $account_transactions[$this->_transaction_purchase_prepaid_purchase_account_id] = $purchase_paid * -1; } foreach ($account_transactions as $account_id => $amount) { if ($purchase->total == 0.0 || $amount != 0.0) { $account_transaction = new stdClass(); $account_transaction->account_id = $account_id; $account_transaction->amount = $amount; if ($account_transaction->account_id == $this->_transaction_purchase_account_id or $account_transaction->account_id == $purchase->account_id) { $account_transaction->forms = array((object) array("form_id" => $purchase->id, "amount" => $account_transaction->amount)); } $purchase_cancel_transaction_data->account_transactions[] = $account_transaction; } } $purchase_invoice_transaction_result = FALSE; if ($purchase->cancel_transaction_id) { $purchase_cancel_transaction_data->id = $purchase->cancel_transaction_id; $purchase_cancel_transaction_data->form_type_handled = "purchase"; $purchase_cancel_transaction = new Beans_Account_Transaction_Update($this->_beans_data_auth($purchase_cancel_transaction_data)); $purchase_cancel_transaction_result = $purchase_cancel_transaction->execute(); } else { $purchase_cancel_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($purchase_cancel_transaction_data)); $purchase_cancel_transaction_result = $purchase_cancel_transaction->execute(); } if (!$purchase_cancel_transaction_result->success) { throw new Exception("Error creating purchase cancellation transaction in journal: " . "TOTAL: " . $purchase_line_total . "\n<br>" . "BALANCE: " . $purchase_balance . "\n<br>" . "PAID: " . $purchase_paid . "\n<br>" . $purchase_cancel_transaction_result->error . "<br><br><br>\n\n\n" . print_r($purchase_cancel_transaction_data->account_transactions, TRUE)); } if (!$purchase->cancel_transaction_id) { $purchase->cancel_transaction_id = $purchase_cancel_transaction_result->data->transaction->id; $purchase->save(); } }
protected function _execute() { if (!$this->_transaction_sale_account_id) { throw new Exception("INTERNAL ERROR: Could not find default SO receivable account."); } if (!$this->_transaction_sale_line_account_id) { throw new Exception("INTERNAL ERROR: Could not find default SO line account."); } if (!$this->_transaction_sale_tax_account_id) { throw new Exception("INTERNAL ERROR: Could not find default SO tax account."); } if (!$this->_transaction_sale_deferred_income_account_id) { throw new Exception("INTERNAL ERROR: Could not find default SO deferred income account."); } if (!$this->_transaction_sale_deferred_liability_account_id) { throw new Exception("INTERNAL ERROR: Could not find default SO deferred liability account."); } if (!$this->_transaction->loaded()) { throw new Exception("Transaction could not be found."); } if (!isset($this->_data->deposit_account_id)) { throw new Exception("Invalid payment deposit account ID: none provided."); } $deposit_account = $this->_load_account($this->_data->deposit_account_id); if (!$deposit_account->loaded()) { throw new Exception("Invalid payment deposit account ID: not found."); } if (!$deposit_account->deposit) { throw new Exception("Invalid payment deposit account ID: account must be marked as deposit."); } if (!$this->_data->amount) { throw new Exception("Invalid payment amount: none provided."); } // Create Transaction Data $update_transaction_data = new stdClass(); // Preserve transaction code. $update_transaction_data->code = $this->_transaction->code; $update_transaction_data->description = isset($this->_data->description) ? $this->_data->description : NULL; $update_transaction_data->description = strpos($update_transaction_data->description, "Customer Payment Recorded") !== FALSE ? $update_transaction_data->description : "Customer Payment Recorded" . ($update_transaction_data->description ? ': ' . $update_transaction_data->description : ''); $update_transaction_data->date = isset($this->_data->date) ? $this->_data->date : $this->_transaction->date; $update_transaction_data->payment = "customer"; $sale_account_transfers = array(); $sale_account_transfers_forms = array(); $writeoff_account_transfer_total = 0.0; $writeoff_account_transfers_forms = array(); if (!$this->_data->sales or !count($this->_data->sales)) { throw new Exception("Please provide at least one sale for this payment."); } // Ensure that we're not duplicating sales within a payment. $handled_sales_ids = array(); foreach ($this->_data->sales as $sale_payment) { if (!isset($sale_payment->sale_id) or !$sale_payment->sale_id) { throw new Exception("Invalid payment sale ID: none provided."); } $sale = $this->_load_customer_sale($sale_payment->sale_id); if (!$sale->loaded()) { throw new Exception("Invalid payment sale: sale not found."); } if (!$sale_payment->amount) { throw new Exception("Invalid payment sale amount: none provided."); } if (in_array($sale->id, $handled_sales_ids)) { throw new Exception("Invalid payment sale: sale ID " . $sale->id . " cannot be in payment more than once."); } if (strtotime($sale->date_created) > strtotime($update_transaction_data->date)) { throw new Exception("Invalid payment sale: sale ID " . $sale->id . " cannot be paid before its creation date: " . $sale->date_created . "."); } $handled_sales_ids[] = $sale->id; $sale_id = $sale->id; // Get the sale total, tax total, and balance as of the payment date. $sale_line_total = $sale->amount; $sale_tax_total = $this->_beans_round($sale->total - $sale->amount); $sale_balance = $this->_get_form_effective_balance($sale, $update_transaction_data->date, $this->_transaction->id); // This makes the math a bit easier to read. $sale_paid = $sale->total + $sale_balance; // Money Received / Paid = Bank $sale_transfer_amount = $sale_payment->amount; $sale_writeoff_amount = (isset($sale_payment->writeoff_balance) and $sale_payment->writeoff_balance) ? $this->_beans_round(0.0 - $sale_balance - $sale_transfer_amount) : FALSE; // AR Adjustment $sale_payment_amount = $sale_writeoff_amount ? $this->_beans_round($sale_transfer_amount + $sale_writeoff_amount) : $sale_transfer_amount; // Another variable to simplify code. $sale_transaction_account_id = FALSE; if ($sale->date_billed and $sale->invoice_transaction_id and (strtotime($sale->date_billed) < strtotime($update_transaction_data->date) or $sale->date_billed == $update_transaction_data->date && $sale->invoice_transaction_id < $this->_transaction->id) or $sale->date_cancelled and $sale->cancel_transaction_id and (strtotime($sale->date_cancelled) < strtotime($update_transaction_data->date) or $sale->date_cancelled == $update_transaction_data->date && $sale->invoice_transaction_id < $this->_transaction->id)) { // Sale AR $sale_transaction_account_id = $sale->account_id; if (!isset($sale_account_transfers[$sale_transaction_account_id])) { $sale_account_transfers[$sale_transaction_account_id] = 0.0; } $sale_account_transfers[$sale_transaction_account_id] = $this->_beans_round($sale_account_transfers[$sale_transaction_account_id] + $sale_payment_amount); if (!isset($sale_account_transfers_forms[$sale_transaction_account_id])) { $sale_account_transfers_forms[$sale_transaction_account_id] = array(); } $sale_account_transfers_forms[$sale_transaction_account_id][] = (object) array("form_id" => $sale_id, "amount" => $sale_payment_amount, "writeoff_amount" => $sale_writeoff_amount ? $sale_writeoff_amount : NULL); } else { $deferred_amounts = $this->_calculate_deferred_payment($sale_payment_amount, $sale_paid, $sale_line_total, $sale_tax_total); $income_transfer_amount = $deferred_amounts->income_transfer_amount; $tax_transfer_amount = $deferred_amounts->tax_transfer_amount; if ($income_transfer_amount) { if (!isset($sale_account_transfers[$this->_transaction_sale_deferred_income_account_id])) { $sale_account_transfers[$this->_transaction_sale_deferred_income_account_id] = 0.0; } if (!isset($sale_account_transfers[$this->_transaction_sale_line_account_id])) { $sale_account_transfers[$this->_transaction_sale_line_account_id] = 0.0; } $sale_account_transfers[$this->_transaction_sale_deferred_income_account_id] = $this->_beans_round($sale_account_transfers[$this->_transaction_sale_deferred_income_account_id] + $income_transfer_amount); $sale_account_transfers[$this->_transaction_sale_line_account_id] = $this->_beans_round($sale_account_transfers[$this->_transaction_sale_line_account_id] - $income_transfer_amount); } if ($tax_transfer_amount) { if (!isset($sale_account_transfers[$this->_transaction_sale_deferred_liability_account_id])) { $sale_account_transfers[$this->_transaction_sale_deferred_liability_account_id] = 0.0; } if (!isset($sale_account_transfers[$this->_transaction_sale_tax_account_id])) { $sale_account_transfers[$this->_transaction_sale_tax_account_id] = 0.0; } $sale_account_transfers[$this->_transaction_sale_deferred_liability_account_id] = $this->_beans_round($sale_account_transfers[$this->_transaction_sale_deferred_liability_account_id] + $tax_transfer_amount); $sale_account_transfers[$this->_transaction_sale_tax_account_id] = $this->_beans_round($sale_account_transfers[$this->_transaction_sale_tax_account_id] - $tax_transfer_amount); } if (!isset($sale_account_transfers[$this->_transaction_sale_account_id])) { $sale_account_transfers[$this->_transaction_sale_account_id] = 0.0; } $sale_account_transfers[$this->_transaction_sale_account_id] = $this->_beans_round($sale_account_transfers[$this->_transaction_sale_account_id] + $sale_payment_amount); if (!isset($sale_account_transfers_forms[$this->_transaction_sale_account_id])) { $sale_account_transfers_forms[$this->_transaction_sale_account_id] = array(); } $sale_account_transfers_forms[$this->_transaction_sale_account_id][] = (object) array("form_id" => $sale_id, "amount" => $sale_payment_amount, "writeoff_amount" => $sale_writeoff_amount ? $sale_writeoff_amount : NULL); } if ($sale_writeoff_amount) { $writeoff_account_transfer_total = $this->_beans_round($writeoff_account_transfer_total + $sale_writeoff_amount); } } $writeoff_account = FALSE; if ($writeoff_account_transfer_total != 0.0) { // We need to add in a write-off. if (!$this->_data->writeoff_account_id) { throw new Exception("Invalid payment write-off account ID: none provided."); } $writeoff_account = $this->_load_account($this->_data->writeoff_account_id); if (!$writeoff_account->loaded()) { throw new Exception("Invalid payment write-off account ID: account not found."); } if (!$writeoff_account->writeoff) { throw new Exception("Invalid payment write-off account ID: account must be marked as write-off."); } if (isset($sale_account_transfers[$writeoff_account->id])) { throw new Exception("Invalid payment write-off account ID: account cannot be tied to any other transaction in the payment."); } $sale_account_transfers[$writeoff_account->id] = $writeoff_account_transfer_total; $sale_account_transfers_forms[$writeoff_account->id] = $writeoff_account_transfers_forms; } $adjustment_account = FALSE; if (isset($this->_data->adjustment_amount) and $this->_data->adjustment_amount != 0.0) { if (!isset($this->_data->adjustment_account_id) or !$this->_data->adjustment_account_id) { throw new Exception("Invalid adjustment account ID: none provided."); } $adjustment_account = $this->_load_account($this->_data->adjustment_account_id); if (!$adjustment_account->loaded()) { throw new Exception("Invalid adjustment account ID: account not found."); } if (isset($sale_account_transfers[$adjustment_account->id])) { throw new Exception("Invalid adjustment account ID: account cannot be tied to any other transaction in the payment."); } $sale_account_transfers[$adjustment_account->id] = $this->_data->adjustment_amount * -1; } // All of the accounts on sales are Accounts Receivable and should be assets. // But to be on the safe side we're going to do table sign adjustments. foreach ($sale_account_transfers as $account_id => $transfer_amount) { $account = $this->_load_account($account_id); if (!$account->loaded()) { throw new Exception("System error: could not load account with ID " . $account_id); } $sale_account_transfers[$account_id] = ($writeoff_account and $writeoff_account->id == $account_id or $adjustment_account and $adjustment_account->id == $account_id) ? $transfer_amount * $deposit_account->account_type->table_sign : $transfer_amount * -1 * $deposit_account->account_type->table_sign; } // V2Item - Consider validating amount to avoid non-zero errors... $sale_account_transfers[$deposit_account->id] = $this->_data->amount * $deposit_account->account_type->table_sign; $update_transaction_data->account_transactions = array(); foreach ($sale_account_transfers as $account_id => $amount) { $account_transaction = new stdClass(); $account_transaction->account_id = $account_id; $account_transaction->amount = $amount; if ($account_transaction->account_id == $deposit_account->id) { $account_transaction->transfer = TRUE; } if ($writeoff_account and $account_transaction->account_id == $writeoff_account->id) { $account_transaction->writeoff = TRUE; } if ($adjustment_account and $account_transaction->account_id == $adjustment_account->id) { $account_transaction->adjustment = TRUE; } if (isset($sale_account_transfers_forms[$account_id])) { $account_transaction->forms = array(); foreach ($sale_account_transfers_forms[$account_id] as $form) { $account_transaction->forms[] = (object) array('form_id' => $form->form_id, 'amount' => $form->amount, 'writeoff_amount' => $form->writeoff_amount); } } $update_transaction_data->account_transactions[] = $account_transaction; } $update_transaction_data->id = $this->_transaction->id; $update_transaction_data->payment_type_handled = 'customer'; $update_transaction = new Beans_Account_Transaction_Update($this->_beans_data_auth($update_transaction_data)); $update_transaction_result = $update_transaction->execute(); if (!$update_transaction_result->success) { throw new Exception("Update failure - could not convert transaction to payment: " . $update_transaction_result->error); } // Recalibrate Customer Invoices / Cancellations $customer_sale_calibrate_invoice = new Beans_customer_Sale_Calibrate_Invoice($this->_beans_data_auth((object) array('ids' => $handled_sales_ids))); $customer_sale_calibrate_invoice_result = $customer_sale_calibrate_invoice->execute(); if (!$customer_sale_calibrate_invoice_result->success) { throw new Exception("UNEXPECTED ERROR: COULD NOT CALIBRATE CUSTOMER SALES: " . $customer_sale_calibrate_invoice_result->error); } // Recalibrate Customer Invoices / Cancellations $customer_sale_calibrate_cancel = new Beans_customer_Sale_Calibrate_Cancel($this->_beans_data_auth((object) array('ids' => $handled_sales_ids))); $customer_sale_calibrate_cancel_result = $customer_sale_calibrate_cancel->execute(); if (!$customer_sale_calibrate_cancel_result->success) { throw new Exception("UNEXPECTED ERROR: COULD NOT CALIBRATE CUSTOMER SALES: " . $customer_sale_calibrate_cancel_result->error); } // Recalibrate any payments tied to these sales AFTER this transaction date. $customer_payment_calibrate = new Beans_Customer_Payment_Calibrate($this->_beans_data_auth((object) array('form_ids' => $handled_sales_ids, 'after_payment_id' => $this->_transaction->id))); $customer_payment_calibrate_result = $customer_payment_calibrate->execute(); if (!$customer_payment_calibrate_result->success) { throw new Exception("UNEXPECTED ERROR: COULD NOT CALIBRATE CUSTOMER PAYMENTS: " . $customer_sale_calibrate_result->error); } return (object) array("payment" => $this->_return_customer_payment_element($this->_load_customer_payment($update_transaction_result->data->transaction->id))); }
protected function _calibrate_sale_invoice($sale) { // Just to be safe in case the above passes a bad sale. if (!$sale->date_billed) { return; } // If the books have been closed for the active date, we have to assume that due-diligence has been done // to prevent a bad transaction from being put into the journal and simply move on. if ($this->_check_books_closed($sale->date_billed)) { return; } $sale_invoice_transaction_data = new stdClass(); $sale_invoice_transaction_data->code = $sale->code; $sale_invoice_transaction_data->description = "Invoice - Sale " . $sale->code; $sale_invoice_transaction_data->date = $sale->date_billed; $sale_invoice_transaction_data->entity_id = $sale->entity_id; $sale_invoice_transaction_data->form_type = 'sale'; $sale_invoice_transaction_data->form_id = $sale->id; $account_transactions = array(); // Get some basics to create our split transaction. $sale_line_total = $sale->amount; $sale_tax_total = $this->_beans_round($sale->total - $sale->amount); // Get a bunch of values for our split... $sale_balance = $this->_get_form_effective_balance($sale, $sale->date_billed, $sale->invoice_transaction_id); $sale_paid = $sale->total + $sale_balance; $deferred_amounts = $this->_calculate_deferred_invoice($sale_paid, $sale_line_total, $sale_tax_total); $income_transfer_amount = $deferred_amounts->income_transfer_amount; $tax_transfer_amount = $deferred_amounts->tax_transfer_amount; // Fill transactions. $account_transactions[$this->_transaction_sale_account_id] = $sale_balance * -1; $account_transactions[$sale->account_id] = $sale_balance; // Deferred Income $account_transactions[$this->_transaction_sale_deferred_income_account_id] = $income_transfer_amount * -1; // Pending Income $account_transactions[$this->_transaction_sale_line_account_id] = -1 * $this->_beans_round($sale_line_total + $account_transactions[$this->_transaction_sale_deferred_income_account_id]); // Deferred Taxes $account_transactions[$this->_transaction_sale_deferred_liability_account_id] = $tax_transfer_amount * -1; // Pending Taxes $account_transactions[$this->_transaction_sale_tax_account_id] = -1 * $this->_beans_round($sale_tax_total + $account_transactions[$this->_transaction_sale_deferred_liability_account_id]); // Income Lines foreach ($sale->form_lines->find_all() as $sale_line) { if (!isset($account_transactions[$sale_line->account_id])) { $account_transactions[$sale_line->account_id] = 0.0; } $account_transactions[$sale_line->account_id] = $this->_beans_round($account_transactions[$sale_line->account_id] + $sale_line->total); } // Taxes $sale_tax_total = 0.0; foreach ($sale->form_taxes->find_all() as $sale_tax) { if (!isset($account_transactions[$sale_tax->tax->account_id])) { $account_transactions[$sale_tax->tax->account_id] = 0.0; } $account_transactions[$sale_tax->tax->account_id] = $this->_beans_round($account_transactions[$sale_tax->tax->account_id] + $sale_tax->total); } // Associate array over to objects. $sale_invoice_transaction_data->account_transactions = array(); foreach ($account_transactions as $account_id => $amount) { if ($sale->total == 0.0 || $amount != 0.0) { $account_transaction = new stdClass(); $account_transaction->account_id = $account_id; $account_transaction->amount = $amount; if ($account_id == $this->_transaction_sale_account_id or $account_id == $sale->account_id) { $account_transaction->forms = array((object) array("form_id" => $sale->id, "amount" => $account_transaction->amount)); } $sale_invoice_transaction_data->account_transactions[] = $account_transaction; } } $sale_invoice_transaction_result = FALSE; if ($sale->invoice_transaction_id) { $sale_invoice_transaction_data->id = $sale->invoice_transaction_id; $sale_invoice_transaction_data->form_type_handled = "sale"; $sale_invoice_transaction = new Beans_Account_Transaction_Update($this->_beans_data_auth($sale_invoice_transaction_data)); $sale_invoice_transaction_result = $sale_invoice_transaction->execute(); } else { $sale_invoice_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($sale_invoice_transaction_data)); $sale_invoice_transaction_result = $sale_invoice_transaction->execute(); } if (!$sale_invoice_transaction_result->success) { throw new Exception("Could not create invoice transaction: " . $sale_invoice_transaction_result->error); } if (!$sale->invoice_transaction_id) { $sale->invoice_transaction_id = $sale_invoice_transaction_result->data->transaction->id; $sale->save(); } }
protected function _calibrate_sale_cancel($sale) { // Just to be safe in case the above passes a bad sale. if (!$sale->date_cancelled) { return; } // If the books have been closed for the active date, we have to assume that due-diligence has been done // to prevent a bad transaction from being put into the journal and simply move on. if ($this->_check_books_closed($sale->date_cancelled)) { return; } $sale_cancel_transaction_data = new stdClass(); $sale_cancel_transaction_data->code = $sale->code; $sale_cancel_transaction_data->description = "Sale Cancelled " . $sale->code; $sale_cancel_transaction_data->date = $sale->date_cancelled; $sale_cancel_transaction_data->form_type = 'sale'; $sale_cancel_transaction_data->form_id = $sale->id; $sale_balance = $this->_get_form_effective_balance($sale, $sale->date_cancelled, $sale->cancel_transaction_id); $account_transactions = array(); // If Invoiced - We reverse the income & tax due, // and put the total into the AR account. if ($sale->date_billed) { // Total into AR $account_transactions[$sale->account_id] = $sale->total; // Income Lines foreach ($sale->form_lines->find_all() as $sale_line) { if (!isset($account_transactions[$sale_line->account_id])) { $account_transactions[$sale_line->account_id] = 0.0; } $account_transactions[$sale_line->account_id] = $this->_beans_round($account_transactions[$sale_line->account_id] - $sale_line->total); } // Taxes foreach ($sale->form_taxes->find_all() as $sale_tax) { if (!isset($account_transactions[$sale_tax->tax->account_id])) { $account_transactions[$sale_tax->tax->account_id] = 0.0; } $account_transactions[$sale_tax->tax->account_id] = $this->_beans_round($account_transactions[$sale_tax->tax->account_id] - $sale_tax->total); } } else { // Get some transfer values. // $sale_balance is defined above $sale_line_total = $sale->amount; $sale_tax_total = $this->_beans_round($sale->total - $sale->amount); $sale_paid = $sale->total + $sale_balance; $deferred_amounts = $this->_calculate_deferred_invoice($sale_paid, $sale_line_total, $sale_tax_total); $income_transfer_amount = $deferred_amounts->income_transfer_amount; $tax_transfer_amount = $deferred_amounts->tax_transfer_amount; // Total into Pending AR AND AR $account_transactions[$this->_transaction_sale_account_id] = -1 * $sale_balance; $account_transactions[$sale->account_id] = $sale_paid; // Deferred Income $account_transactions[$this->_transaction_sale_deferred_income_account_id] = $income_transfer_amount * -1; // Pending Income $account_transactions[$this->_transaction_sale_line_account_id] = -1 * $this->_beans_round($sale_line_total + $account_transactions[$this->_transaction_sale_deferred_income_account_id]); // Deferred Taxes $account_transactions[$this->_transaction_sale_deferred_liability_account_id] = $tax_transfer_amount * -1; // Pending Taxes $account_transactions[$this->_transaction_sale_tax_account_id] = -1 * $this->_beans_round($sale_tax_total + $account_transactions[$this->_transaction_sale_deferred_liability_account_id]); } $sale_cancel_transaction_data->account_transactions = array(); foreach ($account_transactions as $account_id => $amount) { // Cancelled sales are the one case where we want to make sure a 0.00 transaction // can go on the books to mark this as cancelled. if ($sale->total == 0.0 || $amount != 0.0) { $account_transaction = new stdClass(); $account_transaction->account_id = $account_id; $account_transaction->amount = $amount; if ($account_id == $this->_transaction_sale_account_id or $account_id == $sale->account_id) { $account_transaction->forms = array((object) array("form_id" => $sale->id, "amount" => $account_transaction->amount)); } $sale_cancel_transaction_data->account_transactions[] = $account_transaction; } } $sale_cancel_transaction_result = FALSE; if ($sale->cancel_transaction_id) { $sale_cancel_transaction_data->id = $sale->cancel_transaction_id; $sale_cancel_transaction_data->form_type_handled = "sale"; $sale_cancel_transaction = new Beans_Account_Transaction_Update($this->_beans_data_auth($sale_cancel_transaction_data)); $sale_cancel_transaction_result = $sale_cancel_transaction->execute(); } else { $sale_cancel_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($sale_cancel_transaction_data)); $sale_cancel_transaction_result = $sale_cancel_transaction->execute(); } if (!$sale_cancel_transaction_result->success) { throw new Exception("Error creating cancellation transaction in journal: " . $sale_cancel_transaction_result->error . "<br><br><br>\n\n\n" . print_r($sale_cancel_transaction_data->account_transactions, TRUE)); } if (!$sale->cancel_transaction_id) { $sale->cancel_transaction_id = $sale_cancel_transaction_result->data->transaction->id; $sale->save(); } }
protected function _calibrate_sale_create($sale) { // Just to be safe in case the above passes a bad sale. if (!$sale->date_created) { return; } // If the books have been closed for the active date, we have to assume that due-diligence has been done // to prevent a bad transaction from being put into the journal and simply move on. if ($this->_check_books_closed($sale->date_created)) { return; } $account_transactions = array($this->_transaction_sale_line_account_id => 0.0, $this->_transaction_sale_tax_account_id => 0.0, $this->_transaction_sale_account_id => 0.0); $account_transactions[$this->_transaction_sale_account_id] = $sale->total; foreach ($sale->form_lines->find_all() as $sale_line) { $account_transactions[$this->_transaction_sale_line_account_id] = $this->_beans_round($account_transactions[$this->_transaction_sale_line_account_id] + $sale_line->amount * $sale_line->quantity); } foreach ($sale->form_taxes->find_all() as $sale_tax) { $account_transactions[$this->_transaction_sale_tax_account_id] = $this->_beans_round($account_transactions[$this->_transaction_sale_tax_account_id] + $sale_tax->total); } $sale_create_transaction_data = new stdClass(); $sale_create_transaction_data->code = $sale->code; $sale_create_transaction_data->description = "Sale " . $sale->code; $sale_create_transaction_data->date = $sale->date_created; $sale_create_transaction_data->account_transactions = array(); $sale_create_transaction_data->entity_id = $sale->entity_id; $sale_create_transaction_data->form_type = 'sale'; $sale_create_transaction_data->form_id = $sale->id; foreach ($account_transactions as $account_id => $amount) { if ($sale->total == 0.0 || $amount != 0.0) { $account_transaction = new stdClass(); $account_transaction->account_id = $account_id; $account_transaction->amount = $account_id == $this->_transaction_sale_account_id ? $amount * -1 : $amount; // Realistically, this will only hit on the first condition, but the logic applies // throughout the form process. The AR or Pending AR account manages the form balance. if ($account_transaction->account_id == $this->_transaction_sale_account_id or $account_transaction->account_id == $sale->account_id) { // Add a form for the sale. // This updates the balance on the form. $account_transaction->forms = array((object) array("form_id" => $sale->id, "amount" => $account_transaction->amount)); } $sale_create_transaction_data->account_transactions[] = $account_transaction; } } $sale_create_transaction_result = FALSE; if ($sale->create_transaction_id) { $sale_create_transaction_data->id = $sale->create_transaction_id; $sale_create_transaction_data->form_type_handled = "sale"; $sale_create_transaction = new Beans_Account_Transaction_Update($this->_beans_data_auth($sale_create_transaction_data)); $sale_create_transaction_result = $sale_create_transaction->execute(); } else { $sale_create_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($sale_create_transaction_data)); $sale_create_transaction_result = $sale_create_transaction->execute(); } if (!$sale_create_transaction_result->success) { throw new Exception("Error creating sale transaction in journal: " . $sale_create_transaction_result->error . "<br><br><br>\n\n\n" . print_r($sale_create_transaction_data->account_transactions, TRUE)); } if (!$sale->create_transaction_id) { $sale->create_transaction_id = $sale_create_transaction_result->data->transaction->id; $sale->save(); } }
protected function _execute() { if (!$this->_transaction->loaded()) { throw new Exception("Transaction could not be found."); } if (!isset($this->_data->tax_id)) { throw new Exception("Invalid tax ID: none provided."); } $tax = $this->_load_tax($this->_data->tax_id); if (!$tax->loaded()) { throw new Exception("Invalid tax ID: not found."); } // Check for some basic data. if (!isset($this->_data->payment_account_id)) { throw new Exception("Invalid payment account ID: none provided."); } $payment_account = $this->_load_account($this->_data->payment_account_id); if (!$payment_account->loaded()) { throw new Exception("Invalid payment account ID: not found."); } if (!$payment_account->payment) { throw new Exception("Invalid payment account ID: account must be marked as payment."); } if (!isset($this->_data->amount) || !strlen($this->_data->amount)) { throw new Exception("Invalid payment amount: none provided."); } if (!isset($this->_data->total) || !strlen($this->_data->total)) { throw new Exception("Invalid payment total: none provided."); } $this->_payment->amount = $this->_data->amount; $this->_payment->tax_id = $tax->id; $this->_payment->date = isset($this->_data->date) ? $this->_data->date : NULL; $this->_payment->date_start = isset($this->_data->date_start) ? $this->_data->date_start : NULL; $this->_payment->date_end = isset($this->_data->date_end) ? $this->_data->date_end : NULL; $this->_payment->writeoff_amount = isset($this->_data->writeoff_amount) ? $this->_data->writeoff_amount : 0.0; $this->_validate_tax_payment($this->_payment); $tax_prep = new Beans_Tax_Prep($this->_beans_data_auth((object) array('date_start' => $this->_payment->date_start, 'date_end' => $this->_payment->date_end, 'id' => $this->_payment->tax_id))); $tax_prep_result = $tax_prep->execute(); if (!$tax_prep_result->success) { throw new Exception("Could not run tax prep: " . $tax_prep_result->error); } if ($tax_prep_result->data->taxes->due->net->amount != $this->_data->total) { throw new Exception("Invalid payment total: expected " . number_format($tax_prep_result->data->taxes->due->net->amount, 2, '.', '')); } // Find the transfer account and flip the value. $amount = FALSE; foreach ($this->_transaction->account_transactions->find_all() as $account_transaction) { if ($account_transaction->account_id == $payment_account->id) { $amount = $account_transaction->amount * -1 * $payment_account->account_type->table_sign; } } if (!$amount) { throw new Exception("There was an error in matching the payment account to that transaction."); } if ($this->_payment->amount != $amount) { throw new Exception("That transaction amount did not equal the payment amount."); } if ($this->_data->total != $this->_beans_round($this->_payment->amount + $this->_payment->writeoff_amount)) { throw new Exception("Payment amount and writeoff amount must total the payment total."); } // Kind of strange to the use case - but unless we can think of a good way to get // all affected tax_items returned in Beans_Tax_Prep - we have to do this here. $due_tax_items = ORM::Factory('tax_item')->where('tax_id', '=', $this->_payment->tax_id)->where('tax_payment_id', 'IS', NULL)->where('date', '<=', $this->_payment->date_end)->find_all(); $due_tax_items_total = 0.0; foreach ($due_tax_items as $due_tax_item) { $due_tax_items_total = $this->_beans_round($due_tax_items_total + $due_tax_item->total); } if ($due_tax_items_total != $this->_data->total) { throw new Exception("Unexpected error: tax item and payment totals do not match. Try re-running Beans_Tax_Prep."); } // Copy over the appropriate Tax_Prep information so that we know the state at which // this tax payment was created. Updates from this point forward will allow only changing // the payment amount and writeoff amount. $this->_payment->invoiced_line_amount = $tax_prep_result->data->taxes->due->invoiced->form_line_amount; $this->_payment->invoiced_line_taxable_amount = $tax_prep_result->data->taxes->due->invoiced->form_line_taxable_amount; $this->_payment->invoiced_amount = $tax_prep_result->data->taxes->due->invoiced->amount; $this->_payment->refunded_line_amount = $tax_prep_result->data->taxes->due->refunded->form_line_amount; $this->_payment->refunded_line_taxable_amount = $tax_prep_result->data->taxes->due->refunded->form_line_taxable_amount; $this->_payment->refunded_amount = $tax_prep_result->data->taxes->due->refunded->amount; $this->_payment->net_line_amount = $tax_prep_result->data->taxes->due->net->form_line_amount; $this->_payment->net_line_taxable_amount = $tax_prep_result->data->taxes->due->net->form_line_taxable_amount; $this->_payment->net_amount = $tax_prep_result->data->taxes->due->net->amount; // Delete old transaction // Formulate data request object for Beans_Account_Transaction_Create $update_transaction_data = new stdClass(); $update_transaction_data->code = $this->_transaction->code; // PRESERVE THIS $update_transaction_data->description = isset($this->_data->description) ? $this->_data->description : NULL; if (!$update_transaction_data->description) { $update_transaction_data->description = "Tax Remittance: " . $tax->name; } else { $update_transaction_data->description = "Tax Remittance: " . $update_transaction_data->description; } $update_transaction_data->date = isset($this->_data->date) ? $this->_data->date : NULL; $update_transaction_data->reference = isset($this->_data->check_number) ? $this->_data->check_number : NULL; if (!$update_transaction_data->code and $update_transaction_data->reference) { $update_transaction_data->code = $update_transaction_data->reference; } // Positive Payment = Negative to Balance $update_transaction_data->account_transactions = array(); // Payment Account $update_transaction_data->account_transactions[] = (object) array('account_id' => $payment_account->id, 'transfer' => TRUE, 'amount' => $this->_payment->amount * -1 * $payment_account->account_type->table_sign); if (isset($this->_data->writeoff_amount) and $this->_data->writeoff_amount != 0.0) { $writeoff_amount = isset($this->_data->writeoff_amount) ? $this->_data->writeoff_amount : NULL; $writeoff_account_id = isset($this->_data->writeoff_account_id) ? $this->_data->writeoff_account_id : NULL; if (!$writeoff_amount) { throw new Exception("That payment will require a specifc writeoff amount - please provide that value."); } if (!$writeoff_account_id) { throw new Exception("That payment will require a writeoff - please provide a writeoff account ID."); } $writeoff_account = $this->_load_account($writeoff_account_id); if (!$writeoff_account->loaded()) { throw new Exception("Invalid writeoff account: not found."); } if (!$writeoff_account->writeoff) { throw new Exception("Invalid writeoff account: must be marked as a valid writeoff account."); } $update_transaction_data->account_transactions[] = (object) array('account_id' => $writeoff_account->id, 'writeoff' => TRUE, 'amount' => $writeoff_amount * -1 * $payment_account->account_type->table_sign); $this->_payment->amount = $this->_beans_round($this->_payment->amount + $writeoff_amount); } // Tax Account $update_transaction_data->account_transactions[] = (object) array('account_id' => $tax->account_id, 'amount' => $this->_payment->amount * $payment_account->account_type->table_sign); // Make sure our data is good. $update_transaction_data->id = $this->_transaction->id; $update_transaction = new Beans_Account_Transaction_Update($this->_beans_data_auth($update_transaction_data)); $update_transaction_result = $update_transaction->execute(); if (!$update_transaction_result->success) { throw new Exception("An error occurred creating that tax payment: " . $update_transaction_result->error); } // Assign transaction to payment and save $this->_payment->transaction_id = $update_transaction_result->data->transaction->id; $this->_payment->save(); // Update tax_items foreach ($due_tax_items as $due_tax_item) { $due_tax_item->tax_payment_id = $this->_payment->id; $due_tax_item->balance = 0.0; $due_tax_item->save(); } // Update tax balance $this->_tax_payment_update_balance($this->_payment->tax_id); // Update tax due date. $this->_tax_update_due_date($this->_payment->tax_id); return (object) array("payment" => $this->_return_tax_payment_element($this->_payment, TRUE)); }
protected function _calibrate_vendor_payment_transaction($payment) { if (!$payment->loaded()) { throw new Exception("Vendor Payment could not be found."); } // If the books have been closed for the active date, we have to assume that due-diligence has been done // to prevent a bad transaction from being put into the journal and simply move on. if ($this->_check_books_closed($payment->date)) { return (object) array(); } $payment_object = $this->_return_vendor_payment_element($payment); $update_transaction_data = new stdClass(); $update_transaction_data->id = $payment->id; $update_transaction_data->code = $payment->reference; $update_transaction_data->description = $payment->description; $update_transaction_data->date = $payment->date; $update_transaction_data->payment = "vendor"; $update_transaction_data->entity_id = $payment->entity_id; $purchase_account_transfers = array(); $purchase_account_transfers_forms = array(); $purchase_account_transfer_total = 0.0; $writeoff_account_transfer_total = 0.0; $writeoff_account_transfers_forms = array(); // Write once for cleaner code $purchase_account_transfers[$this->_transaction_purchase_account_id] = 0.0; $purchase_account_transfers_forms[$this->_transaction_purchase_account_id] = array(); $purchase_account_transfers[$this->_transaction_purchase_line_account_id] = 0.0; $purchase_account_transfers_forms[$this->_transaction_purchase_line_account_id] = array(); $purchase_account_transfers[$this->_transaction_purchase_prepaid_purchase_account_id] = 0.0; $purchase_account_transfers_forms[$this->_transaction_purchase_prepaid_purchase_account_id] = array(); foreach ($payment_object->purchase_payments as $purchase_id => $purchase_payment) { $purchase = $this->_load_vendor_purchase($purchase_id); $purchase_balance = $this->_get_form_effective_balance($purchase, $payment->date, $payment->id); $purchase_transfer_amount = $purchase_payment->amount; $purchase_writeoff_amount = (isset($purchase_payment->writeoff_amount) and $purchase_payment->writeoff_amount) ? $this->_beans_round($purchase_balance - $purchase_transfer_amount) : FALSE; $purchase_payment_amount = $purchase_writeoff_amount ? $this->_beans_round($purchase_transfer_amount + $purchase_writeoff_amount) : $purchase_transfer_amount; // Apply to Realized Accounts if ($purchase->date_billed and $purchase->invoice_transaction_id and $this->_journal_cmp($purchase->date_billed, $purchase->invoice_transaction_id, $update_transaction_data->date, $update_transaction_data->id) < 0 or $purchase->date_cancelled and $purchase->cancel_transaction_id and $this->_journal_cmp($purchase->date_cancelled, $purchase->cancel_transaction_id, $update_transaction_data->date, $update_transaction_data->id) < 0) { // AP if (!isset($purchase_account_transfers[$purchase->account_id])) { $purchase_account_transfers[$purchase->account_id] = 0.0; } if (!isset($purchase_account_transfers_forms[$purchase->account_id])) { $purchase_account_transfers_forms[$purchase->account_id] = array(); } $purchase_account_transfers[$purchase->account_id] = $this->_beans_round($purchase_account_transfers[$purchase->account_id] + $purchase_payment_amount); // Writeoff if ($purchase_writeoff_amount) { $writeoff_account_transfer_total = $this->_beans_round($writeoff_account_transfer_total + $purchase_writeoff_amount); } $purchase_account_transfers_forms[$purchase->account_id][] = (object) array("form_id" => $purchase_id, "amount" => $purchase_payment_amount * -1, "writeoff_amount" => $purchase_writeoff_amount ? $purchase_writeoff_amount * -1 : NULL); } else { // Pending AP $purchase_account_transfers[$this->_transaction_purchase_account_id] = $this->_beans_round($purchase_account_transfers[$this->_transaction_purchase_account_id] + $purchase_payment_amount); // Pending AP $purchase_account_transfers[$this->_transaction_purchase_line_account_id] = $this->_beans_round($purchase_account_transfers[$this->_transaction_purchase_line_account_id] - $purchase_payment_amount); // Pending COGS $purchase_account_transfers[$this->_transaction_purchase_prepaid_purchase_account_id] = $this->_beans_round($purchase_account_transfers[$this->_transaction_purchase_prepaid_purchase_account_id] + $purchase_payment_amount); // Writeoff if ($purchase_writeoff_amount) { $writeoff_account_transfer_total = $this->_beans_round($writeoff_account_transfer_total + $purchase_writeoff_amount); } $purchase_account_transfers_forms[$this->_transaction_purchase_account_id][] = (object) array("form_id" => $purchase_id, "amount" => $purchase_payment_amount * -1, "writeoff_amount" => $purchase_writeoff_amount ? $purchase_writeoff_amount * -1 : NULL); } } $writeoff_account = FALSE; if ($writeoff_account_transfer_total != 0.0) { $writeoff_account = $payment_object->writeoff_transaction->account; $purchase_account_transfers[$writeoff_account->id] = $writeoff_account_transfer_total; $purchase_account_transfers_forms[$writeoff_account->id] = $writeoff_account_transfers_forms; } $payment_account = $payment_object->payment_transaction->account; // All of the accounts on purchases are Accounts Payable and should be assets. // But to be on the safe side we're going to do table sign adjustments to be on the safe side. foreach ($purchase_account_transfers as $account_id => $transfer_amount) { $purchase_account_transfers[$account_id] = ($writeoff_account and $writeoff_account->id == $account_id) ? $transfer_amount * -1 * $payment_account->type->table_sign : $transfer_amount * $payment_account->type->table_sign; } $adjustment_account = FALSE; if ($payment_object->adjustment_transaction and $payment_object->adjustment_transaction->amount) { $adjustment_account = $payment_object->adjustment_transaction->account; $purchase_account_transfers[$payment_object->adjustment_transaction->account->id] = $payment_object->adjustment_transaction->amount; } $purchase_account_transfers[$payment_account->id] = $payment_object->payment_transaction->amount; if ($payment_account->type->table_sign > 0) { foreach ($purchase_account_transfers as $account_id => $transfer_amount) { $purchase_account_transfers[$account_id] = $transfer_amount * -1; } } $update_transaction_data->account_transactions = array(); foreach ($purchase_account_transfers as $account_id => $amount) { $account_transaction = new stdClass(); $account_transaction->account_id = $account_id; $account_transaction->amount = $amount; if ($account_transaction->account_id == $payment_account->id) { $account_transaction->transfer = TRUE; } if ($writeoff_account and $account_transaction->account_id == $writeoff_account->id) { $account_transaction->writeoff = TRUE; } if ($adjustment_account and $account_transaction->account_id == $adjustment_account->id) { $account_transaction->adjustment = TRUE; } if (isset($purchase_account_transfers_forms[$account_id])) { $account_transaction->forms = array(); foreach ($purchase_account_transfers_forms[$account_id] as $form) { $account_transaction->forms[] = (object) array('form_id' => $form->form_id, 'amount' => $form->amount, 'writeoff_amount' => $form->writeoff_amount); } } $update_transaction_data->account_transactions[] = $account_transaction; } $update_transaction_data->id = $payment->id; $update_transaction_data->payment_type_handled = 'vendor'; $update_transaction = new Beans_Account_Transaction_Update($this->_beans_data_auth($update_transaction_data)); $update_transaction_result = $update_transaction->execute(); if (!$update_transaction_result->success) { throw new Exception("An error occurred creating that payment: " . $update_transaction_result->error); } return (object) array(); }
public function action_transactionupdate() { $transaction_id = $this->request->post("transaction-id"); $split_keys = array(); foreach ($this->request->post() as $key => $value) { if (strpos($key, 'transaction-split-transfer') !== FALSE and $value) { $split_keys[] = str_replace('transaction-split-transfer-', '', $key); } } $new_transaction = new stdClass(); $new_transaction->date = $this->request->post('transaction-date') ? date("Y-m-d", strtotime($this->request->post('transaction-date'))) : date("Y-m-d"); $new_transaction->code = $this->request->post('transaction-number'); $new_transaction->description = $this->request->post('transaction-description'); $new_transaction->account_transactions = array(); $new_transaction->account_transactions[] = (object) array('account_id' => $this->request->post('transaction-account-id'), 'amount' => $this->_get_numeric_value($this->request->post('transaction-credit')) ? $this->_get_numeric_value($this->request->post('transaction-credit')) * $this->request->post('transaction-account-table_sign') : $this->_get_numeric_value($this->request->post('transaction-debit')) * -1 * $this->request->post('transaction-account-table_sign')); if ($this->request->post('transaction-transfer')) { $new_transaction->account_transactions[] = (object) array('account_id' => $this->request->post('transaction-transfer'), 'amount' => $new_transaction->account_transactions[0]->amount * -1); } else { // Loop all split transactions and go for it. foreach ($split_keys as $split_key) { if ($this->request->post('transaction-split-transfer-' . $split_key) and ($this->request->post('transaction-split-credit-' . $split_key) or $this->request->post('transaction-split-debit-' . $split_key))) { $new_transaction->account_transactions[] = (object) array('account_id' => $this->request->post('transaction-split-transfer-' . $split_key), 'amount' => $this->request->post('transaction-split-credit-' . $split_key) ? $this->request->post('transaction-split-credit-' . $split_key) * $this->request->post('transaction-account-table_sign') : $this->request->post('transaction-split-debit-' . $split_key) * -1 * $this->request->post('transaction-account-table_sign')); } } } if (count($new_transaction->account_transactions) == 1) { return $this->_return_error("Please either select a transfer account or create a split."); } $new_transaction->id = $transaction_id; $account_transaction_update = new Beans_Account_Transaction_Update($this->_beans_data_auth($new_transaction)); $account_transaction_update_result = $account_transaction_update->execute(); if (!$account_transaction_update_result->success) { return $this->_return_error($this->_beans_result_get_error($account_transaction_update_result)); } $account_lookup = new Beans_Account_Lookup($this->_beans_data_auth((object) array('id' => $this->request->post('transaction-account-id')))); $account_lookup_result = $account_lookup->execute(); $html = new View_Partials_Accounts_View_Transaction(); $html->setup_company_list_result = $this->_setup_company_list_result; $html->account_lookup_result = $account_lookup_result; $html->transaction = $account_transaction_update_result->data->transaction; $html->account_id = $this->request->post('transaction-account-id'); $this->_return_object->data->transaction = $account_transaction_update_result->data->transaction; $this->_return_object->data->transaction->html = $html->render(); }
protected function _calibrate_purchase_create($purchase) { // Should be impossible - but catches bugs from the above query... if (!$purchase->date_created) { return; } // If the books have been closed for the active date, we have to assume that due-diligence has been done // to prevent a bad transaction from being put into the journal and simply move on. if ($this->_check_books_closed($purchase->date_created)) { return; } $purchase_create_transaction_data = new stdClass(); $purchase_create_transaction_data->code = $purchase->code; $purchase_create_transaction_data->description = "Purchase " . $purchase->code; $purchase_create_transaction_data->date = $purchase->date_created; $purchase_create_transaction_data->account_transactions = array(); $purchase_create_transaction_data->entity_id = $purchase->entity_id; $purchase_create_transaction_data->form_type = 'purchase'; $purchase_create_transaction_data->form_id = $purchase->id; $account_transactions = array($this->_transaction_purchase_prepaid_purchase_account_id => 0.0, $this->_transaction_purchase_line_account_id => 0.0, $this->_transaction_purchase_account_id => 0.0); $account_transactions[$this->_transaction_purchase_account_id] = $purchase->total; foreach ($purchase->form_lines->find_all() as $purchase_line) { $account_transactions[$this->_transaction_purchase_line_account_id] = $this->_beans_round($account_transactions[$this->_transaction_purchase_line_account_id] + $purchase_line->amount * $purchase_line->quantity); } foreach ($account_transactions as $account_id => $amount) { if ($purchase->total == 0.0 || $amount != 0.0) { $account_transaction = new stdClass(); $account_transaction->account_id = $account_id; $account_transaction->amount = $account_id == $this->_transaction_purchase_account_id ? $amount : $amount * -1; if ($account_transaction->account_id == $this->_transaction_purchase_account_id) { $account_transaction->forms = array((object) array("form_id" => $purchase->id, "amount" => $account_transaction->amount)); } $purchase_create_transaction_data->account_transactions[] = $account_transaction; } } $purchase_create_transaction_result = FALSE; if ($purchase->create_transaction_id) { $purchase_create_transaction_data->id = $purchase->create_transaction_id; $purchase_create_transaction_data->form_type_handled = "purchase"; $purchase_create_transaction = new Beans_Account_Transaction_Update($this->_beans_data_auth($purchase_create_transaction_data)); $purchase_create_transaction_result = $purchase_create_transaction->execute(); } else { $purchase_create_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($purchase_create_transaction_data)); $purchase_create_transaction_result = $purchase_create_transaction->execute(); } if (!$purchase_create_transaction_result->success) { throw new Exception("Error creating purchase transaction in journal: " . $purchase_create_transaction_result->error . "<br><br><br>\n\n\n" . print_r($purchase_create_transaction_data->account_transactions, TRUE)); } if (!$purchase->create_transaction_id) { $purchase->create_transaction_id = $purchase_create_transaction_result->data->transaction->id; $purchase->save(); } }
protected function _execute() { if (!$this->_account->loaded()) { throw new Exception("Account could not be found."); } if (ORM::Factory('account')->where('parent_account_id', '=', $this->_account->id)->count_all()) { throw new Exception("Please remove all child accounts before deleting."); } // Query for all transactions associated to this account. $transaction_id_rows = DB::query(Database::SELECT, 'SELECT DISTINCT(transaction_id) as transaction_id FROM account_transactions WHERE account_id = "' . $this->_account->id . '"')->execute()->as_array(); if (count($transaction_id_rows) and !$this->_transfer_account->loaded()) { throw new Exception("Please select a transfer account."); } if (count($transaction_id_rows) and $this->_account->id == $this->_transfer_account->id) { throw new Exception("Transfer account cannot match the account being removed."); } // Loop each transaction and update appropriately. foreach ($transaction_id_rows as $transaction_id_row) { $transaction = $this->_load_transaction($transaction_id_row['transaction_id']); if (!$transaction->loaded()) { throw new Exception("An unexpected error has occurred: transaction not found."); } // Array for $account_id => $amount $new_account_transactions = array(); $new_account_transactions[$this->_transfer_account->id] = 0.0; foreach ($transaction->account_transactions->find_all() as $account_transaction) { if ($account_transaction->account_reconcile_id) { throw new Exception("Cannot delete accounts that have reconciled transactions."); } if ($account_transaction->account_transaction_forms->count_all()) { throw new Exception("This account contains transactions that are associated with a form ( invoice, purchase, payment, etc. ). At this time transactions associated with a form cannot be transferred."); } if ($account_transaction->account_id == $this->_account->id) { $new_account_transactions[$this->_transfer_account->id] = $this->_beans_round($new_account_transactions[$this->_transfer_account->id] + $account_transaction->amount * $account_transaction->account->account_type->table_sign * $this->_transfer_account->account_type->table_sign); } else { if (!isset($new_account_transactions[$account_transaction->account_id])) { $new_account_transactions[$account_transaction->account_id] = 0.0; } $new_account_transactions[$account_transaction->account_id] = $this->_beans_round($new_account_transactions[$account_transaction->account_id] + $account_transaction->amount); } } // Array for $account_id => $amount $account_transaction_update_data = new stdClass(); $account_transaction_update_data->id = $transaction->id; $account_transaction_update_data->account_transactions = array(); foreach ($new_account_transactions as $account_id => $amount) { $account_transaction_update_data->account_transactions[] = (object) array('account_id' => $account_id, 'amount' => $amount); } $account_transaction_update = new Beans_Account_Transaction_Update($this->_beans_data_auth($account_transaction_update_data)); $account_transaction_update_result = $account_transaction_update->execute(); if (!$account_transaction_update_result->success) { throw new Exception("Error updating account transaction: " . $account_transaction_update_result->error); } } // Now delete account. $this->_account->delete(); return (object) array(); }
protected function _calibrate_customer_payment_transaction($payment) { if (!$payment->loaded()) { throw new Exception("Customer Payment could not be found."); } // If the books have been closed for the active date, we have to assume that due-diligence has been done // to prevent a bad transaction from being put into the journal and simply move on. if ($this->_check_books_closed($payment->date)) { return (object) array(); } $payment_object = $this->_return_customer_payment_element($payment); $update_transaction_data = new stdClass(); $update_transaction_data->code = $payment->reference; $update_transaction_data->description = $payment->description; $update_transaction_data->date = $payment->date; $update_transaction_data->payment = "customer"; $sale_account_transfers = array(); $sale_account_transfers_forms = array(); $writeoff_account_transfer_total = 0.0; $writeoff_account_transfers_forms = array(); foreach ($payment_object->sale_payments as $sale_id => $sale_payment) { $sale = $this->_load_customer_sale($sale_id); // Get the sale total, tax total, and balance as of the payment date. $sale_line_total = $sale->amount; $sale_tax_total = $this->_beans_round($sale->total - $sale->amount); $sale_balance = $this->_get_form_effective_balance($sale, $update_transaction_data->date, $payment->id); // This makes the math a bit easier to read. $sale_paid = $sale->total + $sale_balance; $sale_payment_amount = isset($sale_payment->amount) ? $sale_payment->amount : 0; $sale_writeoff_amount = isset($sale_payment->writeoff_amount) ? $sale_payment->writeoff_amount : FALSE; // Money Received / Paid = Bank $sale_transfer_amount = $sale_payment_amount; // - $sale_writeoff_amount; $sale_writeoff_amount = $sale_writeoff_amount ? $this->_beans_round(0.0 - $sale_balance - $sale_transfer_amount) : FALSE; // AR Adjustment $sale_payment_amount = $sale_writeoff_amount ? $this->_beans_round($sale_transfer_amount + $sale_writeoff_amount) : $sale_transfer_amount; // Another variable to simplify code. $sale_transaction_account_id = FALSE; if ($sale->date_billed and $sale->invoice_transaction_id and (strtotime($sale->date_billed) < strtotime($payment_object->date) or $sale->date_billed == $payment_object->date && $sale->invoice_transaction_id < $payment->id) or $sale->date_cancelled and $sale->cancel_transaction_id and (strtotime($sale->date_cancelled) < strtotime($payment_object->date) or $sale->date_cancelled == $payment_object->date && $sale->invoice_transaction_id < $payment->id)) { // Sale AR $sale_transaction_account_id = $sale->account_id; if (!isset($sale_account_transfers[$sale_transaction_account_id])) { $sale_account_transfers[$sale_transaction_account_id] = 0.0; } $sale_account_transfers[$sale_transaction_account_id] = $this->_beans_round($sale_account_transfers[$sale_transaction_account_id] + $sale_payment_amount); if (!isset($sale_account_transfers_forms[$sale_transaction_account_id])) { $sale_account_transfers_forms[$sale_transaction_account_id] = array(); } $sale_account_transfers_forms[$sale_transaction_account_id][] = (object) array("form_id" => $sale_id, "amount" => $sale_payment_amount, "writeoff_amount" => $sale_writeoff_amount ? $sale_writeoff_amount : NULL); } else { $deferred_amounts = $this->_calculate_deferred_payment($sale_payment_amount, $sale_paid, $sale_line_total, $sale_tax_total); $income_transfer_amount = $deferred_amounts->income_transfer_amount; $tax_transfer_amount = $deferred_amounts->tax_transfer_amount; if ($income_transfer_amount) { if (!isset($sale_account_transfers[$this->_transaction_sale_deferred_income_account_id])) { $sale_account_transfers[$this->_transaction_sale_deferred_income_account_id] = 0.0; } if (!isset($sale_account_transfers[$this->_transaction_sale_line_account_id])) { $sale_account_transfers[$this->_transaction_sale_line_account_id] = 0.0; } $sale_account_transfers[$this->_transaction_sale_deferred_income_account_id] = $this->_beans_round($sale_account_transfers[$this->_transaction_sale_deferred_income_account_id] + $income_transfer_amount); $sale_account_transfers[$this->_transaction_sale_line_account_id] = $this->_beans_round($sale_account_transfers[$this->_transaction_sale_line_account_id] - $income_transfer_amount); } if ($tax_transfer_amount) { if (!isset($sale_account_transfers[$this->_transaction_sale_deferred_liability_account_id])) { $sale_account_transfers[$this->_transaction_sale_deferred_liability_account_id] = 0.0; } if (!isset($sale_account_transfers[$this->_transaction_sale_tax_account_id])) { $sale_account_transfers[$this->_transaction_sale_tax_account_id] = 0.0; } $sale_account_transfers[$this->_transaction_sale_deferred_liability_account_id] = $this->_beans_round($sale_account_transfers[$this->_transaction_sale_deferred_liability_account_id] + $tax_transfer_amount); $sale_account_transfers[$this->_transaction_sale_tax_account_id] = $this->_beans_round($sale_account_transfers[$this->_transaction_sale_tax_account_id] - $tax_transfer_amount); } if (!isset($sale_account_transfers[$this->_transaction_sale_account_id])) { $sale_account_transfers[$this->_transaction_sale_account_id] = 0.0; } $sale_account_transfers[$this->_transaction_sale_account_id] = $this->_beans_round($sale_account_transfers[$this->_transaction_sale_account_id] + $sale_payment_amount); if (!isset($sale_account_transfers_forms[$this->_transaction_sale_account_id])) { $sale_account_transfers_forms[$this->_transaction_sale_account_id] = array(); } $sale_account_transfers_forms[$this->_transaction_sale_account_id][] = (object) array("form_id" => $sale_id, "amount" => $sale_payment_amount, "writeoff_amount" => $sale_writeoff_amount ? $sale_writeoff_amount : NULL); } if ($sale_writeoff_amount) { $writeoff_account_transfer_total = $this->_beans_round($writeoff_account_transfer_total + $sale_writeoff_amount); } } $writeoff_account = FALSE; if ($writeoff_account_transfer_total != 0.0) { $writeoff_account = $payment_object->writeoff_transaction->account; $sale_account_transfers[$payment_object->writeoff_transaction->account->id] = $writeoff_account_transfer_total; $sale_account_transfers_forms[$payment_object->writeoff_transaction->account->id] = $writeoff_account_transfers_forms; } $deposit_account = $payment_object->deposit_transaction->account; // All of the accounts on sales are Accounts Receivable and should be assets. // But to be on the safe side we're going to do table sign adjustments. foreach ($sale_account_transfers as $account_id => $transfer_amount) { $sale_account_transfers[$account_id] = ($writeoff_account and $writeoff_account->id == $account_id) ? $transfer_amount * $deposit_account->type->table_sign : $transfer_amount * -1 * $deposit_account->type->table_sign; } $adjustment_account = FALSE; if ($payment_object->adjustment_transaction and $payment_object->adjustment_transaction->amount) { $adjustment_account = $payment_object->adjustment_transaction->account; $sale_account_transfers[$payment_object->adjustment_transaction->account->id] = $payment_object->adjustment_transaction->amount; } $sale_account_transfers[$deposit_account->id] = $payment_object->deposit_transaction->amount; $update_transaction_data->account_transactions = array(); foreach ($sale_account_transfers as $account_id => $amount) { $account_transaction = new stdClass(); $account_transaction->account_id = $account_id; $account_transaction->amount = $amount; if ($account_transaction->account_id == $deposit_account->id) { $account_transaction->transfer = TRUE; } if ($writeoff_account and $account_transaction->account_id == $writeoff_account->id) { $account_transaction->writeoff = TRUE; } if ($adjustment_account and $account_transaction->account_id == $adjustment_account->id) { $account_transaction->adjustment = TRUE; } if (isset($sale_account_transfers_forms[$account_id])) { $account_transaction->forms = array(); foreach ($sale_account_transfers_forms[$account_id] as $form) { $account_transaction->forms[] = (object) array('form_id' => $form->form_id, 'amount' => $form->amount, 'writeoff_amount' => $form->writeoff_amount); } } $update_transaction_data->account_transactions[] = $account_transaction; } $update_transaction_data->id = $payment->id; $update_transaction_data->payment_type_handled = 'customer'; $update_transaction = new Beans_Account_Transaction_Update($this->_beans_data_auth($update_transaction_data)); $update_transaction_result = $update_transaction->execute(); if (!$update_transaction_result->success) { throw new Exception("Update failure - could not update payment: " . $update_transaction_result->error . "\n\n" . print_r($sale_account_transfers, TRUE)); } return (object) array(); }