protected function _execute() { if (!isset($this->_data->id)) { throw new Exception("Purchase could not be found: no ID provided."); } $purchase = $this->_load_vendor_purchase($this->_data->id); if (!$purchase->loaded()) { throw new Exception("Purchase could not be found."); } if (!$purchase->date_billed) { throw new Exception("Purchase invoices cannot be updated before first creating the invoice."); } $requires_calibration = FALSE; if ($this->_data->invoice_number and strlen($this->_data->invoice_number) > 16) { throw new Exception("Invalid invoice number: maximum of 16 characters."); } if ($this->_data->invoice_number) { $purchase->aux_reference = $this->_data->invoice_number; } if ($this->_data->date_billed and $this->_data->date_billed != date("Y-m-d", strtotime($this->_data->date_billed))) { throw new Exception("Invalid invoice date: must be in YYYY-MM-DD format."); } if ($this->_data->date_billed != $purchase->date_billed) { $requires_calibration = TRUE; $purchase->date_billed = $this->_data->date_billed; } $this->_validate_vendor_purchase($purchase); if ($this->_validate_only) { return (object) array(); } $purchase->save(); if ($requires_calibration) { $vendor_purchase_calibrate = new Beans_Vendor_Purchase_Calibrate($this->_beans_data_auth((object) array('ids' => array($purchase->id)))); $vendor_purchase_calibrate_result = $vendor_purchase_calibrate->execute(); if (!$vendor_purchase_calibrate_result->success) { throw new Exception("UNEXPECTED ERROR: COULD NOT CALIBRATE VENDOR PURCHASE: " . $vendor_purchase_calibrate_result->error); } // Reload Purchase $purchase = $this->_load_vendor_purchase($this->_data->id); } return (object) array("purchase" => $this->_return_vendor_purchase_element($purchase)); }
protected function _execute() { if (!$this->_purchase->loaded()) { throw new Exception("Purchase purchase could not be found."); } if ($this->_purchase->date_cancelled || $this->_purchase->cancel_transaction_id) { throw new Exception("Purchase has already been cancelled."); } if ($this->_check_books_closed($this->_purchase->date_created)) { throw new Exception("Purchase purchase could not be deleted. The financial year has been closed already."); } if ($this->_purchase->refund_form_id and $this->_purchase->refund_form_id > $this->_purchase->id) { throw new Exception("Purchase could not be cancelled - it has a refund attached to it."); } $date_cancelled = date("Y-m-d"); $this->_purchase->date_cancelled = $date_cancelled; $this->_purchase->save(); $purchase_calibrate = new Beans_Vendor_Purchase_Calibrate($this->_beans_data_auth((object) array('ids' => array($this->_purchase->id)))); $purchase_calibrate_result = $purchase_calibrate->execute(); $this->_purchase = $this->_load_vendor_purchase($this->_purchase->id); if (!$purchase_calibrate_result->success) { $this->_purchase->date_cancelled = NULL; $this->_purchase->save(); throw new Exception("Error trying to cancel purchase: " . $purchase_calibrate_result->error); } // Remove the refund form from the corresponding form. if ($this->_purchase->refund_form->loaded()) { $this->_purchase->refund_form->refund_form_id = NULL; $this->_purchase->refund_form->save(); } // Recalibrate Payments $vendor_payment_calibrate = new Beans_Vendor_Payment_Calibrate($this->_beans_data_auth((object) array('form_ids' => array($this->_purchase->id)))); $vendor_payment_calibrate_result = $vendor_payment_calibrate->execute(); if (!$vendor_payment_calibrate_result->success) { throw new Exception("Error encountered when calibrating payments: " . $vendor_payment_calibrate_result->error); } $this->_purchase = $this->_load_vendor_purchase($this->_purchase->id); return (object) array("purchase" => $this->_return_vendor_purchase_element($this->_purchase)); }
public function action_calibratedate() { $date = $this->request->post('date'); $manual = $this->request->post('manual'); if (!$date or $date != date("Y-m-d", strtotime($date))) { return $this->_return_error('Invalid date provided: ' . $date . ' expected YYYY-MM-DD'); } // If manual, we don;t want them trying to calibrate pre-fye if ($manual == "1") { $account_closebooks_check = new Beans_Account_Closebooks_Check($this->_beans_data_auth()); $account_closebooks_check_result = $account_closebooks_check->execute(); if (!$account_closebooks_check_result->success) { return $this->_return_error("An unexpected error occurred when trying to validate the date: " . $account_closebooks_check_result->error); } if ($account_closebooks_check_result->data->previous_date && strtotime($date) <= strtotime($account_closebooks_check_result->data->previous_date)) { return $this->_return_error("The books were closed most recently on " . $account_closebooks_check_result->data->previous_date . ". " . "Please choose a date after that to begin manual calibration."); } } // This can take a while. set_time_limit(60 * 10); ini_set('memory_limit', '256M'); // Recalibrate Customer Invoices / Cancellations $customer_sale_calibrate = new Beans_Customer_Sale_Calibrate($this->_beans_data_auth((object) array('date_after' => $date, 'date_before' => $date))); $customer_sale_calibrate_result = $customer_sale_calibrate->execute(); if (!$customer_sale_calibrate_result->success) { return $this->_return_error('Error updating customer sales: ' . $customer_sale_calibrate_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('date_after' => $date, 'date_before' => $date))); $customer_payment_calibrate_result = $customer_payment_calibrate->execute(); if (!$customer_payment_calibrate_result->success) { return $this->_return_error('Error updating customer payments: ' . $customer_payment_calibrate_result->error); } // Recalibrate Vendor Invoices / Cancellations $vendor_purchase_calibrate = new Beans_Vendor_Purchase_Calibrate($this->_beans_data_auth((object) array('date_after' => $date, 'date_before' => $date))); $vendor_purchase_calibrate_result = $vendor_purchase_calibrate->execute(); if (!$vendor_purchase_calibrate_result->success) { return $this->_return_error('Error updating vendor purchases: ' . $vendor_purchase_calibrate_result->error); } // Recalibrate any payments tied to these purchases AFTER this transaction date. $vendor_payment_calibrate = new Beans_Vendor_Payment_Calibrate($this->_beans_data_auth((object) array('date_after' => $date, 'date_before' => $date))); $vendor_payment_calibrate_result = $vendor_payment_calibrate->execute(); if (!$vendor_payment_calibrate_result->success) { return $this->_return_error('Error updating vendor payments: ' . $vendor_payment_calibrate_result->error); } $this->_return_object->data->date_next = date("Y-m-d", strtotime($date . " +1 Day")); $account_transaction_search = new Beans_Account_Transaction_Search($this->_beans_data_auth((object) array('sort_by' => 'newest', 'page_size' => 1))); $account_transaction_search_result = $account_transaction_search->execute(); if (!$account_transaction_search_result->success || !count($account_transaction_search_result->data->transactions)) { return $this->_return_error('Error getting ending transaction: ' . $account_transaction_search_result->error); } $date_end = $account_transaction_search_result->data->transactions[0]->date; // This gets run on the very last iteration of calibration. if (strtotime($date_end) < strtotime($this->_return_object->data->date_next)) { $this->_return_object->data->date_next = FALSE; $account_calibrate = new Beans_Account_Calibrate($this->_beans_data_auth()); $account_calibrate_result = $account_calibrate->execute(); if (!$account_calibrate_result->success) { return $this->_return_error('Error calibrating individual account balances: ' . $account_calibrate_result->error); } $customer_sale_calibrate_check = new Beans_Customer_Sale_Calibrate_Check($this->_beans_data_auth()); $customer_sale_calibrate_check_result = $customer_sale_calibrate_check->execute(); if (!$customer_sale_calibrate_check_result->success) { return $this->_return_error('Error calibrating customer sales: ' . $customer_sale_calibrate_check_result->error); } if (count($customer_sale_calibrate_check_result->data->ids)) { $customer_sale_calibrate = new Beans_Customer_Sale_Calibrate($this->_beans_data_auth((object) array('ids' => $customer_sale_calibrate_check_result->data->ids))); $customer_sale_calibrate_result = $customer_sale_calibrate->execute(); if (!$customer_sale_calibrate_result->success) { return $this->_return_error('Error calibrating customer sales: ' . $customer_sale_calibrate_result->error); } } $vendor_purchase_calibrate_check = new Beans_Vendor_Purchase_Calibrate_Check($this->_beans_data_auth()); $vendor_purchase_calibrate_check_result = $vendor_purchase_calibrate_check->execute(); if (!$vendor_purchase_calibrate_check_result->success) { return $this->_return_error('Error calibrating vendor purchases: ' . $vendor_purchase_calibrate_check_result->error); } if (count($vendor_purchase_calibrate_check_result->data->ids)) { $vendor_purchase_calibrate = new Beans_Vendor_Purchase_Calibrate($this->_beans_data_auth((object) array('ids' => $vendor_purchase_calibrate_check_result->data->ids))); $vendor_purchase_calibrate_result = $vendor_purchase_calibrate->execute(); if (!$vendor_purchase_calibrate_result->success) { return $this->_return_error('Error calibrating vendor purchases: ' . $vendor_purchase_calibrate_result->error); } } } // Update our latest date in case user pauses and comes back later. // We only do this if the user isn't manually recalibrating books. if ($manual !== "1") { $setup_company_update = new Beans_Setup_Company_Update($this->_beans_data_auth((object) array('settings' => array('calibrate_date_next' => $this->_return_object->data->date_next)))); $setup_company_update_result = $setup_company_update->execute(); } }
protected function _execute() { if (!$this->_purchase->loaded()) { throw new Exception("purchase could not be found."); } 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."); } // Independently validate $this->_date_billed and $this->_invoice_number if ($this->_date_billed and $this->_date_billed != date("Y-m-d", strtotime($this->_date_billed))) { throw new Exception("Invalid invoice date: must be in YYYY-MM-DD format."); } if ($this->_invoice_number and strlen($this->_invoice_number) > 16) { throw new Exception("Invalid invoice number: maxmimum length of 16 characters."); } if ($this->_invoice_number and !$this->_date_billed) { throw new Exception("Both an invoice number and date are required."); } // There's a unique use-case that's hard to replicate, but it produces a form that // has no create_transaction - closing the FYE with this form can be frustrating to deal with otherwise. if ($this->_check_books_closed($this->_purchase->date_created) && $this->_purchase->create_transaction_id && $this->_purchase->invoice_transaction_id && $this->_purchase->cancel_transaction_id) { throw new Exception("purchase could not be updated. The financial year has been closed already."); } if ($this->_purchase->date_cancelled) { throw new Exception("A purchase cannot be updated after it has been cancelled."); } if (isset($this->_data->vendor_id)) { $this->_purchase->entity_id = $this->_data->vendor_id; } if (isset($this->_data->account_id)) { $this->_purchase->account_id = $this->_data->account_id; } if (isset($this->_data->sent)) { $this->_purchase->sent = $this->_data->sent; } if (isset($this->_data->date_created)) { $this->_purchase->date_created = $this->_data->date_created; } if (isset($this->_data->purchase_number)) { $this->_purchase->code = $this->_data->purchase_number; } if (isset($this->_data->so_number)) { $this->_purchase->reference = $this->_data->so_number; } if (isset($this->_data->quote_number)) { $this->_purchase->alt_reference = $this->_data->quote_number; } if (isset($this->_data->invoice_number)) { $this->_purchase->aux_reference = $this->_data->invoice_number; } if (isset($this->_data->date_billed)) { if (strtotime($this->_data->date_billed) < strtotime($this->_purchase->date_created)) { throw new Exception("Invalid invoice date: must be on or after the creation date of " . $this->_purchase->date_created . "."); } $this->_purchase->date_billed = $this->_data->date_billed; $account = $this->_load_account($this->_purchase->account_id); $this->_purchase->date_due = date("Y-m-d", strtotime($this->_purchase->date_billed . ' +' . $account->terms . ' Days')); } if (isset($this->_data->remit_address_id)) { $this->_purchase->remit_address_id = $this->_data->remit_address_id; } if (isset($this->_data->shipping_address_id)) { $this->_purchase->shipping_address_id = $this->_data->shipping_address_id; } // Make sure we have good purchase information before moving on. $this->_validate_vendor_purchase($this->_purchase); if ($this->_attributes_only) { $this->_purchase->save(); return (object) array("success" => TRUE, "auth_error" => "", "error" => "", "data" => (object) array("purchase" => $this->_return_vendor_purchase_element($this->_purchase))); } $this->_purchase->total = 0.0; $this->_purchase->amount = 0.0; if (!isset($this->_data->lines) or !is_array($this->_data->lines) or !count($this->_data->lines)) { throw new Exception("Invalid purchase purchase lines: none provided."); } $adjustment_entered = FALSE; foreach ($this->_data->lines as $purchase_line) { $new_purchase_line = $this->_default_form_line(); $new_purchase_line->account_id = isset($purchase_line->account_id) ? (int) $purchase_line->account_id : NULL; $new_purchase_line->description = isset($purchase_line->description) ? $purchase_line->description : NULL; $new_purchase_line->amount = isset($purchase_line->amount) ? $this->_beans_round($purchase_line->amount) : NULL; $new_purchase_line->quantity = isset($purchase_line->quantity) ? (double) $purchase_line->quantity : NULL; $new_purchase_line->adjustment = isset($purchase_line->adjustment) ? $purchase_line->adjustment : FALSE; if ($new_purchase_line->adjustment and $adjustment_entered) { throw new Exception("Invalid purchase line: can only have one adjustment line."); } else { if ($new_purchase_line->adjustment and $new_purchase_line->quantity != 1) { throw new Exception("Invalid purchase line: adjustment lines must have a quantity of 1."); } else { if ($new_purchase_line->adjustment) { $adjustment_entered = TRUE; } } } if ($new_purchase_line->account_id === NULL) { $new_purchase_line->account_id = $this->_beans_setting_get('account_default_costofgoods'); } $this->_validate_form_line($new_purchase_line); $new_purchase_line->total = $this->_beans_round($new_purchase_line->amount * $new_purchase_line->quantity); $new_purchase_line_total = $this->_beans_round($new_purchase_line->total); $this->_purchase->amount = $this->_beans_round($this->_purchase->amount + $new_purchase_line->total); $this->_purchase_lines[] = $new_purchase_line; } $this->_purchase->total = $this->_beans_round($this->_purchase->total + $this->_purchase->amount); // Validate Totals if ($this->_purchase->refund_form_id) { $refund_form = $this->_load_vendor_purchase($this->_purchase->refund_form_id); $original_purchase = $this->_purchase; $refund_purchase = $refund_form; if ($this->_purchase->refund_form_id < $this->_purchase->id) { $refund_purchase = $this->_purchase; $original_purchase = $refund_form; } if ($original_purchase->total > 0.0 and $refund_purchase->total > 0.0 or $original_purchase->total < 0.0 and $refund_purchase->total < 0.0) { throw new Exception("Refund and original purchase totals must offset each other ( they cannot both be positive or negative )."); } if (abs($refund_purchase->total) > abs($original_purchase->total)) { throw new Exception("The refund total cannot be greater than the original purchase total."); } } // Delete all current purchase children. foreach ($this->_purchase->form_lines->find_all() as $purchase_line) { $purchase_line->delete(); } // Save purchase + Children $this->_purchase->save(); foreach ($this->_purchase_lines as $j => $purchase_line) { $purchase_line->form_id = $this->_purchase->id; $purchase_line->save(); } $purchase_calibrate = new Beans_Vendor_Purchase_Calibrate($this->_beans_data_auth((object) array('ids' => array($this->_purchase->id)))); $purchase_calibrate_result = $purchase_calibrate->execute(); if (!$purchase_calibrate_result->success) { throw new Exception("Error encountered when calibrating payments: " . $purchase_calibrate_result->error); } // Recalibrate Payments $vendor_payment_calibrate = new Beans_Vendor_Payment_Calibrate($this->_beans_data_auth((object) array('form_ids' => array($this->_purchase->id)))); $vendor_payment_calibrate_result = $vendor_payment_calibrate->execute(); if (!$vendor_payment_calibrate_result->success) { throw new Exception("Error encountered when calibrating payments: " . $vendor_payment_calibrate_result->error); } $this->_purchase = $this->_load_vendor_purchase($this->_purchase->id); return (object) array("purchase" => $this->_return_vendor_purchase_element($this->_purchase)); }
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."); } // Independently validate $this->_date_billed and $this->_invoice_number if ($this->_date_billed and $this->_date_billed != date("Y-m-d", strtotime($this->_date_billed))) { throw new Exception("Invalid invoice date: must be in YYYY-MM-DD format."); } if ($this->_invoice_number and strlen($this->_invoice_number) > 16) { throw new Exception("Invalid invoice number: maxmimum length of 16 characters."); } if ($this->_invoice_number and !$this->_date_billed) { throw new Exception("An invoice date is required if an invoice number is provided."); } $this->_purchase->entity_id = isset($this->_data->vendor_id) ? $this->_data->vendor_id : NULL; $this->_purchase->account_id = isset($this->_data->account_id) ? $this->_data->account_id : NULL; $this->_purchase->refund_form_id = isset($this->_data->refund_purchase_id) ? $this->_data->refund_purchase_id : NULL; $this->_purchase->sent = isset($this->_data->sent) ? $this->_data->sent : NULL; $this->_purchase->date_created = isset($this->_data->date_created) ? $this->_data->date_created : NULL; $this->_purchase->code = (isset($this->_data->purchase_number) and $this->_data->purchase_number) ? $this->_data->purchase_number : "AUTOGENERATE"; $this->_purchase->reference = isset($this->_data->so_number) ? $this->_data->so_number : NULL; $this->_purchase->alt_reference = isset($this->_data->quote_number) ? $this->_data->quote_number : NULL; $this->_purchase->remit_address_id = isset($this->_data->remit_address_id) ? (int) $this->_data->remit_address_id : NULL; $this->_purchase->shipping_address_id = isset($this->_data->shipping_address_id) ? (int) $this->_data->shipping_address_id : NULL; if ($this->_date_billed and strtotime($this->_date_billed) < strtotime($this->_purchase->date_created)) { throw new Exception("Invalid invoice date: must be on or after the creation date of " . $this->_purchase->date_created . "."); } // Handle Default Account Payable // Vendor Default Account Payable if ($this->_purchase->account_id === NULL) { $vendor = $this->_load_vendor($this->_purchase->entity_id); if ($vendor->loaded() and $vendor->default_account_id) { $this->_purchase->account_id = $vendor->default_account_id; } } // Default Account Payable if ($this->_purchase->account_id === NULL) { $this->_purchase->account_id = $this->_beans_setting_get('account_default_payable'); } // Make sure we have good purchase information before moving on. $this->_validate_vendor_purchase($this->_purchase); $this->_purchase->total = 0.0; $this->_purchase->amount = 0.0; if (!isset($this->_data->lines) or !is_array($this->_data->lines) or !count($this->_data->lines)) { throw new Exception("Invalid purchase lines: none provided."); } foreach ($this->_data->lines as $purchase_line) { $new_purchase_line = $this->_default_form_line(); $new_purchase_line->account_id = isset($purchase_line->account_id) ? (int) $purchase_line->account_id : NULL; $new_purchase_line->description = isset($purchase_line->description) ? $purchase_line->description : NULL; $new_purchase_line->amount = isset($purchase_line->amount) ? $this->_beans_round($purchase_line->amount) : NULL; $new_purchase_line->quantity = isset($purchase_line->quantity) ? (double) $purchase_line->quantity : NULL; // Handle Default Cost of Goods if ($new_purchase_line->account_id === NULL) { $new_purchase_line->account_id = $this->_beans_setting_get('account_default_costofgoods'); } $this->_validate_form_line($new_purchase_line); $new_purchase_line->total = $this->_beans_round($new_purchase_line->amount * $new_purchase_line->quantity); $new_purchase_line_total = $new_purchase_line->total; $this->_purchase->amount = $this->_beans_round($this->_purchase->amount + $new_purchase_line->total); $this->_purchase_lines[] = $new_purchase_line; } $this->_purchase->total = $this->_beans_round($this->_purchase->total + $this->_purchase->amount); // Validate Totals if ($this->_purchase->refund_form_id) { $refund_form = $this->_load_vendor_purchase($this->_purchase->refund_form_id); if (!$refund_form->loaded()) { throw new Exception("That refund_purchase_id was not found."); } $original_purchase = $refund_form; $refund_purchase = $this->_purchase; if ($original_purchase->total > 0.0 and $refund_purchase->total > 0.0 or $original_purchase->total < 0.0 and $refund_purchase->total < 0.0) { throw new Exception("Refund and original purchase totals must offset each other ( they cannot both be positive or negative )."); } if (abs($refund_purchase->total) > abs($original_purchase->total)) { throw new Exception("The refund total cannot be greater than the original purchase total."); } } // Save Purchase + Children $this->_purchase->save(); if ($this->_purchase->code == "AUTOGENERATE") { $this->_purchase->code = $this->_purchase->id; } foreach ($this->_purchase_lines as $j => $purchase_line) { $purchase_line->form_id = $this->_purchase->id; $purchase_line->save(); } $this->_purchase->save(); $purchase_calibrate = new Beans_Vendor_Purchase_Calibrate($this->_beans_data_auth((object) array('ids' => array($this->_purchase->id)))); $purchase_calibrate_result = $purchase_calibrate->execute(); if (!$purchase_calibrate_result->success) { // We've had an account transaction failure and need to delete the purchase we just created. $delete_purchase = new Beans_Vendor_Purchase_Delete($this->_beans_data_auth((object) array('id' => $this->_purchase->id))); $delete_purchase_result = $delete_purchase->execute(); // V2Item // Fatal error! Ensure coverage or ascertain 100% success. if (!$delete_purchase_result->success) { throw new Exception("Error creating account transaction for purchase purchase. " . "COULD NOT DELETE PURCHASE ORDER! " . $delete_purchase_result->error); } throw new Exception("Error trying to create purchase: " . $purchase_calibrate_result->error); } // Reload the sale. $this->_purchase = $this->_load_vendor_purchase($this->_purchase->id); if ($this->_date_billed) { $vendor_purchase_invoice = new Beans_Vendor_Purchase_Invoice($this->_beans_data_auth((object) array('id' => $this->_purchase->id, 'date_billed' => $this->_date_billed, 'invoice_number' => $this->_invoice_number))); $vendor_purchase_invoice_result = $vendor_purchase_invoice->execute(); // If it fails - we undo everything. if (!$vendor_purchase_invoice_result->success) { $vendor_purchase_delete = new Beans_Vendor_Purchase_Delete($this->_beans_data_auth((object) array('id' => $this->_purchase->id))); $vendor_purchase_delete_result = $vendor_purchase_delete->execute(); if (!$vendor_purchase_delete_result->success) { throw new Exception("Error creating account transaction for purchase invoice." . "COULD NOT DELETE PURCHASE! " . $vendor_purchase_delete_result->error . ' ' . $vendor_purchase_invoice_result->error); } throw new Exception("Error creating purchase invoice transaction: " . $vendor_purchase_invoice_result->error); } return $this->_beans_return_internal_result($vendor_purchase_invoice_result); } // We need to reload the purchase so that we can get the correct balance, etc. $this->_purchase = $this->_load_vendor_purchase($this->_purchase->id); return (object) array("purchase" => $this->_return_vendor_purchase_element($this->_purchase)); }
protected function _execute() { if (!$this->_purchase->loaded()) { throw new Exception("That purchase could not be found."); } if ($this->_purchase->date_cancelled) { throw new Exception("A purchase cannot be converted to an invoice after it has been cancelled."); } if ($this->_purchase->date_billed) { throw new Exception("That purchase has already been converted to an invoice."); } 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->_date_billed != date("Y-m-d", strtotime($this->_date_billed))) { throw new Exception("Invalid invoice date: must be in YYYY-MM-DD format."); } if (strtotime($this->_date_billed) < strtotime($this->_purchase->date_created)) { throw new Exception("Invalid invoice date: must be on or after the creation date of " . $this->_purchase->date_created . "."); } if ($this->_invoice_number and strlen($this->_invoice_number) > 16) { throw new Exception("Invalid invoice number: maximum of 16 characters."); } if ($this->_so_number and strlen($this->_so_number) > 16) { throw new Exception("Invalid SO number: maximum of 16 characters."); } // Figure out if we need to create an adjusting entry. if ($this->_invoice_amount and $this->_purchase->total != $this->_invoice_amount) { if (!$this->_invoice_adjustment_description) { throw new Exception("Invalid invoice adjustment description: none provided."); } if (!$this->_invoice_adjustment_account_id) { throw new Exception("Invalid invoice adjustment writeoff account: none provided."); } // Add line to purchase. $purchase_lines = array(); foreach ($this->_purchase->form_lines->find_all() as $line) { $purchase_lines[] = (object) array('description' => $line->description, 'account_id' => $line->account_id, 'quantity' => $line->quantity, 'amount' => $line->amount); } $purchase_lines[] = (object) array('description' => $this->_invoice_adjustment_description, 'account_id' => $this->_invoice_adjustment_account_id, 'quantity' => 1, 'amount' => $this->_beans_round($this->_invoice_amount - $this->_purchase->total), 'adjustment' => TRUE); if (!$this->_validate_only) { $vendor_purchase_update = new Beans_Vendor_Purchase_Update($this->_beans_data_auth((object) array('id' => $this->_purchase->id, 'lines' => $purchase_lines))); $vendor_purchase_update_result = $vendor_purchase_update->execute(); if (!$vendor_purchase_update_result->success) { throw new Exception("Could not adjust purchase: " . $vendor_purchase_update_result->error); } // Re-load purchase. $this->_purchase = $this->_load_vendor_purchase($this->_purchase->id); } } if ($this->_validate_only) { return (object) array(); } $this->_purchase->date_billed = $this->_date_billed; $this->_purchase->date_due = date("Y-m-d", strtotime($this->_purchase->date_billed . ' +' . $this->_purchase->account->terms . ' Days')); if (strlen($this->_invoice_number)) { $this->_purchase->aux_reference = $this->_invoice_number; } if ($this->_so_number) { $this->_purchase->reference = $this->_so_number; } $this->_purchase->save(); $purchase_calibrate = new Beans_Vendor_Purchase_Calibrate($this->_beans_data_auth((object) array('ids' => array($this->_purchase->id)))); $purchase_calibrate_result = $purchase_calibrate->execute(); $this->_purchase = $this->_load_vendor_purchase($this->_purchase->id); if (!$purchase_calibrate_result->success) { $this->_purchase->date_billed = NULL; $this->_purchase->date_due = NULL; $this->_purchase->aux_reference = NULL; $this->_purchase->reference = NULL; $this->_purchase->save(); throw new Exception("Error trying to invoice purchase: " . $purchase_calibrate_result->error); } // Recalibrate Payments $vendor_payment_calibrate = new Beans_Vendor_Payment_Calibrate($this->_beans_data_auth((object) array('form_ids' => array($this->_purchase->id)))); $vendor_payment_calibrate_result = $vendor_payment_calibrate->execute(); if (!$vendor_payment_calibrate_result->success) { throw new Exception("Error encountered when calibrating payments: " . $vendor_payment_calibrate_result->error); } $this->_purchase = $this->_load_vendor_purchase($this->_purchase->id); return (object) array("purchase" => $this->_return_vendor_purchase_element($this->_purchase)); }