Example #1
0
 protected function _execute()
 {
     if (!$this->_transaction->loaded()) {
         throw new Exception("Transaction could not be found.");
     }
     if ($this->_transaction->cancel_transaction->loaded()) {
         throw new Exception("Transaction already belongs to a cancel-pair.");
     }
     if ($this->_transaction->close_books) {
         throw new Exception("Close books transactions cannot be cancelled.");
     }
     $cancel_transaction_data = new stdClass();
     $cancel_transaction_data->code = $this->_transaction->code;
     $cancel_transaction_data->description = "Cancelled Transaction " . $this->_transaction->code;
     $cancel_transaction_data->cancel_transaction_id = $this->_transaction->id;
     $cancel_transaction_data->date = $this->_date ? $this->_date : date("Y-m-d");
     $cancel_transaction_data->account_transactions = array();
     foreach ($this->_transaction->account_transactions->find_all() as $account_transaction) {
         if ($account_transaction->account_reconcile_id) {
             throw new Exception("That transaction has already been reconciled on an account and cannot be changed.");
         }
         $new_account_transaction = new stdClass();
         $new_account_transaction->account_id = $account_transaction->account_id;
         $new_account_transaction->amount = -1 * $account_transaction->amount;
         foreach ($account_transaction->account_transaction_forms->find_all() as $account_transaction_form) {
             if (!isset($new_account_transaction->forms)) {
                 $new_account_transaction->forms = array();
             }
             $new_account_transaction->forms[] = (object) array("form_id" => $account_transaction_form->form_id, "amount" => $this->_beans_round(-1 * $account_transaction_form->amount));
         }
         $cancel_transaction_data->account_transactions[] = $new_account_transaction;
     }
     $account_transaction_create = new Beans_Account_Transaction_Create($this->_beans_data_auth($cancel_transaction_data));
     $account_transaction_create_result = $account_transaction_create->execute();
     if (!$account_transaction_create_result->success) {
         throw new Exception("Error creating cancel transaction: " . $account_transaction_create_result->error);
     }
     $this->_transaction->cancel_transaction_id = $account_transaction_create_result->data->transaction->id;
     $this->_transaction->save();
     return (object) array("transaction" => $account_transaction_create_result->data->transaction);
 }
Example #2
0
 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.");
     }
     // Check for some basic data.
     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.");
     }
     // Formulate data request object for Beans_Account_Transaction_Create
     $create_transaction_data = new stdClass();
     $create_transaction_data->code = isset($this->_data->number) ? $this->_data->number : NULL;
     $create_transaction_data->description = isset($this->_data->description) ? $this->_data->description : NULL;
     $create_transaction_data->description = "Customer Payment Recorded" . ($create_transaction_data->description ? ': ' . $create_transaction_data->description : '');
     $create_transaction_data->date = isset($this->_data->date) ? $this->_data->date : NULL;
     $create_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.");
     }
     $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 " . $sale->code . " cannot be in payment more than once.");
         }
         $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, $create_transaction_data->date, NULL);
         // 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($create_transaction_data->date) or $sale->date_cancelled and $sale->cancel_transaction_id and strtotime($sale->date_cancelled) <= strtotime($create_transaction_data->date)) {
             // 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 a write-off account.
         if (!isset($this->_data->writeoff_account_id) or !$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 - Validate amount to avoid funky non-zero errors.
     $sale_account_transfers[$deposit_account->id] = $this->_data->amount * $deposit_account->account_type->table_sign;
     $create_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);
             }
         }
         $create_transaction_data->account_transactions[] = $account_transaction;
     }
     if ($this->_validate_only) {
         $create_transaction_data->validate_only = TRUE;
     }
     $create_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($create_transaction_data));
     $create_transaction_result = $create_transaction->execute();
     if (!$create_transaction_result->success) {
         throw new Exception("An error occurred creating that payment: " . $create_transaction_result->error);
     }
     if ($this->_validate_only) {
         return (object) array();
     }
     // 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' => $create_transaction_result->data->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($create_transaction_result->data->transaction->id)));
 }
Example #3
0
 protected function _execute()
 {
     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.");
     }
     // Payment.
     $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 > 0 && $tax_prep_result->data->taxes->due->net->amount != $this->_data->total) {
         throw new Exception("Invalid payment total: please make sure the payment and writeoff amounts add up to the expected total.");
         // throw new Exception("Invalid payment total: expected ".number_format($tax_prep_result->data->taxes->due->net->amount,2,'.','')." but received ".number_format($this->_data->total,2,'.',''));
     }
     if ($this->_data->total > 0 && $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 > 0 && $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;
     if ($due_tax_items_total < 0.0 && $this->_payment->amount != 0.0) {
         throw new Exception("Tax payments must be 0.00 when no positive balance is due.");
     }
     if ($this->_payment->amount == 0) {
         $this->_payment->save();
         $this->_tax_update_due_date($this->_payment->tax_id);
         return (object) array("payment" => $this->_return_tax_payment_element($this->_payment));
     }
     $this->_payment->save();
     // Formulate data request object for Beans_Account_Transaction_Create
     $create_transaction_data = new stdClass();
     $create_transaction_data->code = isset($this->_data->number) ? $this->_data->number : NULL;
     $create_transaction_data->description = isset($this->_data->description) ? $this->_data->description : NULL;
     if (!$create_transaction_data->description) {
         $create_transaction_data->description = "Tax Remittance: " . $tax->name;
     } else {
         $create_transaction_data->description = "Tax Remittance: " . $create_transaction_data->description;
     }
     $create_transaction_data->date = isset($this->_data->date) ? $this->_data->date : NULL;
     $create_transaction_data->reference = isset($this->_data->check_number) ? $this->_data->check_number : NULL;
     if (!$create_transaction_data->code and $create_transaction_data->reference) {
         $create_transaction_data->code = $create_transaction_data->reference;
     }
     // Positive Payment = Negative to Balance
     $create_transaction_data->account_transactions = array();
     $create_transaction_data->form_type = 'tax_payment';
     $create_transaction_data->form_id = $this->_payment->id;
     // Payment Account
     $create_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.");
         }
         $create_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
     $create_transaction_data->account_transactions[] = (object) array('account_id' => $tax->account_id, 'amount' => $this->_payment->amount * $payment_account->account_type->table_sign);
     if ($this->_validate_only) {
         $create_transaction_data->validate_only = TRUE;
     }
     $create_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($create_transaction_data));
     $create_transaction_result = $create_transaction->execute();
     if (!$create_transaction_result->success) {
         $this->_payment->delete();
         throw new Exception("An error occurred creating that tax payment: " . $create_transaction_result->error);
     }
     if ($this->_validate_only) {
         return (object) array();
     }
     // Assign transaction to payment and save
     $this->_payment->transaction_id = $create_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));
 }
Example #4
0
 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();
     }
 }
Example #5
0
 protected function _execute()
 {
     if (!$this->_transfer_account->loaded()) {
         throw new Exception("That closing transfer account could not be found.");
     }
     if ($this->_transfer_account->account_type->code != "equity") {
         throw new Exception("You must choose an Equity account to distribute the closing transfer to.");
     }
     if (!$this->_date) {
         throw new Exception("Invalid date: none provided.");
     }
     if (date("Y-m-d", strtotime($this->_date)) != $this->_date) {
         throw new Exception("Invalid date: must be in YYYY-MM-DD format.");
     }
     $include_account_ids = array();
     if (isset($this->_data->include_account_ids) && is_array($this->_data->include_account_ids)) {
         $include_account_ids = $this->_data->include_account_ids;
     }
     if (in_array($this->_transfer_account->id, $include_account_ids)) {
         throw new Exception("You cannot close out the same account you are retaining earnings to.");
     }
     // In case we change our mind on the format.
     $balance_report_date = $this->_date;
     $balance_report_start_date = substr($balance_report_date, 0, 4) . '-01-01';
     if (strtotime($balance_report_date) > time()) {
         throw new Exception("Invalid date: must be a date in the past.");
     }
     // Make sure we haven't closed after this already.
     if ($this->_check_books_closed($balance_report_date)) {
         throw new Exception("The books have already been closed in that date range.");
     }
     $this->_closing_transaction = new stdClass();
     // The first day of the next month.
     $this->_closing_transaction->date = date("Y-m-d", strtotime($this->_date . ' +1 Day'));
     $this->_closing_transaction->close_books = $this->_date;
     $this->_closing_transaction->code = "CLOSEBOOKS";
     $this->_closing_transaction->description = "Close Books for " . $this->_date;
     $this->_closing_transaction->account_transactions = array();
     $transfer_account_total = 0.0;
     // Look up all accounts and generate their inverse transaction.
     $accounts = ORM::Factory('account')->where('account_type_id', 'IS NOT', NULL)->where('reserved', '=', FALSE)->find_all();
     foreach ($accounts as $account) {
         if ((strtolower($account->account_type->type) == "income" or strtolower($account->account_type->type) == "cost of goods sold" or strtolower($account->account_type->type) == "expense" or in_array($account->id, $include_account_ids)) and strpos($account->account_type->code, 'pending_') === FALSE) {
             $balance = $this->_generate_simple_account_balance($account->id, $balance_report_date, $balance_report_start_date);
             if ($balance != 0.0) {
                 $transfer_account_total = $this->_beans_round($transfer_account_total + $balance);
                 $this->_closing_transaction->account_transactions[] = (object) array('account_id' => $account->id, 'amount' => $balance * -1);
             }
         }
     }
     array_unshift($this->_closing_transaction->account_transactions, (object) array('account_id' => $this->_transfer_account_id, 'amount' => $transfer_account_total));
     $account_transaction_create = new Beans_Account_Transaction_Create($this->_beans_data_auth($this->_closing_transaction));
     return $this->_beans_return_internal_result($account_transaction_create->execute());
 }
Example #6
0
 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();
     }
 }
Example #7
0
 protected function _execute()
 {
     if (!$this->_old_payment->loaded()) {
         throw new Exception("Payment could not be found.");
     }
     if ($this->_old_payment->transaction->account_transactions->where('account_reconcile_id', 'IS NOT', NULL)->count_all()) {
         throw new Exception("Payment cannot be changed after it has been reconciled.");
     }
     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 (!$this->_data->amount) {
         throw new Exception("Invalid payment amount: none provided.");
     }
     // Payment.
     $this->_payment->amount = $this->_data->amount;
     $this->_payment->tax_id = $tax->id;
     $this->_payment->date = isset($this->_data->date) ? $this->_data->date : $this->_old_payment->date;
     $this->_payment->date_start = $this->_old_payment->date_start;
     $this->_payment->date_end = $this->_old_payment->date_end;
     $this->_payment->writeoff_amount = isset($this->_data->writeoff_amount) ? $this->_data->writeoff_amount : 0.0;
     $this->_payment->id = $this->_old_payment->id;
     $this->_validate_tax_payment($this->_payment);
     $this->_payment->invoiced_line_amount = $this->_old_payment->invoiced_line_amount;
     $this->_payment->invoiced_line_taxable_amount = $this->_old_payment->invoiced_line_taxable_amount;
     $this->_payment->invoiced_amount = $this->_old_payment->invoiced_amount;
     $this->_payment->refunded_line_amount = $this->_old_payment->refunded_line_amount;
     $this->_payment->refunded_line_taxable_amount = $this->_old_payment->refunded_line_taxable_amount;
     $this->_payment->refunded_amount = $this->_old_payment->refunded_amount;
     $this->_payment->net_line_amount = $this->_old_payment->net_line_amount;
     $this->_payment->net_line_taxable_amount = $this->_old_payment->net_line_taxable_amount;
     $this->_payment->net_amount = $this->_old_payment->net_amount;
     if ($this->_payment->net_amount != $this->_beans_round($this->_payment->amount + $this->_payment->writeoff_amount)) {
         throw new Exception("Payment amount and writeoff amount must total the payment total.");
     }
     // Formulate data request object for Beans_Account_Transaction_Create
     $create_transaction_data = new stdClass();
     $create_transaction_data->code = isset($this->_data->number) ? $this->_data->number : $this->_old_payment->transaction->code;
     $create_transaction_data->description = isset($this->_data->description) ? $this->_data->description : $this->_old_payment->transaction->description;
     if (!$create_transaction_data->description) {
         $create_transaction_data->description = "Tax Remittance: " . $tax->name;
     } else {
         if (strpos($create_transaction_data->description, "Tax Remittance: ") === FALSE) {
             $create_transaction_data->description = "Tax Remittance: " . $create_transaction_data->description;
         }
     }
     $create_transaction_data->date = isset($this->_data->date) ? $this->_data->date : $this->_old_payment->transaction->date;
     $create_transaction_data->reference = isset($this->_data->check_number) ? $this->_data->check_number : $this->_old_payment->transaction->reference;
     if (!$create_transaction_data->code and $create_transaction_data->reference) {
         $create_transaction_data->code = $create_transaction_data->reference;
     }
     $create_transaction_data->form_type = 'tax_payment';
     $create_transaction_data->form_id = $this->_payment->id;
     // Positive Payment = Negative to Balance
     $create_transaction_data->account_transactions = array();
     // Payment Account
     $create_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.");
         }
         $create_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
     $create_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.
     $create_transaction_data->validate_only = TRUE;
     $validate_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($create_transaction_data));
     $validate_transaction_result = $validate_transaction->execute();
     if (!$validate_transaction_result->success) {
         throw new Exception("An error occurred when creating that payment: " . $validate_transaction_result->error);
     }
     if ($this->_validate_only) {
         return (object) array();
     }
     $create_transaction_data->validate_only = FALSE;
     // Delete old transaction
     $account_transaction_delete = new Beans_Account_Transaction_Delete($this->_beans_data_auth((object) array('id' => $this->_old_payment->transaction_id, 'payment_type_handled' => 'tax')));
     $account_transaction_delete_result = $account_transaction_delete->execute();
     // Delete Payment
     $this->_old_payment->delete();
     $create_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($create_transaction_data));
     $create_transaction_result = $create_transaction->execute();
     if (!$create_transaction_result->success) {
         throw new Exception("An error occurred creating that tax payment: " . $create_transaction_result->error);
     }
     // Assign transction to payment and save
     $this->_payment->transaction_id = $create_transaction_result->data->transaction->id;
     $this->_payment->save();
     // Update tax balance
     $this->_tax_payment_update_balance($this->_payment->tax_id);
     return (object) array("payment" => $this->_return_tax_payment_element($this->_payment, TRUE));
 }
Example #8
0
 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();
     }
 }
Example #9
0
 public function action_importtransactions()
 {
     $account_id = $this->request->post('account_id');
     $account_table_sign = $this->request->post('account_table_sign');
     $importdata = $this->request->post('importdata');
     if (!$importdata) {
         return $this->_return_error("Missing required import data.");
     }
     $importobject = json_decode($importdata);
     $importarray = array();
     foreach ($importobject as $key => $value) {
         $importarray[$key] = $value;
     }
     if (!$account_id or !$account_table_sign) {
         return $this->_return_error("Missing required values account ID and table sign.");
     }
     $transaction_keys = array();
     foreach ($importarray as $key => $value) {
         if ($value == "TRANSACTIONKEY") {
             $transaction_keys[] = $key;
         }
     }
     foreach ($transaction_keys as $hash) {
         if (Arr::get($importarray, 'import-transaction-' . $hash . '-transaction-transfer') != "duplicate" and Arr::get($importarray, 'import-transaction-' . $hash . '-transaction-transfer') != "ignore") {
             $create_transaction = new stdClass();
             $create_transaction->date = Arr::get($importarray, 'import-transaction-' . $hash . '-date') ? date("Y-m-d", strtotime(Arr::get($importarray, 'import-transaction-' . $hash . '-date'))) : NULL;
             // THIS WILL NOT ALLOW TRANSACTION LINES WITHOUT A DATE date("Y-m-d");
             $create_transaction->code = Arr::get($importarray, 'import-transaction-' . $hash . '-number');
             $create_transaction->description = Arr::get($importarray, 'import-transaction-' . $hash . '-description');
             $create_transaction->account_transactions = array();
             $create_transaction->account_transactions[] = (object) array('account_id' => $account_id, 'amount' => Arr::get($importarray, 'import-transaction-' . $hash . '-amount') * $account_table_sign);
             if (Arr::get($importarray, 'import-transaction-' . $hash . '-transaction-transfer')) {
                 $create_transaction->account_transactions[] = (object) array('account_id' => Arr::get($importarray, 'import-transaction-' . $hash . '-transaction-transfer'), 'amount' => $create_transaction->account_transactions[0]->amount * -1);
             } else {
                 $split_keys = array();
                 foreach ($importarray as $key => $value) {
                     if ($value == 'import-transaction-' . $hash . '-split-key') {
                         $split_keys[] = str_replace('split-key-', '', $key);
                     }
                 }
                 foreach ($split_keys as $split_key) {
                     if (Arr::get($importarray, 'import-transaction-' . $hash . '-split-transaction-transfer-' . $split_key)) {
                         $create_transaction->account_transactions[] = (object) array('account_id' => Arr::get($importarray, 'import-transaction-' . $hash . '-split-transaction-transfer-' . $split_key), 'amount' => Arr::get($importarray, 'import-transaction-' . $hash . '-split-credit-' . $split_key) ? Arr::get($importarray, 'import-transaction-' . $hash . '-split-credit-' . $split_key) * $account_table_sign : Arr::get($importarray, 'import-transaction-' . $hash . '-split-debit-' . $split_key) * -1 * $account_table_sign);
                     }
                 }
             }
             $account_transaction_create = new Beans_Account_Transaction_Create($this->_beans_data_auth($create_transaction));
             $account_transaction_create_result = $account_transaction_create->execute();
             $this->_beans_result_check($account_transaction_create_result);
         }
     }
     $this->request->redirect('/accounts/view/' . $account_id);
 }
Example #10
0
 protected function _execute()
 {
     $this->_expense->entity_id = isset($this->_data->vendor_id) ? (int) $this->_data->vendor_id : NULL;
     $this->_expense->account_id = isset($this->_data->account_id) ? (int) $this->_data->account_id : NULL;
     $this->_expense->refund_form_id = isset($this->_data->refund_expense_id) ? $this->_data->refund_expense_id : NULL;
     $this->_expense->sent = isset($this->_data->sent) ? $this->_data->sent : NULL;
     $this->_expense->date_created = isset($this->_data->date_created) ? $this->_data->date_created : NULL;
     $this->_expense->code = (isset($this->_data->expense_number) and strlen($this->_data->expense_number)) ? $this->_data->expense_number : "AUTOGENERATE";
     $this->_expense->reference = (isset($this->_data->invoice_number) and strlen($this->_data->invoice_number)) ? $this->_data->invoice_number : NULL;
     $this->_expense->alt_reference = (isset($this->_data->so_number) and strlen($this->_data->so_number)) ? $this->_data->so_number : NULL;
     $this->_expense->remit_address_id = isset($this->_data->remit_address_id) ? (int) $this->_data->remit_address_id : NULL;
     // Default Account Payable
     if ($this->_expense->account_id === NULL) {
         $this->_expense->account_id = $this->_beans_setting_get('account_default_expense');
     }
     // Make sure we have good invoice information before moving on.
     $this->_validate_vendor_expense($this->_expense);
     $this->_expense->total = 0.0;
     $this->_expense->amount = 0.0;
     if (!isset($this->_data->lines) or !is_array($this->_data->lines) or !count($this->_data->lines)) {
         throw new Exception("Invalid expense lines: none provided.");
     }
     $i = 0;
     foreach ($this->_data->lines as $expense_line) {
         $new_expense_line = $this->_default_form_line();
         $new_expense_line->account_id = isset($expense_line->account_id) ? (int) $expense_line->account_id : NULL;
         $new_expense_line->description = isset($expense_line->description) ? $expense_line->description : NULL;
         $new_expense_line->amount = isset($expense_line->amount) ? $this->_beans_round($expense_line->amount) : NULL;
         $new_expense_line->quantity = isset($expense_line->quantity) ? (double) $expense_line->quantity : NULL;
         $this->_validate_form_line($new_expense_line);
         $new_expense_line->total = $this->_beans_round($new_expense_line->amount * $new_expense_line->quantity);
         $this->_expense->amount = $this->_beans_round($this->_expense->amount + $new_expense_line->total);
         $this->_expense_lines[$i] = $new_expense_line;
         $i++;
     }
     $this->_expense->total = $this->_beans_round($this->_expense->total + $this->_expense->amount);
     // If this is a refund we need to verify that the total is not greater than the original.
     if ($this->_expense->refund_form_id and $this->_expense->total > $this->_load_vendor_expense($this->_expense->refund_form_id)->total) {
         throw new Exception("That refund total was greater than the original expense total.");
     }
     // Save expense + Children
     $this->_expense->save();
     if ($this->_expense->code == "AUTOGENERATE") {
         $this->_expense->code = $this->_expense->id;
     }
     // We "decrease" the account.
     $expense_account = $this->_load_account($this->_expense->account_id);
     $this->_account_transactions[$this->_expense->account_id] = $this->_expense->total;
     foreach ($this->_expense_lines as $j => $expense_line) {
         $expense_line->form_id = $this->_expense->id;
         $expense_line->save();
         if (!isset($this->_account_transactions[$expense_line->account_id])) {
             $this->_account_transactions[$expense_line->account_id] = 0;
         }
         $this->_account_transactions[$expense_line->account_id] = $this->_beans_round($this->_account_transactions[$expense_line->account_id] + $expense_line->amount * $expense_line->quantity);
     }
     // Generate Account Transaction
     $account_create_transaction_data = new stdClass();
     $account_create_transaction_data->code = isset($this->_data->check_number) ? $this->_data->check_number : $this->_expense->code;
     $account_create_transaction_data->description = "Expense Recorded: " . $this->_expense->entity->company_name;
     $account_create_transaction_data->date = $this->_expense->date_created;
     $account_create_transaction_data->account_transactions = array();
     $account_create_transaction_data->payment = "expense";
     $account_create_transaction_data->reference = isset($this->_data->check_number) ? $this->_data->check_number : NULL;
     $account_create_transaction_data->entity_id = $this->_expense->entity_id;
     $account_create_transaction_data->form_type = 'expense';
     $account_create_transaction_data->form_id = $this->_expense->id;
     $account_transfer_total = 0.0;
     foreach ($this->_account_transactions as $account_id => $amount) {
         $account_transaction = new stdClass();
         $account_transaction->account_id = $account_id;
         $account_transaction->amount = $account_id == $this->_expense->account_id ? $amount : $amount * -1;
         $account_transaction->forms = array((object) array("form_id" => $this->_expense->id, "amount" => $account_transaction->amount));
         $account_transfer_total = $this->_beans_round($account_transfer_total + $account_transaction->amount);
         $account_create_transaction_data->account_transactions[] = $account_transaction;
     }
     $account_create_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($account_create_transaction_data));
     $account_create_transaction_result = $account_create_transaction->execute();
     if (!$account_create_transaction_result->success) {
         // We've had an account transaction failure and need to delete the expense we just created.
         $delete_expense = new Beans_Vendor_expense_Delete($this->_beans_data_auth((object) array('id' => $this->_expense->id)));
         $delete_expense_result = $delete_expense->execute();
         if (!$delete_expense_result->success) {
             // NOW WE HAVE A REALLY BIG PROBLEM ON OUR HANDS.
             throw new Exception("Error creating account transaction for expense. COULD NOT DELETE EXPENSE! " . $delete_expense_result->error);
         }
         throw new Exception("Error creating account transaction: " . $account_create_transaction_result->error);
     }
     // We're good!
     $this->_expense->create_transaction_id = $account_create_transaction_result->data->transaction->id;
     $this->_expense->save();
     // We need to reload the expense so that we can get the correct balance, etc.
     $this->_expense = $this->_load_vendor_expense($this->_expense->id);
     return (object) array("expense" => $this->_return_vendor_expense_element($this->_expense));
 }
Example #11
0
 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();
     }
 }
Example #12
0
 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.");
     }
     // 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 (!$this->_data->amount) {
         throw new Exception("Invalid payment amount: none provided.");
     }
     // Formulate data request object for Beans_Account_Transaction_Create
     $create_transaction_data = new stdClass();
     $create_transaction_data->code = isset($this->_data->number) ? $this->_data->number : NULL;
     $create_transaction_data->description = isset($this->_data->description) ? $this->_data->description : NULL;
     $create_transaction_data->date = isset($this->_data->date) ? $this->_data->date : NULL;
     $create_transaction_data->reference = isset($this->_data->check_number) ? $this->_data->check_number : NULL;
     $create_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 purchase order " . $purchase->code . " included: vendor mismatch. All purchase purchases must belong to the same vendor.");
             }
         }
         if (!$purchase->date_billed 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 (isset($purchase_payment->invoice_number) and $purchase_payment->invoice_number or isset($purchase_payment->date_billed) and $purchase_payment->date_billed)) {
                 $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, 'date_billed' => $purchase_payment->date_billed, '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, $create_transaction_data->date, NULL);
         $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 $this->_journal_cmp($purchase->date_billed, $purchase->invoice_transaction_id, $create_transaction_data->date, NULL) < 0 or $purchase->date_cancelled and $purchase->cancel_transaction_id and $this->_journal_cmp($purchase->date_cancelled, $purchase->cancel_transaction_id, $create_transaction_data->date, NULL) < 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) {
         // 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.");
         }
         // Flip the sign. ( Just like $purchase_account_transfers[$payment_account->id] = $this->_data->amount etc. below )
         $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;
         }
     }
     $create_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);
             }
         }
         $create_transaction_data->account_transactions[] = $account_transaction;
     }
     $vendor = $this->_load_vendor($vendor_id);
     $create_transaction_data->description = $create_transaction_data->description ? "Vendor Payment Recorded: " . $create_transaction_data->description : "Vendor Payment Recorded: " . $vendor->company_name;
     $create_transaction_data->entity_id = $vendor_id;
     $create_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($create_transaction_data));
     $create_transaction_result = $create_transaction->execute();
     if (!$create_transaction_result->success) {
         throw new Exception("An error occurred creating that payment: " . $create_transaction_result->error);
     }
     // Recalibrate Vendor Invoices
     $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 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' => $create_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($create_transaction_result->data->transaction->id)));
 }
Example #13
0
 public function action_startingbalancevalidate()
 {
     $create_transaction_data = new stdClass();
     $create_transaction_data->validate_only = TRUE;
     $create_transaction_data->account_transactions = array();
     $create_transaction_data->date = date("Y-m-d");
     if ($this->request->post('date') and strlen($this->request->post('date'))) {
         $create_transaction_data->date = date("Y-m-d", strtotime($this->request->post('date')));
     }
     $account_transactions_data = json_decode($this->request->post('account_transactions'));
     foreach ($account_transactions_data as $key => $value) {
         $value_numeric = $this->_get_numeric_value($value);
         if (strpos($key, 'account_debit_') !== FALSE and strlen($value_numeric) and floatval($value_numeric) != 0) {
             $create_transaction_data->account_transactions[] = (object) array('account_id' => str_replace('account_debit_', '', $key), 'amount' => -1 * $value_numeric);
         } else {
             if (strpos($key, 'account_credit_') !== FALSE and strlen($value_numeric) and floatval($value_numeric) != 0) {
                 $create_transaction_data->account_transactions[] = (object) array('account_id' => str_replace('account_credit_', '', $key), 'amount' => $value_numeric);
             }
         }
     }
     $create_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($create_transaction_data));
     $create_transaction_result = $create_transaction->execute();
     if (!$create_transaction_result->success) {
         return $this->_return_error($this->_beans_result_get_error($create_transaction_result));
     }
 }
Example #14
0
 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();
     }
 }
Example #15
0
 protected function _execute()
 {
     if (!$this->_expense->loaded()) {
         throw new Exception("Expense could not be found.");
     }
     if ($this->_check_books_closed($this->_expense->date_created) && $this->_expense->create_transaction_id && $this->_expense->invoice_transaction_id && $this->_expense->cancel_transaction_id) {
         throw new Exception("Expense could not be updated.  The financial year has been closed already.");
     }
     if (isset($this->_data->vendor_id)) {
         $this->_expense->entity_id = $this->_data->vendor_id;
     }
     if (isset($this->_data->account_id)) {
         $this->_expense->account_id = $this->_data->account_id;
     }
     if (isset($this->_data->sent)) {
         $this->_expense->sent = $this->_data->sent;
     }
     if (isset($this->_data->date_created)) {
         $this->_expense->date_created = $this->_data->date_created;
     }
     if (isset($this->_data->expense_number)) {
         $this->_expense->code = $this->_data->expense_number;
     }
     if (isset($this->_data->invoice_number)) {
         $this->_expense->reference = $this->_data->invoice_number;
     }
     if (isset($this->_data->so_number)) {
         $this->_expense->alt_reference = $this->_data->so_number;
     }
     if (isset($this->_data->remit_address_id)) {
         $this->_expense->remit_address_id = $this->_data->remit_address_id;
     }
     // Make sure we have good expense information before moving on.
     $this->_validate_vendor_expense($this->_expense);
     if ($this->_attributes_only) {
         $this->_expense->save();
         return (object) array("success" => TRUE, "auth_error" => "", "error" => "", "data" => (object) array("expense" => $this->_return_vendor_expense_element($this->_expense)));
     }
     $this->_expense->total = 0.0;
     $this->_expense->amount = 0.0;
     if (!isset($this->_data->lines) or !is_array($this->_data->lines) or !count($this->_data->lines)) {
         throw new Exception("Invalid expense lines: none provided.");
     }
     $i = 0;
     foreach ($this->_data->lines as $expense_line) {
         $new_expense_line = $this->_default_form_line();
         $new_expense_line->account_id = isset($expense_line->account_id) ? (int) $expense_line->account_id : NULL;
         $new_expense_line->description = isset($expense_line->description) ? $expense_line->description : NULL;
         $new_expense_line->amount = isset($expense_line->amount) ? $this->_beans_round($expense_line->amount) : NULL;
         $new_expense_line->quantity = isset($expense_line->quantity) ? (double) $expense_line->quantity : NULL;
         $this->_validate_form_line($new_expense_line);
         $new_expense_line->total = $this->_beans_round($new_expense_line->amount * $new_expense_line->quantity);
         $new_expense_line_total = $this->_beans_round($new_expense_line->total);
         $this->_expense->amount = $this->_beans_round($this->_expense->amount + $new_expense_line->total);
         $this->_expense_lines[$i] = $new_expense_line;
         $i++;
     }
     $this->_expense->total = $this->_beans_round($this->_expense->total + $this->_expense->amount);
     // Cancel Account Transaction
     if ($this->_expense->create_transaction_id) {
         $account_transaction_delete = new Beans_Account_Transaction_Delete($this->_beans_data_auth((object) array('id' => $this->_expense->create_transaction_id, 'form_type_handled' => 'expense', 'payment_type_handled' => 'expense')));
         $account_transaction_delete_result = $account_transaction_delete->execute();
         if (!$account_transaction_delete_result->success) {
             throw new Exception("Error cancelling account transaction: " . $account_transaction_delete_result->error);
         }
         $this->_expense->create_transaction_id = NULL;
     }
     // Delete all current expense children.
     foreach ($this->_expense->form_lines->find_all() as $expense_line) {
         $expense_line->delete();
     }
     // Save expense + Children
     $this->_expense->save();
     // We "decrease" the account.
     $expense_account = $this->_load_account($this->_expense->account_id);
     $this->_account_transactions[$this->_expense->account_id] = $this->_expense->total;
     foreach ($this->_expense_lines as $j => $expense_line) {
         $expense_line->form_id = $this->_expense->id;
         $expense_line->save();
         if (!isset($this->_account_transactions[$expense_line->account_id])) {
             $this->_account_transactions[$expense_line->account_id] = 0.0;
         }
         $this->_account_transactions[$expense_line->account_id] = $this->_beans_round($this->_account_transactions[$expense_line->account_id] + $this->_beans_round($expense_line->amount * $expense_line->quantity));
     }
     // Generate Account Transaction
     $account_create_transaction_data = new stdClass();
     $account_create_transaction_data->code = isset($this->_data->check_number) ? $this->_data->check_number : $this->_expense->create_transaction->code;
     $account_create_transaction_data->description = "Expense Recorded: " . $this->_expense->entity->company_name;
     $account_create_transaction_data->date = $this->_expense->date_created;
     $account_create_transaction_data->account_transactions = array();
     $account_create_transaction_data->payment = "expense";
     $account_create_transaction_data->reference = isset($this->_data->check_number) ? $this->_data->check_number : $this->_expense->create_transaction->reference;
     $account_create_transaction_data->form_type = 'expense';
     $account_create_transaction_data->form_id = $this->_expense->id;
     foreach ($this->_account_transactions as $account_id => $amount) {
         $account_transaction = new stdClass();
         $account_transaction->account_id = $account_id;
         $account_transaction->amount = $account_id == $this->_expense->account_id ? $amount : $amount * -1;
         $account_transaction->forms = array((object) array("form_id" => $this->_expense->id, "amount" => $account_transaction->amount));
         $account_create_transaction_data->account_transactions[] = $account_transaction;
     }
     $account_create_transaction = new Beans_Account_Transaction_Create($this->_beans_data_auth($account_create_transaction_data));
     $account_create_transaction_result = $account_create_transaction->execute();
     if (!$account_create_transaction_result->success) {
         // We've had an account transaction failure and need to delete the expense we just created.
         $delete_expense = new Beans_vendor_expense_Delete($this->_beans_data_auth((object) array('id' => $this->_expense->id)));
         $delete_expense_result = $delete_expense->execute();
         // NOW WE HAVE A REALLY BIG PROBLEM ON OUR HANDS.
         if (!$delete_expense_result->success) {
             throw new Exception("Error creating account transaction for expense. COULD NOT DELETE EXPENSE! " . $delete_expense_result->error);
         }
         throw new Exception("Error creating account transaction: " . $account_create_transaction_result->error);
     }
     // We're good!
     $this->_expense->create_transaction_id = $account_create_transaction_result->data->transaction->id;
     $this->_expense->save();
     $this->_expense = $this->_load_vendor_expense($this->_expense->id);
     return (object) array("expense" => $this->_return_vendor_expense_element($this->_expense));
 }