protected function _execute() { $vendor_purchase_calibrate_create = new Beans_Vendor_Purchase_Calibrate_Create($this->_beans_data_auth((object) array('ids' => isset($this->_data->ids) ? $this->_data->ids : NULL, 'date_after' => isset($this->_data->date_after) ? $this->_data->date_after : NULL, 'date_before' => isset($this->_data->date_before) ? $this->_data->date_before : NULL))); $vendor_purchase_calibrate_create_result = $vendor_purchase_calibrate_create->execute(); if (!$vendor_purchase_calibrate_create_result->success) { throw new Exception("Unexpected error - could not calibrate purchases: " . $vendor_purchase_calibrate_create_result->error); } $vendor_purchase_calibrate_invoice = new Beans_Vendor_Purchase_Calibrate_Invoice($this->_beans_data_auth((object) array('ids' => isset($this->_data->ids) ? $this->_data->ids : NULL, 'date_after' => isset($this->_data->date_after) ? $this->_data->date_after : NULL, 'date_before' => isset($this->_data->date_before) ? $this->_data->date_before : NULL))); $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 invoiced purchases: " . $vendor_purchase_calibrate_invoice_result->error); } $vendor_purchase_calibrate_cancel = new Beans_Vendor_Purchase_Calibrate_Cancel($this->_beans_data_auth((object) array('ids' => isset($this->_data->ids) ? $this->_data->ids : NULL, 'date_after' => isset($this->_data->date_after) ? $this->_data->date_after : NULL, 'date_before' => isset($this->_data->date_before) ? $this->_data->date_before : NULL))); $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 cancelled purchases: " . $vendor_purchase_calibrate_cancel_result->error); } return (object) array(); }
protected function _execute() { if (!$this->_payment->loaded()) { throw new Exception("Payment could not be found."); } $form_ids_query = ' SELECT DISTINCT(account_transaction_forms.form_id) as form_id FROM account_transaction_forms ' . ' INNER JOIN account_transactions ON account_transaction_forms.account_transaction_id = account_transactions.id WHERE ' . ' account_transactions.transaction_id = ' . $this->_payment->id; $form_ids = DB::Query(Database::SELECT, $form_ids_query)->execute()->as_array(); $handled_purchase_ids = array(); foreach ($form_ids as $form_id) { $handled_purchase_ids[] = $form_id['form_id']; } $payment_date = $this->_payment->date; $payment_id = $this->_payment->id; $account_transaction_delete = new Beans_Account_Transaction_Delete($this->_beans_data_auth((object) array('id' => $this->_payment->id, 'payment_type_handled' => 'vendor'))); $account_transaction_delete_result = $account_transaction_delete->execute(); if (!$account_transaction_delete_result->success) { throw new Exception("Error cancelling payment: " . $account_transaction_delete_result->error); } // Recalibrate Vendor Invoices / Cancellations $vendor_purchase_calibrate_invoice = new Beans_Vendor_Purchase_Calibrate_Invoice($this->_beans_data_auth((object) array('ids' => $handled_purchase_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' => $handled_purchase_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' => $handled_purchase_ids))); $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(); }
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))); }