Example #1
0
 function autopay_credit()
 {
     log_write("debug", "invoice_autopay", "Executing autopay_credit()");
     /*
     	Fetch Current Credit Pool Amount
     
     	NOTE: we do a full query here, to prevent caching from giving us incorrect information.
     */
     $sql_obj = new sql_query();
     $sql_obj->string = "SELECT SUM(amount_total) as value FROM customers_credits WHERE id_customer='" . $this->id_org . "' LIMIT 1";
     $sql_obj->execute();
     $sql_obj->fetch_array();
     $amount_credit = $sql_obj->data[0]["value"];
     unset($sql_obj);
     if ($amount_credit > 0) {
         $this->obj_invoice->data["amount_due"] = $this->obj_invoice->data["amount_total"] - $this->obj_invoice->data["amount_paid"];
         if ($amount_credit > $this->obj_invoice->data["amount_due"]) {
             $amount_credit = $this->obj_invoice->data["amount_due"];
         }
     } else {
         log_write("debug", "invoice_autopay", "No credit available");
         return 0;
     }
     /*
     	Define Item Details
     */
     $item = new invoice_items();
     $item->id_invoice = $this->id_invoice;
     $item->type_invoice = $this->type_invoice;
     $item->type_item = "payment";
     $data = array();
     $data["date_trans"] = date("Y-m-d");
     $data["amount"] = $amount_credit;
     $data["source"] = "CREDIT";
     $data["description"] = "Automated Credit Payment";
     $data["chartid"] = "credit";
     if (!$item->prepare_data($data)) {
         log_write("error", "invoice_autopay", "An error was encountered whilst processing credit payment data.");
         return 0;
     }
     $item->action_create();
     $item->action_update();
     $item->action_update_total();
     $item->action_update_ledger();
     if (!$item->id_item) {
         log_write("error", "invoice_autopay", "An error occured whilst creating the credit autopay item");
     }
     unset($item);
     /*
     	Make Credit Payment Item
     */
     log_write("debug", "invoice_autopay", "Autopayment against invoice " . $this->id_invoice . " made from credit pool.");
     return 1;
 }
     } else {
         $data["amount"] = $amount;
     }
     $data["chartid"] = $dest_account;
     $data["source"] = "";
     $data["description"] = "";
     /*
     	Process data
     */
     if (!error_check()) {
         // prepare data
         if (!$item->prepare_data($data)) {
             log_write("error", "process", "An error was encountered whilst processing supplied data.");
         } else {
             // create item
             $item->action_create();
             $item->action_update();
             // update invoice summary totals
             $item->action_update_total();
             $item->action_update_ledger();
         }
     }
     unset($item);
     unset($data);
     break;
 case "transfer":
 case "bank_fee":
 case "interest":
     /*
     	TRANSFER / BANK_FEE / INTEREST
     
 function set_invoice_payment($id, $invoicetype, $itemid, $date_trans, $chartid, $amount, $source, $description)
 {
     log_debug("accounts_invoices_manage", "Executing set_invoice_payment({$id}, {$invoicetype}, values...)");
     // check the invoicetype
     if ($invoicetype != "ar" && $invoicetype != "ap") {
         throw new SoapFault("Sender", "INVALID_INVOICE_TYPE");
     }
     if (user_permissions_get("accounts_" . $invoicetype . "_write")) {
         $obj_invoice_item = new invoice_items();
         $obj_invoice_item->type_invoice = $invoicetype;
         $obj_invoice_item->id_invoice = @security_script_input_predefined("int", $id);
         $obj_invoice_item->id_item = @security_script_input_predefined("any", $itemid);
         $obj_invoice_item->type_item = "payment";
         /*
         	Error Handling
         */
         // verify invoice existance
         if (!$obj_invoice_item->verify_invoice()) {
             throw new SoapFault("Sender", "INVALID_INVOICE");
         }
         // make sure invoice is not locked
         if ($obj_invoice_item->check_lock()) {
             throw new SoapFault("Sender", "LOCKED");
         }
         // verify item existance (if editing one)
         if ($obj_invoice_item->id_item) {
             if (!$obj_invoice_item->verify_item()) {
                 throw new SoapFault("Sender", "INVALID_ITEMID");
             }
         }
         /*
         	Load SOAP data
         */
         $data["date_trans"] = @security_script_input_predefined("date", $date_trans);
         $data["chartid"] = @security_script_input_predefined("int", $chartid);
         $data["amount"] = @security_script_input_predefined("money", $amount);
         $data["source"] = @security_script_input_predefined("any", $source);
         $data["description"] = @security_script_input_predefined("any", $description);
         foreach (array_keys($data) as $key) {
             if ($data[$key] == "error") {
                 throw new SoapFault("Sender", "INVALID_INPUT");
             }
         }
         // process the data
         if (!$obj_invoice_item->prepare_data($data)) {
             throw new SoapFault("Sender", "UNEXPECTED_PREP_ERROR");
         }
         /*
         	Apply Data
         */
         // create SQL transaction
         $sql_obj = new sql_query();
         $sql_obj->trans_begin();
         // create / update payment
         if (!$obj_invoice_item->id_item) {
             if (!$obj_invoice_item->action_create()) {
                 $sql_obj->trans_rollback();
                 throw new SoapFault("Sender", "UNEXPECTED_ACTION_ERROR");
             }
         }
         if (!$obj_invoice_item->action_update()) {
             $sql_obj->trans_rollback();
             throw new SoapFault("Sender", "UNEXPECTED_ACTION_ERROR");
         }
         // update invoice totals
         $obj_invoice_item->action_update_total();
         // Generate ledger entries.
         $obj_invoice_item->action_update_ledger();
         // commit
         if (error_check()) {
             $sql_obj->trans_rollback();
             throw new SoapFault("Sender", "UNEXPECTED_ACTION_ERROR");
         } else {
             $sql_obj->trans_commit();
             return $obj_invoice_item->id_item;
         }
     } else {
         throw new SoapFault("Sender", "ACCESS DENIED");
     }
 }
function invoice_form_items_process($type, $returnpage_error, $returnpage_success)
{
    log_debug("inc_invoices_items", "Executing invoice_form_items_process({$type}, {$returnpage_error}, {$returnpage_success})");
    /*
    	Start invoice_items class
    */
    $item = new invoice_items();
    $item->id_invoice = @security_form_input_predefined("int", "id_invoice", 1, "");
    $item->id_item = @security_form_input_predefined("int", "id_item", 0, "");
    $item->type_invoice = $type;
    $item->type_item = @security_form_input_predefined("any", "item_type", 1, "");
    /*
    	Fetch all form data
    */
    if ($item->id_item) {
        $mode = "edit";
    } else {
        $mode = "add";
    }
    //// ERROR CHECKING ///////////////////////
    /*
    	Check that invoice and item are valid
    */
    if ($item->verify_invoice()) {
        if ($mode == "edit") {
            if (!$item->verify_item()) {
                $_SESSION["error"]["message"][] = "<p><b>Error: The requested item/invoice combination does not exist. Are you trying to use a link to a deleted invoice?</b></p>";
            }
        }
    } else {
        $_SESSION["error"]["message"][] = "<p><b>Error: The requested invoice does not exist.</b></p>";
    }
    // fetch form data
    switch ($item->type_item) {
        case "standard":
            /*
            	STANDARD ITEMS
            */
            // fetch information from form
            $data["amount"] = @security_form_input_predefined("money", "amount", 0, "");
            $data["chartid"] = @security_form_input_predefined("int", "chartid", 1, "");
            $data["description"] = @security_form_input_predefined("any", "description", 0, "");
            // fetch information from all tax checkboxes from form
            $sql_tax_obj = new sql_query();
            $sql_tax_obj->string = "SELECT id FROM account_taxes";
            $sql_tax_obj->execute();
            if ($sql_tax_obj->num_rows()) {
                $sql_tax_obj->fetch_array();
                foreach ($sql_tax_obj->data as $data_tax) {
                    $data["tax_" . $data_tax["id"]] = @security_form_input_predefined("any", "tax_" . $data_tax["id"], 0, "");
                }
            }
            // end of loop through taxes
            break;
        case "product":
            /*
            	PRODUCT ITEMS
            */
            // fetch information from form
            $data["price"] = @security_form_input_predefined("money", "price", 0, "");
            $data["quantity"] = @security_form_input_predefined("float", "quantity", 1, "");
            $data["units"] = @security_form_input_predefined("any", "units", 0, "");
            $data["customid"] = @security_form_input_predefined("int", "productid", 1, "");
            $data["description"] = @security_form_input_predefined("any", "description", 0, "");
            $data["discount"] = @security_form_input_predefined("float", "discount", 0, "");
            break;
        case "time":
            /*
            	TIME ITEMS
            */
            // fetch information from form
            $data["price"] = @security_form_input_predefined("money", "price", 0, "");
            $data["customid"] = @security_form_input_predefined("int", "productid", 1, "");
            $data["timegroupid"] = @security_form_input_predefined("int", "timegroupid", 1, "");
            $data["description"] = @security_form_input_predefined("any", "description", 0, "");
            $data["discount"] = @security_form_input_predefined("float", "discount", 0, "");
            $data["units"] = "hours";
            break;
        case "service":
        case "service_usage":
            /*
            	SERVICE ITEMS
            */
            // fetch information from form
            $data["price"] = @security_form_input_predefined("money", "price", 0, "");
            $data["quantity"] = @security_form_input_predefined("float", "quantity", 1, "");
            $data["description"] = @security_form_input_predefined("any", "description", 1, "");
            $data["discount"] = @security_form_input_predefined("float", "discount", 0, "");
            $data["units"] = "";
            // keep existing custom id
            $data["customid"] = sql_get_singlevalue("SELECT customid as value FROM account_items WHERE id='" . $item->id_item . "' LIMIT 1");
            break;
        case "payment":
            /*
            	PAYMENT ITEM
            */
            // fetch information from form
            $data["date_trans"] = @security_form_input_predefined("date", "date_trans", 1, "");
            $data["amount"] = @security_form_input_predefined("money", "amount", 1, "");
            $data["source"] = @security_form_input_predefined("any", "source", 0, "");
            $data["description"] = @security_form_input_predefined("any", "description", 0, "");
            if ($_POST["chartid"] == "credit") {
                $data["chartid"] = "credit";
            } else {
                $data["chartid"] = @security_form_input_predefined("int", "chartid", 1, "");
            }
            break;
        case "credit":
            /*
            	CREDIT ITEMS
            */
            // fetch information from form
            $data["amount"] = @security_form_input_predefined("money", "amount", 0, "");
            $data["chartid"] = @security_form_input_predefined("int", "chartid", 1, "");
            $data["description"] = @security_form_input_predefined("any", "description", 0, "");
            // fetch information from all tax checkboxes from form
            $sql_tax_obj = new sql_query();
            $sql_tax_obj->string = "SELECT id FROM account_taxes";
            $sql_tax_obj->execute();
            if ($sql_tax_obj->num_rows()) {
                $sql_tax_obj->fetch_array();
                foreach ($sql_tax_obj->data as $data_tax) {
                    $data["tax_" . $data_tax["id"]] = @security_form_input_predefined("any", "tax_" . $data_tax["id"], 0, "");
                }
            }
            // end of loop through taxes
            break;
        default:
            log_write("error", "inc_invoice", "Unknown item type passed to processing form.");
            break;
    }
    /*
    	Process data
    */
    if (!$item->prepare_data($data)) {
        log_write("error", "process", "An error was encountered whilst processing supplied data.");
    }
    /// if there was an error, go back to the entry page
    if ($_SESSION["error"]["message"]) {
        $_SESSION["error"]["form"][$item->type_invoice . "_invoice_" . $mode] = "failed";
        header("Location: ../../index.php?page={$returnpage_error}&id=" . $item->id_invoice . "&itemid=" . $item->id_item . "&type=" . $item->type_item . "");
        exit(0);
    } else {
        /*
        	Start SQL Transaction
        */
        $sql_obj = new sql_query();
        $sql_obj->trans_begin();
        /*
        	APPLY ITEM CHANGES
        */
        if ($mode == "add") {
            $item->action_create();
            $item->action_update();
        } else {
            $item->action_update();
        }
        /*
        	Re-calculate Taxes
        
        	Note: Wo not re-calculate taxes for payment items, as this will change
        	any overridden values made on AP invocies and is unnessacary.
        */
        if ($item->type_item != "payment") {
            $item->action_update_tax();
        }
        /*
        	Update invoice summary totals
        */
        $item->action_update_total();
        /*
        	Generate ledger entries.
        
        	(Note that for quotes, we do NOT generate ledger entries, since a quote
        	should have no impact on the accounts)
        */
        if ($item->type_invoice != "quotes") {
            $item->action_update_ledger();
        }
        /*
        	Commit
        */
        if (error_check()) {
            $sql_obj->trans_rollback();
            log_write("error", "inc_invoice_items", "An error occured whilst updating the invoice item. No changes have been made.");
        } else {
            $sql_obj->trans_commit();
        }
        // display updated details
        header("Location: ../../index.php?page={$returnpage_success}&id=" . $item->id_invoice . "");
        exit(0);
    }
    // end if passed tests
}
function page_execute($argv)
{
    /*
    	Input Options
    */
    $option_date = NULL;
    $option_type = NULL;
    if (empty($argv[2])) {
        die("You must provide a date option in form of YYYY-MM-DD\n");
    }
    if (preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $argv[2])) {
        $option_date = $argv[2];
    } else {
        die("You must provide a date option in form of YYYY-MM-DD - wrong format supplied\n");
    }
    if (empty($argv[3])) {
        die("Service Type must be set.\n");
    }
    if (preg_match('/^\\S\\S*$/', $argv[3])) {
        $option_type = $argv[3];
        $option_type_id = sql_get_singlevalue("SELECT id as value FROM service_types WHERE name='{$option_type}' LIMIT 1");
        if (!$option_type_id) {
            die("Service type {$option_type} is unknown\n");
        }
    } else {
        die("You must provide a service type\n");
    }
    log_write("notification", "repair", "Executing usage charge rollback for invoices generated {$option_date} for service type {$option_type} (ID {$option_type_id})");
    /*
    	Fetch IDs of all sercices with selected option type
    */
    $option_services = array();
    $obj_sql_service = new sql_query();
    $obj_sql_service->string = "SELECT id FROM services WHERE typeid='" . $option_type_id . "'";
    $obj_sql_service->execute();
    if ($obj_sql_service->num_rows()) {
        $obj_sql_service->fetch_array();
        foreach ($obj_sql_service->data as $data) {
            $option_services[] = $data["id"];
        }
    }
    unset($obj_sql_service);
    log_write("notification", "repair", "Returned ID of matching services, array of " . format_arraytocommastring($option_services, NULL) . "");
    /*
    	Start Transaction
    */
    $obj_sql_trans = new sql_query();
    $obj_sql_trans->trans_begin();
    /*
    	Fetch AR Invoices for selected period
    */
    $obj_sql_ar = new sql_query();
    $obj_sql_ar->string = "SELECT id, customerid, code_invoice, dest_account, amount_total, amount_paid FROM account_ar WHERE date_trans='{$option_date}'";
    $obj_sql_ar->execute();
    if ($obj_sql_ar->num_rows()) {
        $obj_sql_ar->fetch_array();
        foreach ($obj_sql_ar->data as $data_ar) {
            $invoice_items = array();
            // store item details
            /*
            	Fetch Invoice Items
            */
            $obj_sql_items = new sql_query();
            $obj_sql_items->string = "SELECT id, customid, chartid, amount, description FROM account_items WHERE invoiceid='" . $data_ar["id"] . "' AND invoicetype='ar' AND type='service_usage'";
            $obj_sql_items->execute();
            if ($obj_sql_items->num_rows()) {
                $obj_sql_items->fetch_array();
                /*
                	For each item, check the service type and whether it is one of the items
                	that we want to credit.
                */
                foreach ($obj_sql_items->data as $data_item) {
                    if (in_array($data_item["customid"], $option_services)) {
                        // item is one of the target services, add details to array
                        log_write("debug", "repair", "Invoice ID #" . $data_ar["id"] . ", (" . $data_ar["code_invoice"] . ") item ID #" . $data_item["id"] . " is a valid service usage item to refund.");
                        // check if it's call charges
                        if (!strpos($data_item["description"], "call charges")) {
                            log_write("debug", "repair", "Skipping non-call charge usage item from credit");
                            continue;
                        }
                        // add invoice items
                        $invoice_items_tmp = array();
                        $invoice_items_tmp["id"] = $data_item["id"];
                        $invoice_items_tmp["customid"] = $data_item["customid"];
                        $invoice_items_tmp["chartid"] = $data_item["chartid"];
                        $invoice_items_tmp["amount"] = $data_item["amount"];
                        $invoice_items_tmp["description"] = $data_item["description"];
                        // add to array
                        $invoice_items[] = $invoice_items_tmp;
                    }
                }
            }
            // end of AR invoice items loop
            /*
            	If any items matched, we should create a credit note and add the items as credits
            */
            if (!empty($invoice_items)) {
                /*
                	Create Credit Note
                
                	We have all the information needed for the credit note from the invoice.
                */
                $credit = new credit();
                $credit->type = "ar_credit";
                $credit->prepare_set_defaults();
                $credit->data["invoiceid"] = $data_ar["id"];
                $credit->data["customerid"] = $data_ar["customerid"];
                $credit->data["employeeid"] = "0";
                $credit->data["date_trans"] = date("Y-m-d");
                $credit->data["dest_account"] = $data_ar["dest_account"];
                $credit->data["notes"] = "Automatically generated credit by repair process to cover service usage refund of invoice " . $data_ar["code_invoice"] . "";
                // create a new credit
                if ($credit->action_create()) {
                    log_write("notification", "repair", "Credit note successfully created");
                    journal_quickadd_event("account_ar_credit", $credit->id, "Credit Note successfully created");
                } else {
                    log_write("error", "repair", "An unexpected fault occured whilst attempting to create the credit note");
                }
                /*
                	Add Items
                
                	We loop through each selected item and for each item, we create an appropiate credit note item.
                */
                foreach ($invoice_items as $data_item) {
                    // create credit item
                    $item = new invoice_items();
                    $item->id_invoice = $credit->id;
                    $item->type_invoice = "ar_credit";
                    $item->type_item = "credit";
                    // set item details
                    $data = array();
                    $data["amount"] = $data_item["amount"];
                    $data["price"] = $data_item["amount"];
                    $data["chartid"] = $data_item["chartid"];
                    $data["description"] = "Credit For: " . $data_item["description"];
                    // fetch taxes for selected item
                    $sql_tax_obj = new sql_query();
                    $sql_tax_obj->string = "SELECT taxid FROM services_taxes WHERE serviceid='" . $data_item["customid"] . "'";
                    $sql_tax_obj->execute();
                    if ($sql_tax_obj->num_rows()) {
                        $sql_tax_obj->fetch_array();
                        foreach ($sql_tax_obj->data as $data_tax) {
                            $sql_cust_tax_obj = new sql_query();
                            $sql_cust_tax_obj->string = "SELECT id FROM customers_taxes WHERE customerid='" . $credit->data["customerid"] . "' AND taxid='" . $data_tax["taxid"] . "'";
                            $sql_cust_tax_obj->execute();
                            if ($sql_cust_tax_obj->num_rows()) {
                                $data["tax_" . $data_tax["taxid"]] = "on";
                            }
                        }
                    }
                    unset($sql_tax_obj);
                    if (!$item->prepare_data($data)) {
                        log_write("error", "process", "An error was encountered whilst processing supplied data.");
                    } else {
                        $item->action_create();
                        $item->action_update();
                    }
                    unset($data);
                }
                // end of items loop
                /*
                	Re-calculate Credit Note Totals
                */
                $item->action_update_tax();
                $item->action_update_total();
                $item->action_update_ledger();
                // finsihed with credit items
                unset($item);
                /*
                	Apply Credit Note against the invoice if it hasn't been paid in full.
                */
                $amount_invoice = array();
                if ($data_ar["amount_total"] != $data_ar["amount_paid"]) {
                    // determine amount owing
                    $amount_invoice["owing"] = $data_ar["amount_total"] - $data_ar["amount_paid"];
                    if ($amount_invoice["owing"] <= 0) {
                        // nothing todo
                        log_write("notification", "repair", "Ignoring overpaid invoice " . $data_ar["code_invoice"] . " and assigning credit note to customer account/pool instead");
                    } else {
                        // determine credit amount
                        $amount_invoice["credit"] = sql_get_singlevalue("SELECT amount_total as value FROM account_ar_credit WHERE id='" . $credit->id . "' LIMIT 1");
                        if ($amount_invoice["credit"] > $amount_invoice["owing"]) {
                            // pay the amount owing which is less than the credit
                            $amount_invoice["creditpay"] = $amount_invoice["owing"];
                        } else {
                            // customer owes more than the credit is for, make credit payment amount maximum
                            $amount_invoice["creditpay"] = $amount_invoice["credit"];
                        }
                        // make credit payment against the invoice
                        $item = new invoice_items();
                        $item->id_invoice = $data_ar["id"];
                        $item->type_invoice = "ar";
                        $item->type_item = "payment";
                        // set item details
                        $data = array();
                        $data["date_trans"] = date("Y-m-d");
                        $data["amount"] = $amount_invoice["creditpay"];
                        $data["chartid"] = "credit";
                        $data["source"] = "CREDITED FUNDS (AUTOMATIC)";
                        $data["description"] = "Credit from credit note " . $credit->data["code_credit"] . " for service usage charge correction";
                        if (!$item->prepare_data($data)) {
                            log_write("error", "process", "An error was encountered whilst processing supplied data for credit payment to invoice");
                        } else {
                            // create & update payment item
                            $item->action_create();
                            $item->action_update();
                            // update invoice totals & ledger
                            $item->action_update_tax();
                            $item->action_update_total();
                            $item->action_update_ledger();
                            log_write("notification", "repair", "Applied credit of " . $amount_invoice["creditpay"] . "");
                        }
                        unset($item);
                    }
                    // end if credit payment made
                } else {
                    log_write("notification", "repair", "Credited invoice " . $data_ar["code_invoice"] . " has already been paid in full, assigning credit note to customer's credit pool for future use.");
                }
                /*
                	Email PDF credit notes and message.
                */
                if ($GLOBALS["config"]["ACCOUNTS_INVOICE_AUTOEMAIL"] == 1 || $GLOBALS["config"]["ACCOUNTS_INVOICE_AUTOEMAIL"] == "enabled") {
                    $email = $credit->generate_email();
                    $credit->email_credit($email["sender"], $email["to"], $email["cc"], $email["bcc"], $email["subject"], $email["message"]);
                } else {
                    log_write("notification", "repair", "No credit note email sent, ACCOUNTS_INVOICE_AUTOEMAIL is disabled.");
                }
                // unset the credit note
                unset($credit);
                /*
                	Flag the refunded usage periods for re-billing.
                
                	Now that we have refunded the usage on the selected invoice, we should then flag any service periods
                	of the same service type and invoice ID, to cause the usge to be rebilled in the next service billing month.
                */
                // fetch id_service_customer values from services where customer matches invoice
                $obj_sql_cust = new sql_query();
                $obj_sql_cust->string = "SELECT id FROM services_customers WHERE customerid='" . $data_ar["customerid"] . "' AND serviceid IN (" . format_arraytocommastring($option_services, NULL) . ")";
                $obj_sql_cust->execute();
                if ($obj_sql_cust->num_rows()) {
                    $obj_sql_cust->fetch_array();
                    foreach ($obj_sql_cust->data as $data_cust) {
                        // update any periods for this customer-service which have the ID of the selected invoice as
                        // the usage period invoice.
                        //
                        // these usage periods will then be re-invoiced at the next service invoicing run.
                        //
                        $obj_sql_period = new sql_query();
                        $obj_sql_period->string = "UPDATE services_customers_periods SET invoiceid_usage='0', rebill='1' WHERE invoiceid_usage='" . $data_ar["id"] . "' AND id_service_customer='" . $data_cust["id"] . "'";
                        $obj_sql_period->execute();
                    }
                    log_write("notification", "repair", "Flagged services for customer " . $data_ar["customerid"] . " to bill for usage periods.");
                } else {
                    log_write("warning", "repair", "No usage periods found to flag for rebilling for customer " . $data_ar["customerid"] . ", possibly the service has been deleted?");
                }
                unset($obj_sql_cust);
            }
            // if creditable items exist on the selected invoice
            if (error_check()) {
                // there was an error, do not continue processing invoices.
                continue;
            }
        }
    }
    // end of AR invoice loop
    /*
    	Close Transaction
    */
    if (error_check()) {
        // rollback/failure
        log_write("error", "repair", "An error occured whilst executing, rolling back DB changes");
        $obj_sql_trans->trans_rollback();
    } else {
        // commit
        log_write("notification", "repair", "Successful execution, applying DB changes");
        $obj_sql_trans->trans_commit();
    }
}
 function invoice_generate($invoiceid = NULL)
 {
     log_write("debug", "inc_customers", "Executing invoice_generate()");
     // we don't need to worry about checking if this is the appropiate date, that logic is handled by
     // other functions before calling this one.
     // initatiate SQL
     $sql_obj = new sql_query();
     $sql_obj->trans_begin();
     // do we need to create an invoice?
     if (!$invoiceid) {
         $obj_invoice = new invoice();
         $obj_invoice->type = "ar";
         $obj_invoice->data["customerid"] = $this->id;
         $obj_invoice->data["employeeid"] = 1;
         $obj_invoice->data["notes"] = "Invoice generated from customer orders page.";
         $obj_invoice->prepare_date_shift();
         $obj_invoice->action_create();
         $invoiceid = $obj_invoice->id;
         log_write("debug", "inc_customers", "Creating a new invoice with ID of {$invoiceid}");
     } else {
         // reuse existing
         log_write("debug", "inc_customers", "Using specified invoice {$invoiceid} for orders invoicing");
     }
     // run through the items and add to the invoice
     $obj_orders_sql = new sql_query();
     $obj_orders_sql->string = "SELECT * FROM customers_orders WHERE id_customer='" . $this->id . "'";
     $obj_orders_sql->execute();
     if ($obj_orders_sql->num_rows()) {
         $obj_orders_sql->fetch_array();
         foreach ($obj_orders_sql->data as $data_order) {
             log_write("debug", "inc_customers", "Adding order item " . $data_order["id"] . " to invoice " . $invoiceid . " for customer " . $this->id . "");
             // select values desired, certain safety checks
             $data_order_tmp = array();
             $data_order_tmp["customid"] = $data_order["customid"];
             $data_order_tmp["quantity"] = $data_order["quantity"];
             $data_order_tmp["units"] = addslashes($data_order["units"]);
             $data_order_tmp["amount"] = $data_order["amount"];
             $data_order_tmp["price"] = $data_order["price"];
             $data_order_tmp["discount"] = $data_order["discount"];
             $data_order_tmp["description"] = addslashes($data_order["description"]);
             // Add each order as an item on the invoice.
             $obj_item = new invoice_items();
             $obj_item->id_invoice = $invoiceid;
             $obj_item->type_invoice = "ar";
             $obj_item->type_item = $data_order["type"];
             $obj_item->prepare_data($data_order_tmp);
             $obj_item->action_create();
             $obj_item->action_update();
             // delete the item now that it's been added
             $obj_delete_sql = new sql_query();
             $obj_delete_sql->string = "DELETE FROM customers_orders WHERE id='" . $data_order["id"] . "' LIMIT 1";
             $obj_delete_sql->execute();
             unset($obj_delete_sql);
         }
         // update invoice summary information
         $obj_item->action_update_tax();
         $obj_item->action_update_total();
         $obj_item->action_update_ledger();
         unset($obj_item);
     }
     // end if order items.
     // make automated payments - such as customer credit pool or auto-pay credit card functionality
     if ($GLOBALS["config"]["ACCOUNTS_AUTOPAY"]) {
         log_write("debug", "inc_services_invoicegen", "Autopay Functionality Enabled, running appropiate functions for invoice ID {$invoiceid}");
         $obj_autopay = new invoice_autopay();
         $obj_autopay->id_invoice = $invoiceid;
         $obj_autopay->type_invoice = "ar";
         $obj_autopay->autopay();
         unset($obj_autopay);
     }
     // save changes
     if (error_check()) {
         $sql_obj->trans_rollback();
         log_write("error", "inc_customers", "An error occurred whilst attempting to generate an invoice.");
         return 0;
     } else {
         $sql_obj->trans_commit();
         log_write("notification", "inc_customers", "Successfully generate invoice " . $obj_invoice->data["code_invoice"] . " for customer " . $this->data["name_customer"] . "");
         return $invoiceid;
     }
 }