4376 lines
150 KiB
PHP
4376 lines
150 KiB
PHP
<?php
|
|
|
|
/**
|
|
* AgileBill - Open Billing Software
|
|
*
|
|
* This body of work is free software; you can redistribute it and/or
|
|
* modify it under the terms of the Open AgileBill License
|
|
* License as published at http://www.agileco.com/agilebill/license1-4.txt
|
|
*
|
|
* For questions, help, comments, discussion, etc., please join the
|
|
* Agileco community forums at http://forum.agileco.com/
|
|
*
|
|
* @link http://www.agileco.com/
|
|
* @copyright 2004-2008 Agileco, LLC.
|
|
* @license http://www.agileco.com/agilebill/license1-4.txt
|
|
* @author Tony Landis <tony@agileco.com>
|
|
* @package AgileBill
|
|
* @version 1.4.93
|
|
*/
|
|
|
|
|
|
/**
|
|
* The main AgileBill Invoice Class
|
|
*/
|
|
class invoice
|
|
{
|
|
/** Enable summary invoice view that rolls multiple instances of the same sku w/identical base&setup price & attributes into one line item */
|
|
var $summarizeInvoice=true;
|
|
|
|
/**
|
|
* Holds sku's of line items to exclude from invoice summarys (pdf view only)
|
|
*
|
|
* @var array
|
|
*/
|
|
var $summarizeInvoiceExclude;
|
|
|
|
/** Invoice type, 0=new, 1=recurr */
|
|
var $type=0;
|
|
|
|
/** Invoice Creation Timestamp */
|
|
var $date_orig;
|
|
|
|
/** Last modification Timestamp */
|
|
var $date_last;
|
|
|
|
/** Invoice Id */
|
|
var $record_id;
|
|
|
|
/** Invoice Item Id */
|
|
var $item_id=1;
|
|
|
|
/** Parent Invoice Id for recurring */
|
|
var $parent_id;
|
|
|
|
/** Account Id for invoice */
|
|
var $account_id;
|
|
|
|
/** Affiliate Id of Invoice */
|
|
var $affiliate_id;
|
|
|
|
/** Account Billing Id */
|
|
var $account_billing_id;
|
|
|
|
/** Campaign Id */
|
|
var $campaign_id;
|
|
|
|
/** Reseller Id */
|
|
var $reseller_id;
|
|
|
|
/** Billed Currency Id */
|
|
var $billed_currency_id;
|
|
|
|
/** Actual Billed Currency selected by Client */
|
|
var $actual_billed_currency_id;
|
|
|
|
/** Checkout Plugin Id */
|
|
var $checkout_plugin_id;
|
|
|
|
/** Array of checkout plugin data returned by checkout plugin */
|
|
var $checkout_plugin_data;
|
|
|
|
/** Current Notice Count */
|
|
var $notice_count=0;
|
|
|
|
/** Last Notice Timestamp */
|
|
var $notice_date;
|
|
|
|
/** Due Date Timestamp */
|
|
var $due_date;
|
|
|
|
/** Net Term Id */
|
|
var $net_term_id=false;
|
|
|
|
/** Net Term Last Notice/Late fee Timestamp */
|
|
var $net_term_date_last;
|
|
|
|
/** Net Term Interval Count */
|
|
var $net_term_intervals=0;
|
|
|
|
/** Process Status */
|
|
var $process_status=0;
|
|
|
|
/** Billing Status */
|
|
var $billing_status=0;
|
|
|
|
/** Suspend Billing Status */
|
|
var $suspend_billing=0;
|
|
|
|
/** Printed Invoice Status */
|
|
var $print_status=0;
|
|
|
|
/** Refunded Invoice Status */
|
|
var $refund_status=0;
|
|
|
|
/** Calcuate Taxes */
|
|
var $tax=true;
|
|
|
|
/** Calculate Discounts */
|
|
var $discount=true;
|
|
|
|
/** Total Invoice Amount */
|
|
var $total_amt=0;
|
|
|
|
/** Total Amount Billed */
|
|
var $billed_amt=0;
|
|
|
|
/** Actual total amount billed (converted to local) */
|
|
var $actual_billed_amt=0;
|
|
|
|
/** Total Tax Amount */
|
|
var $tax_amt=0;
|
|
|
|
/** Total Discount Amount */
|
|
var $discount_amt=0;
|
|
|
|
/** Recurring Amount */
|
|
var $recur_amt;
|
|
|
|
/** Recurring Array for Later Processing */
|
|
var $recur_arr;
|
|
|
|
/** IP Address of User */
|
|
var $ip=USER_IP;
|
|
|
|
/** Array of the Invoice items */
|
|
var $invoice_item;
|
|
|
|
/** Array of the discounts for the Invoice items */
|
|
var $item_discount;
|
|
|
|
/** Array of the taxes for the Invoice Items */
|
|
var $item_tax;
|
|
|
|
/** Tracking to determine payment options */
|
|
var $any_new=false;
|
|
var $any_trial=false;
|
|
var $any_recurring=false;
|
|
|
|
/** Invoice Config Global Options */
|
|
var $invoice_delivery=1;
|
|
var $invoice_format=0;
|
|
var $notice_max=MAX_BILLING_NOTICE;
|
|
var $grace_period=GRACE_PERIOD;
|
|
|
|
|
|
|
|
/**
|
|
* Get the global level invoice settings
|
|
*/
|
|
function setupGlobal() {
|
|
$db=&DB();
|
|
$invopt=$db->Execute(sqlSelect($db,"setup_invoice","*",""));
|
|
if($invopt && $invopt->RecordCount()) {
|
|
$this->invoice_delivery=$invopt->fields['invoice_delivery'];
|
|
$this->invoice_format=$invopt->fields['invoice_show_itemized'];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the account level invoice options
|
|
*
|
|
* @param int $id Account Id
|
|
*/
|
|
function setupAccount() {
|
|
if(!$this->account_id) return;
|
|
$db=&DB();
|
|
$acctrs=$db->Execute(sqlSelect($db,"account","invoice_grace,invoice_advance_gen","id=$this->account_id"));
|
|
if($acctrs && $acctrs->RecordCount()) {
|
|
$this->advance_gen=$acctrs->fields['invoice_advance_gen'];
|
|
if($this->grace_period == GRACE_PERIOD && !empty($acctrs->fields['invoice_grace'])) $this->grace_period=$acctrs->fields['invoice_grace'];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize new invoice creation
|
|
*
|
|
* @param bool $type 0=new 1=recur
|
|
*/
|
|
function initNew($type=0) {
|
|
$this->type=$type;
|
|
$this->date_orig=time();
|
|
$this->date_last=time();
|
|
|
|
global $C_list;
|
|
$this->net_term = $C_list->is_installed('net_term');
|
|
|
|
// get account invoice defaults
|
|
$this->setupAccount();
|
|
}
|
|
|
|
/**
|
|
* Commit the current invoice/items/discounts/taxes
|
|
*
|
|
* @param object $taxObj Object for Tax Calculation
|
|
* @param object $discountObj Object for Discount Calculation
|
|
* @param bool $email Send customer/admin e-mails
|
|
*/
|
|
function commitNew(&$taxObj, &$discountObj, $email=true) {
|
|
|
|
// init DB transaction
|
|
$db=&DB();
|
|
$db->BeginTrans();
|
|
|
|
// get invoice id
|
|
if(empty($this->record_id)) $this->record_id = sqlGenID($db,"invoice");
|
|
|
|
// serialized records:
|
|
if(is_array($this->checkout_plugin_data)) $this->checkout_plugin_data=serialize($this->checkout_plugin_data);
|
|
if(is_array($this->recur_arr)) $this->recur_arr=serialize($this->recur_arr);
|
|
|
|
// dates & defaults
|
|
if(empty($this->due_date)) $this->due_date=time();
|
|
if(empty($this->date_orig)) $this->date_orig=time();
|
|
if(empty($this->date_last)) $this->date_last=time();
|
|
if(empty($this->notice_next_date)) $this->notice_next_date=$this->due_date+86400;
|
|
|
|
// net terms
|
|
if ($this->net_term && !$this->billing_status && $this->total_amt>0) {
|
|
include_once(PATH_MODULES.'net_term/net_term.inc.php');
|
|
$net=new net_term;
|
|
$this->net_term_id = $net->termsAllowed($this->account_id, $this->checkout_plugin_id);
|
|
if(empty($this->net_term_date_last)) $this->net_term_date_last=time();
|
|
}
|
|
|
|
// insert invoice
|
|
$fields=Array(
|
|
'date_orig'=>$this->date_orig,
|
|
'date_last'=>$this->date_last,
|
|
'parent_id'=>$this->parent_id,
|
|
'type'=>$this->type,
|
|
'process_status'=>$this->process_status,
|
|
'billing_status'=>$this->billing_status,
|
|
'suspend_billing'=>$this->suspend_billing,
|
|
'refund_status'=>$this->refund_status,
|
|
'print_status'=>$this->print_status,
|
|
'account_id'=>$this->account_id,
|
|
'account_billing_id'=>$this->account_billing_id,
|
|
'affiliate_id'=>$this->affiliate_id,
|
|
'campaign_id'=>$this->campaign_id,
|
|
'reseller_id'=>$this->reseller_id,
|
|
'checkout_plugin_id'=>$this->checkout_plugin_id,
|
|
'checkout_plugin_data'=>$this->checkout_plugin_data,
|
|
'tax_amt'=>$this->tax_amt,
|
|
'discount_amt'=>$this->discount_amt,
|
|
'total_amt'=>$this->total_amt,
|
|
'billed_amt'=>$this->billed_amt,
|
|
'recur_amt'=>$this->recur_amt,
|
|
'recur_arr'=>$this->recur_arr,
|
|
'actual_billed_amt'=>$this->actual_billed_amt,
|
|
'billed_currency_id'=>$this->billed_currency_id,
|
|
'actual_billed_currency_id'=>$this->actual_billed_currency_id,
|
|
'notice_count'=>$this->notice_count,
|
|
'notice_max'=>$this->notice_max,
|
|
'notice_next_date'=>$this->notice_next_date,
|
|
'due_date'=>$this->due_date,
|
|
'grace_period'=>$this->grace_period,
|
|
'net_term_id'=>$this->net_term_id,
|
|
'net_term_date_last'=>$this->net_term_date_last,
|
|
'net_term_intervals'=>$this->net_term_intervals,
|
|
'ip'=>$this->ip
|
|
);
|
|
$db->Execute($sql=sqlInsert($db, "invoice", $fields, $this->record_id));
|
|
|
|
// loop through invoice items
|
|
if(is_array($this->invoice_item)) {
|
|
foreach($this->invoice_item as $id=>$fields) {
|
|
// get an invoice_item id
|
|
$invoice_item_id = sqlGenID($db, "invoice_item");
|
|
|
|
// domain sku's
|
|
if ($fields['item_type'] == 2) {
|
|
$fields['sku'] = "DOMAIN-".strtoupper($fields['domain_type']);
|
|
$fields['price_type'] = '0';
|
|
}
|
|
|
|
// build e-mail item details
|
|
if($email) {
|
|
$email_instructions='';
|
|
if($fields['item_type']<2 && !empty($fields['product_id'])) {
|
|
// product, get email instructions and translated name
|
|
$translate_prod=$db->Execute(sqlSelect($db,"product_translate","email_template,name","product_id={$fields['product_id']} and language_id=::".SESS_LANGUAGE."::"));
|
|
if($translate_prod && $translate_prod->RecordCount()) {
|
|
$instructions=$translate_prod->fields['email_template'];
|
|
$name=$translate_prod->fields['name'];
|
|
} else {
|
|
$name=$fields["sku"];
|
|
}
|
|
} elseif ($fields['item_type'] == 2) {
|
|
$name=strtoupper($fields['domain_name'].".".$fields['domain_tld']);
|
|
} else {
|
|
if(!empty($fields['product_name'])) $name=$fields['product_name']; else $name=$fields['sku'];
|
|
}
|
|
// add to e-mail array
|
|
$email_arr[] = array('Qty' => '('.$fields["quantity"].')', 'Item' => 'SKU '.$fields["sku"], 'Price' => number_format($fields["total_amt"],2), 'Name' => $name, 'Instructions' => $instructions);
|
|
}
|
|
|
|
// insert the invoice item_id
|
|
$fields['invoice_id']=$this->record_id;
|
|
$fields['date_orig']=time();
|
|
$attr = serialize($fields['product_attr']);
|
|
$fields['product_attr']=$fields['product_attr_cart'];
|
|
$fields['product_attr_cart']=$attr;
|
|
$db->Execute($sql=sqlInsert($db, "invoice_item", $fields, $invoice_item_id));
|
|
|
|
// insert taxes
|
|
if($this->tax && $this->tax_amt > 0 && !empty($this->tax_arr[$id])) {
|
|
$taxObj->invoice_item($this->record_id, $invoice_item_id, $this->account_id, $this->tax_arr[$id]);
|
|
}
|
|
|
|
// insert discounts
|
|
if($this->discount && $this->discount_amt>0 && !empty($this->discount_arr[$id])) {
|
|
$discountObj->invoice_item($this->record_id, $invoice_item_id, $this->account_id, $this->discount_arr[$id]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// complete DB transaction
|
|
$db->CompleteTrans();
|
|
|
|
// complete building e-mail notices and send
|
|
if($email) {
|
|
include_once(PATH_MODULES.'email_template/email_template.inc.php');
|
|
|
|
// Create the products order list for the e-mail:
|
|
$e_itm_usr = '';
|
|
$e_itm_adm = '';
|
|
if(is_array($email_arr)) {
|
|
foreach($email_arr as $i=>$em) {
|
|
$e_itm_usr .= $em['Qty'].' '.$em['Item'].' ('.$em['Name'].') '.$em['Price'];
|
|
$e_itm_adm .= $em['Qty'].' '.$em['Item'].' ('.$em['Name'].') '.$em['Price']."\r\n";
|
|
if(!empty($email_arr[$i]['Instructions'])) $e_itm_usr .= "\r\n * " . $email_item_arr[$i]['Instructions'];
|
|
$e_itm_usr .= "\r\n";
|
|
}
|
|
$e_arr_user = Array('%products%' => $e_itm_usr);
|
|
$e_arr_adm = Array('%products%' => $e_itm_adm);
|
|
}
|
|
|
|
// e-mail invoice creation confirmation
|
|
$mail = new email_template;
|
|
$mail->send('invoice_confirm_user', $this->account_id, $this->record_id, $this->checkout_plugin_id, $e_arr_user);
|
|
$email = new email_template;
|
|
$email->send('admin->invoice_confirm_admin', $this->account_id, $this->record_id, $this->checkout_plugin_id, $e_arr_adm);
|
|
}
|
|
|
|
// net terms?
|
|
if($this->net_term_id) {
|
|
$this->approveInvoice(array('id'=>$this->record_id), $this);
|
|
return $this->record_id;
|
|
}
|
|
|
|
// Determine the approval status by checkout plugin type & settings:
|
|
if($email && $this->billing_status == 0 && $this->billed_amt > 0 ) {
|
|
global $C_list;
|
|
if($this->checkout_type == 'redirect') {
|
|
// User e-mail alert of due invoice
|
|
$email = new email_template;
|
|
$email->send('invoice_due_user', $this->account_id, $this->record_id, $user_currency, $C_list->date($this->due_date));
|
|
} elseif ($this->checkout_type == 'other') {
|
|
// Admin e-mail alert of manual payment processing
|
|
$email = new email_template;
|
|
$email->send('admin->invoice_due_admin', $this->account_id, $this->record_id, $admin_currency, $C_list->date($this->due_date));
|
|
}
|
|
} elseif($this->billed_amt>0 ) {
|
|
if($email) {
|
|
// User alert of payment processed
|
|
$email = new email_template;
|
|
$email->send('invoice_paid_user', $this->account_id, $this->record_id, $this->billed_currency_id, '');
|
|
// Admin alert of payment processed
|
|
$email = new email_template;
|
|
$email->send('admin->invoice_paid_admin', $this->account_id, $this->record_id, $this->billed_currency_id, '');
|
|
}
|
|
$this->autoApproveInvoice($this->record_id);
|
|
} elseif($this->billed_amt == 0 && $this->billing_status == 1 ) {
|
|
$this->autoApproveInvoice($this->record_id);
|
|
}
|
|
|
|
// return invoice id
|
|
return $this->record_id;
|
|
}
|
|
|
|
/**
|
|
* Add an invoice item
|
|
*
|
|
* @param int $id Reference ID for use in Cart or false
|
|
* @param object $taxObj Object for Tax Calculation
|
|
* @param object $discountObj Object for Discount Calculation
|
|
* @param int $item_type 0/1=Product/Service/Hosting 2=Domain 3=Add Hoc
|
|
* @param string $taxable True, False, or 'validate' to locate the specified $product id and verify
|
|
* @param int $service_id If this is for a service upgrade, this will be defined
|
|
* @param int $parent_id Item Parent Id
|
|
* @param int $product_id Item Product Id
|
|
* @param array $product_attr Item attributes from the cart/prev service
|
|
* @param string $product_name Item product name
|
|
* @param string $sku Item Product SKU
|
|
* @param int $quantity Item Quantity
|
|
* @param float $price_base Item Base price
|
|
* @param float $price_setup Item Setup Price
|
|
* @param float $discount_manual Ad Hoc Discount Amount
|
|
* @param int $recurring_schedule Item recurring schedule, 0=week, 1=month, 2=quarter, 3=semi-annual, 4=annual, 5=bi-year
|
|
* @param int $date_start Date service started
|
|
* @param int $date_stop Date service stops
|
|
* @param string $domain_name Domain name
|
|
* @param string $domain_tld Domain TLD
|
|
* @param int $domain_term Domain Term
|
|
* @param string $domain_type Domain Type (register, transfer, renew, park, ns_transfer)
|
|
*/
|
|
function addItem($id, &$taxObj, &$discountObj, $item_type, $taxable=false, $service_id=false, $parent_id=false, $product_id=false, $product_attr=false, $product_name=false, $sku=false, $quantity=1, $price_base=false, $price_setup=false, $discount_manual=false, $recurring_schedule=false, $date_start=false, $date_stop=false, $domain_name=false, $domain_tld=false, $domain_term=false, $domain_type=false) {
|
|
$tax_amt=0;
|
|
$total_amt=0;
|
|
$discount_amt=0;
|
|
|
|
// define correct qty
|
|
if($quantity<=0) $quantity=1;
|
|
|
|
// determine the reference id for this item
|
|
if($id>0) {
|
|
$this->item_id=$id;
|
|
} else {
|
|
$this->item_id++;
|
|
}
|
|
|
|
// get the product details
|
|
if($product_id && $item_type<2) {
|
|
$db=&DB();
|
|
$product=$db->Execute(sqlSelect($db,"product","*","id=$product_id"));
|
|
if($product && $product->RecordCount()) {
|
|
$taxable = $product->fields['taxable'];
|
|
$this->product["$this->item_id"] = $product->fields;
|
|
}
|
|
|
|
// get the tld details
|
|
} elseif($item_type==2) {
|
|
$db=&DB();
|
|
$tld=$db->Execute(sqlSelect($db,"host_tld","*","name=::$domain_tld::"));
|
|
if($tld && $tld->RecordCount())
|
|
$taxable = $tld->fields['taxable'];
|
|
}
|
|
|
|
// get the product pricing details if product
|
|
$price_type=0;
|
|
if($price_base===false && $price_setup===false && $product_id && $item_type<2) {
|
|
if($product && $product->RecordCount()) {
|
|
$price_type=$product->fields['price_type'];
|
|
$sku=$product->fields['sku'];
|
|
include_once(PATH_MODULES.'product/product.inc.php');
|
|
$productObj=new product;
|
|
|
|
// get pricing for this product:
|
|
$prod_price = $productObj->price_prod($product->fields, $recurring_schedule, $this->account_id);
|
|
$price_base = $prod_price["base"];
|
|
$price_setup = $prod_price["setup"];
|
|
|
|
// calculate any product attributes fees
|
|
$attr_price = $productObj->price_attr($product->fields, $product_attr, $recurring_schedule, $this->account_id);
|
|
$price_base += $attr_price["base"];
|
|
$price_setup += $attr_price["setup"];
|
|
|
|
// determine price type for checkout
|
|
if ($product->fields["price_type"] == '0')
|
|
$this->any_new=true;
|
|
else if ($product->fields["price_type"] == '1')
|
|
$this->any_recurring=true;
|
|
else if ($product->fields["price_type"] == '2')
|
|
$this->any_trial=true;
|
|
|
|
} else {
|
|
$this->any_new=true;
|
|
}
|
|
} else {
|
|
$this->any_new=true;
|
|
}
|
|
|
|
// get the TLD pricing details if domain
|
|
if($price_base===false && $price_setup===false && $domain_tld && $domain_term && $domain_type) {
|
|
include_once(PATH_MODULES.'host_tld/host_tld.inc.php');
|
|
$tldObj = new host_tld;
|
|
$tldprice = $tldObj->price_tld_arr($domain_tld, $domain_type, false, false, false, $this->account_id);
|
|
if($domain_type == "park") {
|
|
$price_base = $tldprice;
|
|
} else {
|
|
$price_base = $tldprice["$domain_term"];
|
|
$this->tld_arr["$this->item_id"] = $tldprice;
|
|
}
|
|
}
|
|
|
|
// set total amount for this line item before attributes, taxes, or discounts
|
|
$price_base *= $quantity;
|
|
$price_setup *= $quantity;
|
|
$total_amt = ($price_setup + $price_base);
|
|
|
|
// format product attributes for storage
|
|
$product_attr_cart=false;
|
|
if(($item_type==0 || $item_type>2) && is_array($product_attr)) $product_attr_cart = $this->get_product_attr_cart($product_attr);
|
|
|
|
// recurring taxes and arrays
|
|
if($price_base>0 && $price_type==1)
|
|
{
|
|
// increment the total invoice recurring amount
|
|
$this->recur_amt += $price_base;
|
|
|
|
// determine taxes for the recurring amount
|
|
if($this->tax && $taxable && $price_base>0 && $this->account_id) {
|
|
$recur_tax_arr = $taxObj->calculate($price_base, $this->country_id, $this->state);
|
|
if(is_array($recur_tax_arr)) foreach($recur_tax_arr as $tx) $this->recur_amt += $tx['rate'];
|
|
}
|
|
|
|
// get the recurring arrays for price and invoice
|
|
if($product && $product->RecordCount()) {
|
|
$this->price_arr["$this->item_id"] = $productObj->price_recurr_arr($product->fields, $this->account_id);
|
|
$this->recur_arr[] = Array (
|
|
'price' => $price_base*$quantity,
|
|
'recurr_schedule'=> $recurring_schedule,
|
|
'recurr_type' => $product->fields['price_recurr_type'],
|
|
'recurr_weekday' => $product->fields['price_recurr_weekday'],
|
|
'recurr_week' => $product->fields['price_recurr_week']
|
|
);
|
|
}
|
|
}
|
|
|
|
// calculate any ad-hoc line item level (admin) discounts
|
|
if($this->discount && $discount_manual>0) {
|
|
$total_amt -= $discount_manual;
|
|
$discount_amt += $discount_manual;
|
|
$this->discount_amt += $discount_amt;
|
|
$discountObj->add_manual_discount($discount_manual,'MISC',$this->item_id);
|
|
}
|
|
|
|
// account level discounts
|
|
if($this->discount && $this->account_id) {
|
|
// calculate any database level discounts for this item (both account specific and session specific)
|
|
$discount_amt = $discountObj->calc_all_discounts(0, $this->item_id, $product_id, $total_amt, $this->account_id, $this->total_amt+$total_amt);
|
|
$total_amt -= $discount_amt;
|
|
$this->discount_amt += $discount_amt;
|
|
}
|
|
|
|
// add to total discount array
|
|
if(is_array($discountObj->discount_arr)) {
|
|
$this->discount_arr["$this->item_id"] = $discountObj->discount_arr;
|
|
}
|
|
|
|
// increment invoice total amount
|
|
$this->total_amt += $total_amt;
|
|
|
|
// calculate any taxes for current item
|
|
if($this->tax && $taxable && $total_amt>0 && $this->account_id) {
|
|
$tax_arr = $taxObj->calculate($total_amt, $this->country_id, $this->state);
|
|
if(is_array($tax_arr)) {
|
|
foreach($tax_arr as $tx) $tax_amt += $tx['rate'];
|
|
$this->item_tax["$this->item_id"] = $tax_arr;
|
|
$this->tax_arr["$this->item_id"] = $tax_arr;
|
|
}
|
|
$this->tax_amt += $tax_amt;
|
|
$this->total_amt += $tax_amt;
|
|
}
|
|
|
|
// store the fields to an array
|
|
$this->invoice_item["$this->item_id"]=Array(
|
|
'item_type'=>$item_type,
|
|
'price_type'=>$price_type,
|
|
'taxable'=>$taxable,
|
|
'service_id'=>$service_id,
|
|
'parent_id'=>$parent_id,
|
|
'product_id'=>$product_id,
|
|
'product_attr'=>$product_attr,
|
|
'product_attr_cart'=>$product_attr_cart,
|
|
'product_name'=>$product_name,
|
|
'sku'=>$sku,
|
|
'quantity'=>$quantity,
|
|
'price_base'=>$price_base,
|
|
'price_setup'=>$price_setup,
|
|
'recurring_schedule'=>$recurring_schedule,
|
|
'date_start'=>$date_start,
|
|
'date_stop'=>$date_stop,
|
|
'domain_name'=>$domain_name,
|
|
'domain_tld'=>$domain_tld,
|
|
'domain_term'=>$domain_term,
|
|
'domain_type'=>$domain_type,
|
|
'total_amt'=>$total_amt,
|
|
'tax_amt'=>$tax_amt,
|
|
'discount_amt'=>$discount_amt
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Group all taxes to lump sums
|
|
*/
|
|
function group_taxes() {
|
|
if(is_array($this->tax_arr)) {
|
|
foreach($this->tax_arr as $taxarr) foreach($taxarr as $taxes) $arr[$taxes["name"]]+=$taxes["rate"];
|
|
if(is_array($arr)) {
|
|
foreach($arr as $a=>$b) $ret[] = Array('name'=>$a, 'rate'=>$b);
|
|
return $ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Group all discounts to lump sums
|
|
*/
|
|
function group_discounts() {
|
|
if(is_array($this->discount_arr)) {
|
|
foreach($this->discount_arr as $discarr) foreach($discarr as $discounts) $arr[$discounts["discount"]]+=$discounts["amount"];
|
|
if(is_array($arr)) {
|
|
foreach($arr as $a=>$b) $ret[] = Array('name'=>$a, 'total'=>$b);
|
|
return $ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build a formatted product attribute list
|
|
*
|
|
* @param array $attributes
|
|
* @return string Formatted product attribute list
|
|
*/
|
|
function get_product_attr_cart($attributes) {
|
|
# Set the attribute array:
|
|
if(!empty($attributes) && is_array($attributes)) {
|
|
$db=&DB();
|
|
$product_attr = false;
|
|
foreach($attributes as $id=>$value) {
|
|
if (!empty($value)) {
|
|
if(is_numeric($id)) {
|
|
$attr = $db->Execute(sqlSelect($db,"product_attr","name","id=$id"));
|
|
if ($attr && $attr->RecordCount()) $product_attr .= "{$attr->fields['name']}==".ereg_replace("\r\n", "<br>", $value)."\r\n";
|
|
} else {
|
|
$product_attr .= "{$id}=={$value}\r\n";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $product_attr;
|
|
}
|
|
|
|
|
|
|
|
/** Custom Tracking
|
|
*/
|
|
function custom_tracking($VAR)
|
|
{
|
|
# Get the invoice id
|
|
if(SESS_LOGGED == false)
|
|
return false;
|
|
|
|
# Check if we are in the iframe
|
|
if(empty($VAR['_escape']) || empty($VAR['confirm']))
|
|
{
|
|
echo '<iframe id="custom_ecom_track" style="border:0px; width:0px; height:0px;"scrolling="auto" '.
|
|
'frameborder="0" SRC="?_page=core:blank&_escape=1&confirm=1&do[]=invoice:custom_tracking&rand='.md5(microtime()).'"></iframe>';
|
|
return;
|
|
}
|
|
|
|
# Get the un-tracked invoice details
|
|
$db = &DB();
|
|
$sql = "SELECT * FROM ".AGILE_DB_PREFIX."invoice WHERE
|
|
( custom_affiliate_status IS NULL OR
|
|
custom_affiliate_status = 0 )
|
|
AND billing_status = ".$db->qstr(1)."
|
|
AND site_id = ".$db->qstr(DEFAULT_SITE)."
|
|
AND account_id = ".$db->qstr(SESS_ACCOUNT);
|
|
$result = $db->Execute($sql);
|
|
if ($result === false) {
|
|
global $C_debug;
|
|
$C_debug->error('','', $db->ErrorMsg(). "\r\n\r\n". $sql);
|
|
return false;
|
|
}
|
|
if($result->RecordCount() == 0) {
|
|
echo 'none';
|
|
return false;
|
|
}
|
|
|
|
# Get the totals
|
|
$invoice = '';
|
|
$total_amount = false;
|
|
while(!$result->EOF)
|
|
{
|
|
if(!empty($invoice))
|
|
$invoice .= '-';
|
|
$invoice .= $result->fields['id'];
|
|
$amt = $result->fields["total_amt"];
|
|
$total_amount += $amt;
|
|
$result->MoveNext();
|
|
}
|
|
|
|
# echo the custom tracking code to the screen:
|
|
if(!is_file(PATH_FILES.'tracking.txt')) return false;
|
|
$tracking = file_get_contents(PATH_FILES.'tracking.txt');
|
|
$tracking = ereg_replace('%%amount%%', "$total_amount", $tracking);
|
|
$tracking = ereg_replace('%%invoice%%', $invoice, $tracking);
|
|
$tracking = ereg_replace('%%affiliate%%', SESS_AFFILIATE, $tracking);
|
|
$tracking = ereg_replace('%%campaign%%', SESS_CAMPAIGN, $tracking);
|
|
$tracking = ereg_replace('%%account%%', SESS_ACCOUNT, $tracking);
|
|
echo $tracking;
|
|
|
|
# Update the record so it is not tracked again
|
|
$sql = "UPDATE ".AGILE_DB_PREFIX."invoice
|
|
SET
|
|
custom_affiliate_status = ".$db->qstr('1')."
|
|
WHERE
|
|
account_id = ".$db->qstr(SESS_ACCOUNT)."
|
|
AND
|
|
billing_status = ".$db->qstr(1)."
|
|
AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
if ($rs === false) {
|
|
global $C_debug;
|
|
$C_debug->error('','', $db->ErrorMsg(). "\r\n\r\n". $sql);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Performance: (for the admin dashboard)
|
|
*/
|
|
function performance($VAR)
|
|
{
|
|
global $smarty, $C_list, $C_translate;
|
|
|
|
|
|
# Get the period type, default to month
|
|
if (empty($VAR['period']))
|
|
$p = 'm';
|
|
else
|
|
$p = $VAR['period'];
|
|
|
|
# Determine the correct period language:
|
|
if($p=='' or $p == 'm')
|
|
{
|
|
$pTrans = $C_translate->translate('thismonth','invoice','') . ' '.
|
|
$C_translate->translate('vs','invoice','') . ' ' .
|
|
$C_translate->translate('lastmonth','invoice','');
|
|
$pFore = $C_translate->translate('thismonth','invoice','');
|
|
}
|
|
elseif ($p == 'w')
|
|
{
|
|
$pTrans = $C_translate->translate('thisweek','invoice','') . ' '.
|
|
$C_translate->translate('vs','invoice','') . ' ' .
|
|
$C_translate->translate('lastweek','invoice','');
|
|
$pFore = $C_translate->translate('thisweek','invoice','');
|
|
}
|
|
elseif ($p == 'y')
|
|
{
|
|
$pTrans = $C_translate->translate('thisyear','invoice','') . ' '.
|
|
$C_translate->translate('vs','invoice','') . ' ' .
|
|
$C_translate->translate('lastyear','invoice','');
|
|
$pFore = $C_translate->translate('thisyear','invoice','');
|
|
}
|
|
|
|
$smarty->assign('period_compare', $pTrans);
|
|
$smarty->assign('period_forcast', $pFore);
|
|
|
|
|
|
|
|
# Get the period start & end
|
|
switch ($p) {
|
|
case 'w':
|
|
$dow = date('w');
|
|
$this_start = mktime(0,0,0,date('m'), date('d')-$dow, date('y'));
|
|
$this_end = mktime(23,59,59,date('m'), date('d'), date('y'));
|
|
$last_start = mktime(0,0,0,date('m'), date('d', $this_start)-7, date('y'));
|
|
$last_end = $this_start-1;
|
|
break;
|
|
|
|
case 'm':
|
|
$this_start = mktime(0,0,0,date('m'), 1, date('y'));
|
|
$this_end = mktime(23,59,59,date('m'), date('d'), date('y'));
|
|
$last_start = mktime(0,0,0, date('m', $this_start)-1, 1, date('y'));
|
|
$last_end = $this_start-1;
|
|
break;
|
|
|
|
case 'y':
|
|
$this_start = mktime(0,0,0,1,1, date('y', time()));
|
|
$this_end = mktime(23,59,59, date('m'), date('d'), date('y'));
|
|
$last_start = mktime(0,0,0,1,1, date('y', $this_start)-1);
|
|
$last_end = $this_start-1;
|
|
break;
|
|
}
|
|
|
|
##############################
|
|
# Get sales for this period
|
|
##############################
|
|
$db = &DB();
|
|
$this_amt = 0;
|
|
$sql = 'SELECT total_amt FROM ' . AGILE_DB_PREFIX . 'invoice WHERE
|
|
date_orig >= ' . $db->qstr( $this_start ) . ' AND
|
|
date_orig <= ' . $db->qstr( $this_end ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
while( !$rs->EOF ) {
|
|
$this_amt += $rs->fields['total_amt'];
|
|
$rs->MoveNext();
|
|
}
|
|
$smarty->assign('sales_current', $this_amt);
|
|
|
|
###############################
|
|
# Get sales for last period
|
|
###############################
|
|
$last_amt = 0;
|
|
$sql = 'SELECT total_amt FROM ' . AGILE_DB_PREFIX . 'invoice WHERE
|
|
date_orig >= ' . $db->qstr( $last_start ) . ' AND
|
|
date_orig <= ' . $db->qstr( $last_end ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
while( !$rs->EOF ) {
|
|
$last_amt += $rs->fields['total_amt'];
|
|
$rs->MoveNext();
|
|
}
|
|
$smarty->assign('sales_previous', $last_amt);
|
|
|
|
###############################
|
|
# Get sales change percentage
|
|
###############################
|
|
if($last_amt > 0)
|
|
$sales_change = $this_amt/$last_amt *100 -100;
|
|
else
|
|
$sales_change = 0;
|
|
|
|
if($sales_change == 0)
|
|
$sales_change = '';
|
|
elseif($sales_change < 0)
|
|
$sales_change = '<font color="#990000">' . number_format($sales_change, 1). '%</font>';
|
|
else
|
|
$sales_change = '+'.number_format($sales_change, 1). '%';
|
|
|
|
|
|
$smarty->assign('sales_change', $sales_change);
|
|
|
|
#################################
|
|
# Get forcast for current period
|
|
#################################
|
|
switch ($p) {
|
|
case 'w':
|
|
$dow = date('w')+1;
|
|
$forcast_daily = $this_amt/$dow ;
|
|
$forcast_l_daily = $last_amt / 7;
|
|
@$forcast_change = $forcast_daily / $forcast_1_daily *100 -100;
|
|
$forcast_current = $forcast_daily * 7;
|
|
break;
|
|
|
|
case 'm':
|
|
$forcast_daily = $this_amt / date('d');
|
|
$forcast_1_daily = $last_amt / date('t', mktime(0,0,0,date('m')-1, 1, date('y')));
|
|
@$forcast_change = $forcast_daily / $forcast_1_daily *100 -100;
|
|
$forcast_current = $forcast_daily * date('t');
|
|
break;
|
|
|
|
case 'y':
|
|
$forcast_daily = $this_amt / date('z');
|
|
$forcast_1_daily = $last_amt / 356;
|
|
@$forcast_change = $forcast_daily / $forcast_1_daily *100 -100;
|
|
$forcast_current = $forcast_daily * 365;
|
|
break;
|
|
}
|
|
|
|
$smarty->assign('forcast_current', $forcast_current);
|
|
|
|
###############################
|
|
# Get forcast change percentage
|
|
###############################
|
|
if($last_amt > 0 )
|
|
@$forcast_change = $forcast_daily/$forcast_1_daily *100;
|
|
else
|
|
$forcast_change = 0;
|
|
|
|
|
|
if($forcast_change == 0)
|
|
$forcast_change = '-';
|
|
elseif($forcast_change < 0)
|
|
$forcast_change = '<font color="#990000">' . number_format($forcast_change, 1). '%</font>';
|
|
else
|
|
$forcast_change = '+'.number_format($forcast_change, 1). '%';
|
|
|
|
|
|
$smarty->assign('forcast_change', $forcast_change);
|
|
|
|
|
|
####################################################
|
|
# Get Quota for Today to meet Forcasted sales:
|
|
####################################################
|
|
$smarty->assign('quota_current', $forcast_daily);
|
|
|
|
##############################
|
|
# Get AR credits for this period
|
|
##############################
|
|
$this_billed_amt = 0;
|
|
$sql = 'SELECT billed_amt FROM ' . AGILE_DB_PREFIX . 'invoice WHERE
|
|
date_orig >= ' . $db->qstr( $this_start ) . ' AND
|
|
date_orig <= ' . $db->qstr( $this_end ) . ' AND
|
|
billed_amt > ' . $db->qstr( 0 ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
while( !$rs->EOF ) {
|
|
$this_billed_amt += $rs->fields['billed_amt'];
|
|
$rs->MoveNext();
|
|
}
|
|
$smarty->assign('ar_credits_current', $this_billed_amt);
|
|
|
|
###############################
|
|
# Get AR credits for last period
|
|
###############################
|
|
$last_billed_amt = 0;
|
|
$sql = 'SELECT billed_amt FROM ' . AGILE_DB_PREFIX . 'invoice WHERE
|
|
date_orig >= ' . $db->qstr( $last_start ) . ' AND
|
|
date_orig <= ' . $db->qstr( $last_end ) . ' AND
|
|
billed_amt > ' . $db->qstr( 0 ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
while( !$rs->EOF ) {
|
|
$last_billed_amt += $rs->fields['billed_amt'];
|
|
$rs->MoveNext();
|
|
}
|
|
$smarty->assign('ar_credits_previous', $last_billed_amt);
|
|
|
|
###############################
|
|
# Get AR Credits change percentage
|
|
###############################
|
|
if($last_billed_amt > 0)
|
|
$ar_change = $this_billed_amt/$last_billed_amt *100 -100;
|
|
else
|
|
$ar_change = 0;
|
|
|
|
if($ar_change == 0)
|
|
$ar_change = '-';
|
|
elseif($ar_change < 0)
|
|
$ar_change = '<font color="#990000">' . number_format($ar_change, 1). '%</font>';
|
|
else
|
|
$ar_change = '+'.number_format($ar_change, 1). '%';
|
|
|
|
$smarty->assign('ar_credit_change', $ar_change);
|
|
|
|
##########################################
|
|
# Get AR Balance
|
|
##########################################
|
|
$this_ar_balance = $this_billed_amt - $this_amt;
|
|
$last_ar_balance = $last_billed_amt - $last_amt;
|
|
|
|
$smarty->assign('ar_balance_current', $this_ar_balance);
|
|
$smarty->assign('ar_balance_last', $last_ar_balance);
|
|
|
|
#########################################
|
|
# Get Users (current)
|
|
#########################################
|
|
$sql = 'SELECT id FROM ' . AGILE_DB_PREFIX . 'account WHERE
|
|
date_orig >= ' . $db->qstr( $this_start ) . ' AND
|
|
date_orig <= ' . $db->qstr( $this_end ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
$users_current = $rs->RecordCount();
|
|
$smarty->assign('users_current', $users_current);
|
|
|
|
#########################################
|
|
# Get Users (previous)
|
|
#########################################
|
|
$sql = 'SELECT id FROM ' . AGILE_DB_PREFIX . 'account WHERE
|
|
date_orig >= ' . $db->qstr( $last_start ) . ' AND
|
|
date_orig <= ' . $db->qstr( $last_end ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
$users_previous = $rs->RecordCount();
|
|
$smarty->assign('users_previous', $users_previous);
|
|
|
|
###############################
|
|
# Get users change percentage
|
|
###############################
|
|
if($users_previous > 0)
|
|
@$users_change = $users_current/$users_current *100 -100;
|
|
else
|
|
$users_change = 0;
|
|
|
|
if($users_change == 0)
|
|
$users_change = '-';
|
|
elseif($users_change < 0)
|
|
$users_change = '<font color="#990000">' . number_format($users_change, 1). '%</font>';
|
|
else
|
|
$users_change = '+'.number_format($users_change, 1). '%';
|
|
|
|
$smarty->assign('users_change', $users_change);
|
|
|
|
# Get Tickets
|
|
if( $C_list->is_installed('ticket') )
|
|
{
|
|
$smarty->assign('show_tickets', true);
|
|
|
|
#########################################
|
|
# Get Tickets (current)
|
|
#########################################
|
|
$sql = 'SELECT id FROM ' . AGILE_DB_PREFIX . 'ticket WHERE
|
|
date_orig >= ' . $db->qstr( $this_start ) . ' AND
|
|
date_orig <= ' . $db->qstr( $this_end ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
$tickets_current = $rs->RecordCount();
|
|
$smarty->assign('tickets_current', $tickets_current);
|
|
|
|
#########################################
|
|
# Get Tickets (previous)
|
|
#########################################
|
|
$sql = 'SELECT id FROM ' . AGILE_DB_PREFIX . 'ticket WHERE
|
|
date_orig >= ' . $db->qstr( $last_start ) . ' AND
|
|
date_orig <= ' . $db->qstr( $last_end ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
$tickets_previous = $rs->RecordCount();
|
|
$smarty->assign('tickets_previous', $tickets_previous);
|
|
|
|
###############################
|
|
# Get Tickets change percentage
|
|
###############################
|
|
if($tickets_previous > 0)
|
|
@$tickets_change = $tickets_current/$tickets_current *100 -100;
|
|
else
|
|
$tickets_change = 0;
|
|
|
|
if($tickets_change == 0)
|
|
$tickets_change = '-';
|
|
elseif($tickets_change < 0)
|
|
$tickets_change = '<font color="#990000">' . number_format($tickets_change, 1). '%</font>';
|
|
else
|
|
$tickets_change = '+'.number_format($tickets_change, 1). '%';
|
|
|
|
$smarty->assign('tickets_change', $tickets_change);
|
|
}
|
|
|
|
# Get Affiliate stats
|
|
if( $C_list->is_installed('affiliate') )
|
|
{
|
|
$smarty->assign('show_affiliates', true);
|
|
|
|
###########################################
|
|
# Get affiliate sales for this period
|
|
###########################################
|
|
$this_amt = 0;
|
|
$sql = 'SELECT total_amt FROM ' . AGILE_DB_PREFIX . 'invoice WHERE
|
|
date_orig >= ' . $db->qstr( $this_start ) . ' AND
|
|
date_orig <= ' . $db->qstr( $this_end ) . ' AND
|
|
affiliate_id != ' . $db->qstr( 0 ) . ' AND
|
|
affiliate_id != ' . $db->qstr( '' ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
while( !$rs->EOF ) {
|
|
$this_amt += $rs->fields['total_amt'];
|
|
$rs->MoveNext();
|
|
}
|
|
$smarty->assign('affiliate_sales_current', $this_amt);
|
|
|
|
##########################################
|
|
# Get affiliate sales for last period
|
|
##########################################
|
|
$last_amt = 0;
|
|
$sql = 'SELECT total_amt FROM ' . AGILE_DB_PREFIX . 'invoice WHERE
|
|
date_orig >= ' . $db->qstr( $last_start ) . ' AND
|
|
date_orig <= ' . $db->qstr( $last_end ) . ' AND
|
|
affiliate_id != ' . $db->qstr( 0 ) . ' AND
|
|
affiliate_id != ' . $db->qstr( '' ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
while( !$rs->EOF ) {
|
|
$last_amt += $rs->fields['total_amt'];
|
|
$rs->MoveNext();
|
|
}
|
|
$smarty->assign('affiliate_sales_previous', $last_amt);
|
|
|
|
###########################################
|
|
# Get affiliate sales change percentage
|
|
###########################################
|
|
if($last_amt > 0)
|
|
$sales_change = $this_amt/$last_amt *100 -100;
|
|
else
|
|
$sales_change = 0;
|
|
|
|
if($sales_change == 0)
|
|
$sales_change = '-';
|
|
elseif($sales_change < 0)
|
|
$sales_change = '<font color="#990000">' . number_format($sales_change, 1). '%</font>';
|
|
else
|
|
$sales_change = '+'.number_format($sales_change, 1). '%';
|
|
|
|
$smarty->assign('affiliate_sales_change', $sales_change);
|
|
}
|
|
|
|
|
|
/** Get VoIP Performance Data
|
|
*/
|
|
if( $C_list->is_installed('voip') )
|
|
{
|
|
|
|
# Avg. Call Duration for this period
|
|
$rs = $db->Execute(sqlSelect($db, "voip_cdr", "avg(ceiling(billsec/60))", "disposition='ANSWERED' AND date_orig >= $this_start AND date_orig <= $this_end"));
|
|
if(empty($rs->fields[0])) $acd=0; else $acd = $rs->fields[0];
|
|
$smarty->assign('acd',$acd);
|
|
|
|
# Avg. Call Duration for last period
|
|
$rs = $db->Execute(sqlSelect($db, "voip_cdr", "avg(ceiling(billsec/60))", "disposition='ANSWERED' AND date_orig >= $last_start AND date_orig <= $last_end"));
|
|
if(empty($rs->fields[0])) $acd_last=0; else $acd_last = $rs->fields[0];
|
|
$smarty->assign('acd_last',$acd_last);
|
|
|
|
# Get Avg. Call Duration change Percentage
|
|
if($acd > 0) $acd_change = $acd/$acd_last*100-100; else $acd_change = 0;
|
|
if($acd_change == 0)
|
|
$acd_change = '-';
|
|
elseif ($acd_change < 0)
|
|
$acd_change = '<font color="#990000">' . number_format($acd_change, 1). '%</font>';
|
|
else
|
|
$acd_change = '+'.number_format($acd_change, 1). '%';
|
|
$smarty->assign('acd_change', $acd_change);
|
|
|
|
|
|
# Avg. Successful Rate for this period
|
|
$rs = $db->Execute(sqlSelect($db, "voip_cdr", "count(*)", "disposition='ANSWERED' AND date_orig >= $this_start AND date_orig <= $this_end"));
|
|
$rs1 = $db->Execute(sqlSelect($db, "voip_cdr", "count(*)", "date_orig >= $this_start AND date_orig <= $this_end"));
|
|
if ($rs->fields[0])
|
|
$asr = number_format(($rs->fields[0] / $rs1->fields[0]) * 100,3)." %";
|
|
else
|
|
$asr = "-";
|
|
$smarty->assign('asr', $asr);
|
|
|
|
# Number of CDRs for this period
|
|
$cdrs = $rs1->fields[0];
|
|
$smarty->assign('cdrs', number_format($cdrs,0));
|
|
|
|
# Avg. Successful Rate for last period
|
|
$rs = $db->Execute(sqlSelect($db, "voip_cdr", "count(*)", "disposition='ANSWERED' AND date_orig >= $last_start AND date_orig <= $last_end"));
|
|
$rs1 = $db->Execute(sqlSelect($db, "voip_cdr", "count(*)", "date_orig >= $last_start AND date_orig <= $last_end"));
|
|
if ($rs->fields[0])
|
|
$asr_last = number_format(($rs->fields[0] / $rs1->fields[0]) * 100,3)." %";
|
|
else
|
|
$asr_last = "-";
|
|
$smarty->assign('asr_last', $asr_last);
|
|
|
|
# Number of CDRS for last period
|
|
$cdrs_last = $rs1->fields[0];
|
|
$smarty->assign('cdrs_last', number_format($cdrs_last,0));
|
|
|
|
# Get Avg. Successful Rate change Percentage
|
|
if($asr > 0) $asr_change = $asr/$asr_last*100-100; else $asr_change = 0;
|
|
if($asr_change == 0)
|
|
$asr_change = '-';
|
|
elseif ($asr_change < 0)
|
|
$asr_change = '<font color="#990000">' . number_format($asr_change, 1). '%</font>';
|
|
else
|
|
$asr_change = '+'.number_format($asr_change, 1). '%';
|
|
$smarty->assign('asr_change', $asr_change);
|
|
|
|
|
|
# Get Number of CDRs change Percentage
|
|
if($cdrs > 0) $cdrs_change = $cdrs/$cdrs_last*100-100; else $cdrs_change = 0;
|
|
if($cdrs_change == 0)
|
|
$cdrs_change = '-';
|
|
elseif ($cdrs_change < 0)
|
|
$cdrs_change = '<font color="#990000">' . number_format($cdrs_change, 1). '%</font>';
|
|
else
|
|
$cdrs_change = '+'.number_format($cdrs_change, 1). '%';
|
|
$smarty->assign('cdrs_change', $cdrs_change);
|
|
}
|
|
|
|
|
|
# Generate the Calendar Overview
|
|
include_once(PATH_MODULES.'core/calendar.inc.php');
|
|
$calendar = new calendar;
|
|
$start = $calendar->start;
|
|
$end = $calendar->end;
|
|
|
|
global $C_list;
|
|
$C_list->currency(DEFAULT_CURRENCY);
|
|
$currency_symbol=$C_list->format_currency[DEFAULT_CURRENCY]['symbol'];
|
|
|
|
# Get the paid/due invoice statistics
|
|
$rs = $db->Execute($sql=sqlSelect($db,"invoice","date_orig,total_amt,billing_status,refund_status,billed_amt,suspend_billing","date_orig >= $start and date_orig <= $end"));
|
|
if($rs && $rs->RecordCount()) {
|
|
while(!$rs->EOF) {
|
|
$day = date("j", $rs->fields['date_orig']);
|
|
|
|
if($rs->fields['billed_amt'] > 0 && ($rs->fields['billing_status'] == 1 || $rs->fields['refund_status'] != 1)) {
|
|
$paid[$day] += $rs->fields['billed_amt'];
|
|
}
|
|
if ($rs->fields['billing_status'] != 1 && $rs->fields['refund_status'] != 1 ) {
|
|
$amt = $rs->fields['total_amt'] - $rs->fields['billed_amt'];
|
|
$due[$day] += $amt;
|
|
}
|
|
|
|
$rs->MoveNext();
|
|
}
|
|
|
|
if(is_array($paid))
|
|
foreach($paid as $day=>$item)
|
|
$calendar->add("<b>Paid</b> - {$currency_symbol}". number_format($item,2), $day, 'green', 'green');
|
|
|
|
if(is_array($due))
|
|
foreach($due as $day=>$item)
|
|
$calendar->add("<b>Due</b> - {$currency_symbol}". number_format($item,2), $day,'red','red');
|
|
}
|
|
|
|
# Get the upcoming due services
|
|
$rs = $db->Execute($sql=sqlSelect($db,"service","date_next_invoice,price","price > 0 AND date_next_invoice >= $start AND date_next_invoice <= $end AND suspend_billing <> 1"));
|
|
if($rs && $rs->RecordCount()) {
|
|
while(!$rs->EOF) {
|
|
$day = date("j", $rs->fields['date_next_invoice']);
|
|
$sdue[$day] += $rs->fields['price'];
|
|
$rs->MoveNext();
|
|
}
|
|
foreach($sdue as $day=>$item) {
|
|
$calendar->add("<b>Recurring</b> - {$currency_symbol}". number_format($item,2), $day, 'grey', 'grey');
|
|
}
|
|
}
|
|
|
|
$calout= $calendar->generate();
|
|
$smarty->assign("calendar", $calout);
|
|
|
|
return;
|
|
}
|
|
|
|
/** AUTO APPROVE INVOICE
|
|
*/
|
|
function autoApproveInvoice($invoice_id)
|
|
{
|
|
$do = false;
|
|
|
|
# Get the invoice details:
|
|
$db = &DB();
|
|
$q = "SELECT * FROM ".AGILE_DB_PREFIX."invoice WHERE
|
|
id = ".$db->qstr($invoice_id)." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$invoice = $db->Execute($q);
|
|
if ($invoice === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','autoApproveInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
|
|
# Get the checkout details:
|
|
$q = "SELECT * FROM ".AGILE_DB_PREFIX."checkout WHERE
|
|
id = ".$db->qstr($invoice->fields['checkout_plugin_id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$checkout = $db->Execute($q);
|
|
if ($checkout === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','autoApproveInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
|
|
# Get the account details:
|
|
$q = "SELECT * FROM ".AGILE_DB_PREFIX."account WHERE
|
|
id = ".$db->qstr($invoice->fields['account_id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$account = $db->Execute($q);
|
|
if ($account === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','autoApproveInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
|
|
# is this a recurring invoices, and is manual approvale req?
|
|
if ( $invoice->fields['type'] == 1 && $checkout->fields['manual_approval_recur'] != 1) {
|
|
$do = true;
|
|
}
|
|
|
|
# Manual approval required for all?
|
|
if( $invoice->fields['type'] != 1 && $checkout->fields['manual_approval_all'] != 1) {
|
|
$do = true;
|
|
}
|
|
|
|
if(!$do) {
|
|
|
|
# manual approval req. for invoice amount?
|
|
if(!empty($checkout->fields['manual_approval_amount']) && $do == true)
|
|
if($checkout->fields['manual_approval_amount'] <= $invoice->fields['total_amt'])
|
|
$do = false;
|
|
|
|
# manual approval req. for user's country?
|
|
if(!empty($checkout->fields['manual_approval_country']) && $do == true) {
|
|
$arr = unserialize($checkout->fields['manual_approval_country']);
|
|
for($i=0; $i<count($arr); $i++) {
|
|
if($account->fields['country_id'] == $arr[$i])
|
|
$do = false;
|
|
}
|
|
}
|
|
|
|
# manual approval req. for user's currency?
|
|
if(!empty($checkout->fields['manual_approval_currency']) && $do == true) {
|
|
$arr = unserialize($checkout->fields['manual_approval_currency']);
|
|
for($i=0; $i<count($arr); $i++) {
|
|
if($invoice->fields['actual_billed_currency_id'] == $arr[$i])
|
|
$do = false;
|
|
}
|
|
}
|
|
|
|
# manual approval req. for user's group(s)?
|
|
if(!empty($checkout->fields['manual_approval_group']) && $do == true) {
|
|
# Get the group details:
|
|
$q = "SELECT group_id FROM ".AGILE_DB_PREFIX."account_group WHERE
|
|
account_id = ".$db->qstr($invoice->fields['account_id'])." AND
|
|
active = ".$db->qstr('1')." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$groups = $db->Execute($q);
|
|
if ($groups === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','autoApproveInvoice', $db->ErrorMsg());
|
|
}
|
|
|
|
$arr = unserialize($checkout->fields['manual_approval_group']);
|
|
while(!$groups->EOF) {
|
|
for($i=0; $i<count($arr); $i++) {
|
|
$idx = $groups->fields["group_id"];
|
|
if($idx == $arr[$i])
|
|
$do = false;
|
|
}
|
|
$groups->MoveNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($do)
|
|
{
|
|
# Approve the invoice
|
|
$arr['id'] = $invoice_id;
|
|
$this->approveInvoice($arr, $this);
|
|
}
|
|
else
|
|
{
|
|
# Admin manual approval notice
|
|
include_once(PATH_MODULES.'email_template/email_template.inc.php');
|
|
$mail = new email_template;
|
|
$mail->send('invoice_manual_auth_admin', $invoice->fields['account_id'], $invoice->fields['id'], $invoice->fields['checkout_plugin_id'], '');
|
|
}
|
|
}
|
|
|
|
|
|
/* APPROVE INVOICE
|
|
*/
|
|
function approveInvoice($VAR)
|
|
{
|
|
# Get the invoice details:
|
|
$db = &DB();
|
|
$q = "SELECT * FROM ".AGILE_DB_PREFIX."invoice WHERE
|
|
id = ".$db->qstr($VAR['id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$invoice = $db->Execute($q);
|
|
if ($invoice === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','approveInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
|
|
# Validate invoice exists & needs approval:
|
|
if($invoice->fields['id'] != $VAR['id'] || $invoice->fields['process_status'] == '1') return false;
|
|
|
|
# Update the invoice approval status:
|
|
$q = "UPDATE ".AGILE_DB_PREFIX."invoice SET
|
|
date_last = ".$db->qstr(time()).",
|
|
process_status = ".$db->qstr('1')." WHERE
|
|
id = ".$db->qstr($VAR['id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$result = $db->Execute($q);
|
|
if ($result === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','approveInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
|
|
# Send approval notice to user:
|
|
include_once(PATH_MODULES.'email_template/email_template.inc.php');
|
|
$mail = new email_template;
|
|
$mail->send('invoice_approved_user', $invoice->fields['account_id'], $VAR['id'], '', '');
|
|
|
|
# Include the service class
|
|
include_once(PATH_MODULES.'service/service.inc.php');
|
|
$srvc = new service;
|
|
|
|
# Determine if services have already been created for this invoice:
|
|
if($invoice->fields['type'] != 1 )
|
|
{
|
|
$q = "SELECT id FROM ".AGILE_DB_PREFIX."service WHERE
|
|
invoice_id = ".$db->qstr($VAR['id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$service = $db->Execute($q);
|
|
if ($service === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','approveInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
if ($service->RecordCount() > 0)
|
|
{
|
|
# Update services to approved status:
|
|
while(!$service->EOF)
|
|
{
|
|
$srvc->approveService($service->fields['id']);
|
|
$service->MoveNext();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
# Get the parent items in this invoice :
|
|
$q = "SELECT * FROM ".AGILE_DB_PREFIX."invoice_item WHERE
|
|
( parent_id = 0 OR parent_id IS NULL OR parent_id = '') AND
|
|
invoice_id = ".$db->qstr($VAR['id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$ii = $db->Execute($q);
|
|
if ($ii === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','approveInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
while(!$ii->EOF)
|
|
{
|
|
if(empty($ii->fields['service_id']))
|
|
{
|
|
# Add the service
|
|
$srvc->invoiceItemToService($ii->fields['id'], $invoice);
|
|
|
|
# Check for any children items in this invoice:
|
|
$q = "SELECT * FROM ".AGILE_DB_PREFIX."invoice_item WHERE
|
|
parent_id = ".$db->qstr($ii->fields['id'])." AND
|
|
invoice_id = ".$db->qstr($VAR['id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$iii = $db->Execute($q);
|
|
if ($iii === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','approveInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
while(!$iii->EOF)
|
|
{
|
|
# Add the service
|
|
$srvc->invoiceItemToService($ii->fields['id'], $invoice);
|
|
$iii->MoveNext();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$srvc = new service;
|
|
if($ii->fields['item_type'] == 2 && $ii->fields['domain_type'] == 'renew' ) {
|
|
# this is a domain renewal
|
|
$srvc->renewDomain( $ii, $invoice->fields['account_billing_id'] );
|
|
} else {
|
|
# this is an upgrade for an existing service
|
|
$srvc->modifyService( $ii, $invoice->fields['account_billing_id'] );
|
|
}
|
|
}
|
|
$ii->MoveNext();
|
|
}
|
|
}
|
|
elseif ($invoice->fields['type'] == 1 )
|
|
{
|
|
# recurring invoice, just update assoc services
|
|
# Loop through invoice items & approve assoc services
|
|
$q = "SELECT service_id FROM ".AGILE_DB_PREFIX."invoice_item WHERE
|
|
invoice_id = ".$db->qstr($VAR['id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$service = $db->Execute($q);
|
|
if ($service === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','voidInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
if ($service->RecordCount() > 0)
|
|
{
|
|
# Include the service class
|
|
include_once(PATH_MODULES.'service/service.inc.php');
|
|
$srvc = new service;
|
|
|
|
# Update services to inactive status:
|
|
while(!$service->EOF) {
|
|
$srvc->approveService($service->fields['service_id']);
|
|
$service->MoveNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
# get account id
|
|
if(defined("SESS_ACCOUNT"))
|
|
$account_id = SESS_ACCOUNT;
|
|
else
|
|
$account_id = 0;
|
|
|
|
# if approved, create a memo
|
|
$id = $db->GenID(AGILE_DB_PREFIX . 'invoice_memo_id');
|
|
$q = "INSERT INTO ".AGILE_DB_PREFIX."invoice_memo
|
|
SET
|
|
id = ".$db->qstr($id).",
|
|
site_id = ".$db->qstr(DEFAULT_SITE).",
|
|
date_orig = ".$db->qstr(time()).",
|
|
invoice_id = ".$db->qstr($VAR['id']).",
|
|
account_id = ".$db->qstr($account_id).",
|
|
type = ".$db->qstr('approval').",
|
|
memo = ".$db->qstr('NA');
|
|
$memo = $db->Execute($q);
|
|
if ($memo === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','approveInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/** VOID INVOICE
|
|
*/
|
|
function voidInvoice($VAR)
|
|
{
|
|
# Update the invoice approval status:
|
|
$db = &DB();
|
|
$q = "UPDATE ".AGILE_DB_PREFIX."invoice SET
|
|
date_last = ".$db->qstr(time()).",
|
|
process_status = ".$db->qstr('0')." WHERE
|
|
id = ".$db->qstr($VAR['id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$update = $db->Execute($q);
|
|
if ($update === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','voidInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
|
|
# Determine if services have already been created for this invoice and deactivate:
|
|
$q = "SELECT id FROM ".AGILE_DB_PREFIX."service WHERE
|
|
invoice_id = ".$db->qstr($VAR['id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$service = $db->Execute($q);
|
|
if ($service === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','voidInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
if ($service->RecordCount() > 0)
|
|
{
|
|
# Include the service class
|
|
include_once(PATH_MODULES.'service/service.inc.php');
|
|
$srvc = new service;
|
|
|
|
# Update services to inactive status:
|
|
while(!$service->EOF) {
|
|
$srvc->voidService($service->fields['id']);
|
|
$service->MoveNext();
|
|
}
|
|
}
|
|
|
|
# Loop through invoice items & delete assoc services
|
|
$q = "SELECT service_id FROM ".AGILE_DB_PREFIX."invoice_item WHERE
|
|
invoice_id = ".$db->qstr($VAR['id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$service = $db->Execute($q);
|
|
if ($service === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','voidInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
if ($service->RecordCount() > 0)
|
|
{
|
|
# Include the service class
|
|
include_once(PATH_MODULES.'service/service.inc.php');
|
|
$srvc = new service;
|
|
|
|
# Update services to inactive status:
|
|
while(!$service->EOF) {
|
|
$srvc->voidService($service->fields['service_id']);
|
|
$service->MoveNext();
|
|
}
|
|
}
|
|
|
|
# if voided, create a memo
|
|
$id = $db->GenID(AGILE_DB_PREFIX . 'invoice_memo_id');
|
|
$q = "INSERT INTO ".AGILE_DB_PREFIX."invoice_memo
|
|
SET
|
|
id = ".$db->qstr($id).",
|
|
site_id = ".$db->qstr(DEFAULT_SITE).",
|
|
date_orig = ".$db->qstr(time()).",
|
|
invoice_id = ".$db->qstr($VAR['id']).",
|
|
account_id = ".$db->qstr(SESS_ACCOUNT).",
|
|
type = ".$db->qstr('void').",
|
|
memo = ".$db->qstr('NA');
|
|
$insert = $db->Execute($q);
|
|
if ($insert === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','voidInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/** RECONCILE INVOICE
|
|
*/
|
|
function reconcile($VAR)
|
|
{
|
|
global $C_translate, $C_debug;
|
|
|
|
# validate amt
|
|
if( $VAR['amount'] <= 0) {
|
|
$C_debug->alert( "Payment amount to low!" );
|
|
return false;
|
|
}
|
|
|
|
# get the invoice details
|
|
$db = &DB();
|
|
$sql = 'SELECT * FROM ' . AGILE_DB_PREFIX . 'invoice WHERE
|
|
id = ' . $db->qstr( $VAR['id'] ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
if ($rs === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','reconcileInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
|
|
if(@$rs->RecordCount() == 0) return false;
|
|
|
|
$amt = $VAR['amount'];
|
|
$total_amt = $rs->fields['total_amt'];
|
|
$billed_amt = $rs->fields['billed_amt'];
|
|
$billed_currency_id = $rs->fields['billed_currency_id'];
|
|
$actual_billed_amt = $rs->fields['actual_billed_amt'];
|
|
$actual_billed_currency_id = $rs->fields['actual_billed_currency_id'];
|
|
$due = $total_amt - $billed_amt;
|
|
|
|
$overpaid = false;
|
|
if($amt > $due)
|
|
{
|
|
$billed = 1;
|
|
$update = $total_amt;
|
|
|
|
$overpaid = $amt - $due;
|
|
|
|
$C_translate->value['invoice']['amt'] = number_format($overpaid, 2);
|
|
$alert = $C_translate->translate('rec_over','invoice','');
|
|
}
|
|
elseif ($amt == $due)
|
|
{
|
|
$billed = 1;
|
|
$update = $total_amt;
|
|
}
|
|
else
|
|
{
|
|
$billed = 0;
|
|
$update = $amt + $billed_amt;
|
|
}
|
|
|
|
# Update the invoice record
|
|
$sql = 'UPDATE ' . AGILE_DB_PREFIX . 'invoice
|
|
SET
|
|
billed_amt = ' . $db->qstr( $update ) . ',
|
|
billing_status = ' . $db->qstr( $billed ) . '
|
|
WHERE
|
|
id = ' . $db->qstr( $VAR['id'] ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$db->Execute($sql);
|
|
|
|
# Create a memo
|
|
$id = $db->GenID(AGILE_DB_PREFIX . 'invoice_memo_id');
|
|
$q = "INSERT INTO ".AGILE_DB_PREFIX."invoice_memo
|
|
SET
|
|
id = ".$db->qstr($id).",
|
|
site_id = ".$db->qstr(DEFAULT_SITE).",
|
|
date_orig = ".$db->qstr(time()).",
|
|
invoice_id = ".$db->qstr($VAR['id']).",
|
|
account_id = ".$db->qstr(SESS_ACCOUNT).",
|
|
type = ".$db->qstr('reconcile').",
|
|
memo = ".$db->qstr('+ '.number_format($VAR['amount'],2) . " \r\n" . @$VAR['memo']);
|
|
$db->Execute($q);
|
|
|
|
|
|
# Reciept printing
|
|
include_once PATH_MODULES.'invoice/receipt_print.php';
|
|
$receipt = new receipt_print;
|
|
$receipt->add($rs, number_format($VAR['amount'],2), number_format($update,2));
|
|
|
|
|
|
# Auto update if billed complete
|
|
if($billed)
|
|
{
|
|
$this->autoApproveInvoice($VAR['id']);
|
|
|
|
# Get the default currency ISO
|
|
$q = "SELECT ".AGILE_DB_PREFIX."invoice_memo
|
|
SET
|
|
id = ".$db->qstr($id).",
|
|
site_id = ".$db->qstr(DEFAULT_SITE).",
|
|
date_orig = ".$db->qstr(time()).",
|
|
invoice_id = ".$db->qstr($VAR['id']).",
|
|
account_id = ".$db->qstr(SESS_ACCOUNT).",
|
|
type = ".$db->qstr('reconcile').",
|
|
memo = ".$db->qstr('+ '.number_format($VAR['amount'],2) . " \r\n" . @$VAR['memo']);
|
|
$currency = $db->Execute($q);
|
|
|
|
# User invoice creation confirmation
|
|
include_once(PATH_MODULES.'email_template/email_template.inc.php');
|
|
$email = new email_template;
|
|
$email->send('invoice_paid_user', $rs->fields['account_id'], $VAR['id'], $rs->fields['billed_currency_id'], '');
|
|
|
|
# Admin alert of payment processed
|
|
$email = new email_template;
|
|
$email->send('admin->invoice_paid_admin', $rs->fields['account_id'], $VAR['id'], $rs->fields['billed_currency_id'], '');
|
|
}
|
|
|
|
# Redirect
|
|
if(!empty($VAR['redirect']))
|
|
{
|
|
echo '
|
|
<script language="JavaScript">
|
|
window.parent.location=\''.$VAR['redirect'].'\'; ';
|
|
if(!empty($alert))
|
|
echo 'alert(\''.$alert.'\');';
|
|
echo '</script>';
|
|
exit;
|
|
}
|
|
|
|
$msg = $C_translate->translate('ref_comp','invoice','');
|
|
$C_debug->alert( $msg );
|
|
return;
|
|
}
|
|
|
|
|
|
/** REFUND INVOICE
|
|
*/
|
|
function refund($VAR)
|
|
{
|
|
global $C_translate, $C_debug;
|
|
|
|
# validate amt
|
|
if( $VAR['amount'] <= 0) {
|
|
$C_debug->alert( "Refund amount to low!" );
|
|
return false;
|
|
}
|
|
|
|
# get the invoice details
|
|
$db = &DB();
|
|
$sql = 'SELECT * FROM ' . AGILE_DB_PREFIX . 'invoice WHERE
|
|
id = ' . $db->qstr( $VAR['id'] ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($sql);
|
|
if(@$rs->RecordCount() == 0) return false;
|
|
|
|
$amt = $VAR['amount'];
|
|
$total_amt = $rs->fields['total_amt'];
|
|
$billed_amt = $rs->fields['billed_amt'];
|
|
$billed_currency_id = $rs->fields['billed_currency_id'];
|
|
$actual_billed_amt = $rs->fields['actual_billed_amt'];
|
|
$actual_billed_currency_id = $rs->fields['actual_billed_currency_id'];
|
|
$update = $billed_amt - $amt;
|
|
|
|
if($update>0) $billing_status=1; else $billing_status=0;
|
|
|
|
# Update the invoice record
|
|
echo $sql = 'UPDATE ' . AGILE_DB_PREFIX . 'invoice
|
|
SET
|
|
billed_amt = ' . $db->qstr( $update ) . ',
|
|
billing_status = '.$billing_status.',
|
|
suspend_billing = 1,
|
|
refund_status = 1
|
|
WHERE
|
|
id = ' . $db->qstr( $VAR['id'] ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$update2 = $db->Execute($sql);
|
|
if ($update2 === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','refundInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
|
|
# Create a memo
|
|
$id = $db->GenID(AGILE_DB_PREFIX . 'invoice_memo_id');
|
|
$q = "INSERT INTO ".AGILE_DB_PREFIX."invoice_memo
|
|
SET
|
|
id = ".$db->qstr($id).",
|
|
site_id = ".$db->qstr(DEFAULT_SITE).",
|
|
date_orig = ".$db->qstr(time()).",
|
|
invoice_id = ".$db->qstr($VAR['id']).",
|
|
account_id = ".$db->qstr(SESS_ACCOUNT).",
|
|
type = ".$db->qstr('refund').",
|
|
memo = ".$db->qstr('- '.number_format($VAR['amount'],2) . " \r\n" . @$VAR['memo']);
|
|
$insert = $db->Execute($q);
|
|
if ($insert === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','refundInvoice', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
|
|
# Void:
|
|
$this->voidInvoice($VAR, $this);
|
|
|
|
# Call into the checkout plugin and attempt realtime refund
|
|
$billing = $db->Execute($sql=sqlSelect($db, array('account_billing','checkout'), 'A.*,B.checkout_plugin',
|
|
"A.id = ::{$rs->fields['account_billing_id']}:: AND A.checkout_plugin_id=B.id"));
|
|
if($billing && $billing->RecordCount() && !empty($billing->fields['checkout_plugin'])) {
|
|
$plugin_file = PATH_PLUGINS.'checkout/'. $billing->fields['checkout_plugin'] .'.php';
|
|
if(is_file($plugin_file)) {
|
|
include_once ( $plugin_file );
|
|
eval( '$PLG = new plg_chout_' . $billing->fields['checkout_plugin'] . '("'.$billing->fields['checkout_plugin_id'].'");');
|
|
if(is_callable(Array($PLG,"refund"))) $PLG->refund($rs->fields, $billing->fields, $amt);
|
|
}
|
|
}
|
|
|
|
# Redirect
|
|
if(!empty($VAR['redirect'])) {
|
|
echo ' <script language="JavaScript"> window.parent.location=\''.$VAR['redirect'].'\'; </script>';
|
|
return;
|
|
}
|
|
|
|
$msg = $C_translate->translate('ref_comp','invoice','');
|
|
$C_debug->alert( $msg );
|
|
return;
|
|
}
|
|
|
|
# Get translated/hardcoded line item description for PDF invoice
|
|
function getLineItemDesc($sku,$id,$domain=false,$item_name)
|
|
{
|
|
if(!empty($item_name)) return $item_name;
|
|
global $C_translate;
|
|
if(!empty($sku) && $sku == 'DOMAIN-PARK' || $sku == 'DOMAIN-TRANSFER' || $sku == 'DOMAIN-REGISTER' || $sku == 'DOMAIN-RENEW') {
|
|
if($sku == 'DOMAIN-REGISTER') $name=$C_translate->translate('register','cart','');
|
|
elseif ($sku == 'DOMAIN-TRANSFER') $name=$C_translate->translate('transfer','cart','');
|
|
elseif ($sku == 'DOMAIN-PARK') $name=$C_translate->translate('park','cart','');
|
|
elseif ($sku == 'DOMAIN-RENEW') $name=$C_translate->translate('renew','cart','');
|
|
if($domain) return "$domain \r\n ( $name )";
|
|
else return $name;
|
|
} else {
|
|
include_once(PATH_CORE.'list.inc.php');
|
|
$C_list=new CORE_list;
|
|
if(empty($this->product_desc["$id"])) {
|
|
$desc = $C_list->translate("product_translate", "name", "product_id", $id, "translate_product");
|
|
$this->product_desc["$id"] = $desc['name'];
|
|
}
|
|
if(!empty($this->product_desc["$id"]))
|
|
return $this->product_desc["$id"];
|
|
else
|
|
return $sku;
|
|
}
|
|
return $sku;
|
|
}
|
|
|
|
/**
|
|
* Task based function to e-mail or store printable PDF of all unprinted invoices
|
|
*/
|
|
function delivery_task()
|
|
{
|
|
# get all unprinted invoices
|
|
$db=&DB();
|
|
$invcfg = $db->Execute(sqlSelect($db,"setup_invoice","*","id=::".DEFAULT_SITE."::"));
|
|
$rs = $db->SelectLimit($sql=sqlSelect($db,Array("invoice","account"),
|
|
"A.id,B.email,B.first_name,B.last_name,B.invoice_delivery,B.invoice_show_itemized",
|
|
"(A.billing_status=0 OR A.billing_status IS NULL) AND (A.print_status=0 OR A.print_status=NULL) and A.account_id=B.id and (B.invoice_delivery is not null AND B.invoice_delivery>0)"),100);
|
|
if($rs && $rs->RecordCount())
|
|
{
|
|
//define('FPDF_FONTPATH', PATH_INCLUDES.'pdf/font/');
|
|
require_once(PATH_INCLUDES.'pdf/fpdi.php');
|
|
require_once(PATH_INCLUDES.'pdf/fpdf_tpl.php');
|
|
require_once(PATH_INCLUDES.'pdf/fpdf.php');
|
|
require_once(PATH_INCLUDES.'pdf/pdf_invoice_'.$invcfg->fields['invoice_pdf_plugin'].'.inc.php');
|
|
|
|
// Send the e-mail....
|
|
require_once(PATH_INCLUDES."phpmailer/class.phpmailer.php");
|
|
|
|
$mail = new PHPMailer();
|
|
$mail->From = SITE_EMAIL;
|
|
$mail->FromName = SITE_NAME;
|
|
|
|
/*
|
|
$mail->SMTPAuth = true;
|
|
$mail->Host = "smtp.domain.com";
|
|
$mail->Username = "user";
|
|
$mail->Password = "pass";
|
|
$mail->Mailer = "smtp";
|
|
$mail->Debug = true;
|
|
*/
|
|
|
|
while(!$rs->EOF)
|
|
{
|
|
$pdf = new pdf_invoice_overview();
|
|
$pdf->companyName = SITE_NAME;
|
|
$pdf->companyAddress = SITE_ADDRESS;
|
|
$pdf->companyCity = SITE_CITY;
|
|
$pdf->companyState = SITE_STATE;
|
|
$pdf->companyZip = SITE_ZIP;
|
|
|
|
# load the setup_invoice fields into the pdf class
|
|
$pdf->load_setup($invcfg);
|
|
|
|
$pagecount = $pdf->setSourceFile($pdf->getTemplate());
|
|
$tplidx = $pdf->ImportPage(1);
|
|
|
|
$pdf->addPage();
|
|
$pdf->useTemplate($tplidx);
|
|
|
|
# override the show itemized, based on the customers choice
|
|
if($rs->fields['invoice_show_itemized'] == 0 || $rs->fields['invoice_show_itemized'] == 1)
|
|
$pdf->show_itemized = $rs->fields['invoice_show_itemized'];
|
|
|
|
$this->pdfInvoiceSummary($rs->fields['id'], $pdf);
|
|
|
|
$file = tempnam(PATH_FILES, "pdf_inv_".$rs->fields['id']).".pdf";
|
|
$pdf->Output($file,'F');
|
|
$pdf->closeParsers();
|
|
|
|
if($rs->fields['invoice_delivery'] == 1) {
|
|
$mail->AddAddress($rs->fields['email'], $rs->fields['first_name']. ' ' . $rs->fields['last_name']);
|
|
$mail->Subject = "Printable Invoice No. ". $rs->fields['id'];
|
|
$mail->Body = "Please find the printable version of invoice number {$rs->fields['id']} attached.\r\n\r\nThank you,\r\n".SITE_NAME;
|
|
$mail->AddAttachment($file, "INVOICE_{$rs->fields['id']}.pdf");
|
|
|
|
if($mail->Send()) {
|
|
$fields=Array('print_status'=>1);
|
|
$db->Execute(sqlUpdate($db,"invoice",$fields,"id=".$rs->fields['id']));
|
|
} else {
|
|
echo "Unable to email invoice # {$rs->fields['id']} to {$rs->fields['email']}<BR>";
|
|
}
|
|
|
|
$mail->ClearAddresses();
|
|
$mail->ClearAttachments();
|
|
} else if($rs->fields['invoice_delivery'] == 2) {
|
|
if(copy($file,AGILE_PDF_INVOICE_PATH."invoice_".$rs->fields['id'].".pdf")) {
|
|
$fields=Array('print_status'=>1);
|
|
$db->Execute(sqlUpdate($db,"invoice",$fields,"id=".$rs->fields['id']));
|
|
}
|
|
}
|
|
|
|
// delete tmp file and clean up vars used
|
|
unlink($file);
|
|
unset($pdf->itemsSummary);
|
|
unset($pdf); unset($tplidx); unset($pagecount);
|
|
|
|
$rs->MoveNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/** Display a PDF invoice
|
|
*/
|
|
function pdf($VAR)
|
|
{
|
|
# Check invoice
|
|
if(empty($VAR['id'])) {
|
|
echo 'No Invoice Specified.';
|
|
return false;
|
|
}
|
|
|
|
# Check admin authentication:
|
|
global $C_auth;
|
|
if ($C_auth->auth_method_by_name('invoice','view') == false) {
|
|
# Validate on account level
|
|
$db = &DB();
|
|
$rs = $db->Execute(sqlSelect($db,"invoice","account_id", "id = ::{$VAR['id']}::"));
|
|
if ($rs->fields['account_id'] != SESS_ACCOUNT) {
|
|
// todo: redirect to login page if not logged
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$db =& DB();
|
|
$invcfg = $db->Execute(sqlSelect($db,"setup_invoice","*","id=::".DEFAULT_SITE."::"));
|
|
|
|
if (!defined('FPDF_FONTPATH'))
|
|
define('FPDF_FONTPATH', PATH_INCLUDES.'pdf/font/');
|
|
require_once(PATH_INCLUDES.'pdf/fpdi.php');
|
|
require_once(PATH_INCLUDES.'pdf/fpdf_tpl.php');
|
|
require_once(PATH_INCLUDES.'pdf/fpdf.php');
|
|
require_once(PATH_INCLUDES.'pdf/pdf_invoice_'.$invcfg->fields['invoice_pdf_plugin'].'.inc.php');
|
|
|
|
ob_start();
|
|
|
|
$pdf = new pdf_invoice_overview();
|
|
$pdf->companyName = SITE_NAME;
|
|
$pdf->companyAddress = SITE_ADDRESS;
|
|
$pdf->companyCity = SITE_CITY;
|
|
$pdf->companyState = SITE_STATE;
|
|
$pdf->companyZip = SITE_ZIP;
|
|
|
|
# load the setup_invoice
|
|
$pdf->load_setup($invcfg);
|
|
|
|
$pagecount = $pdf->setSourceFile($pdf->getTemplate());
|
|
$tplidx = $pdf->ImportPage(1);
|
|
$pdf->addPage();
|
|
$pdf->useTemplate($tplidx);
|
|
$this->pdfInvoiceSummary($VAR['id'], $pdf);
|
|
$pdf->Output('invoice.pdf','D');
|
|
$pdf->closeParsers();
|
|
|
|
ob_end_flush();
|
|
}
|
|
|
|
/** Export multiple invoices */
|
|
function pdfExport(&$rs)
|
|
{
|
|
$db =& DB();
|
|
$invcfg = $db->Execute(sqlSelect($db,"setup_invoice","*",""));
|
|
|
|
define('FPDF_FONTPATH', PATH_INCLUDES.'pdf/font/');
|
|
require_once(PATH_INCLUDES.'pdf/fpdi.php');
|
|
require_once(PATH_INCLUDES.'pdf/fpdf_tpl.php');
|
|
require_once(PATH_INCLUDES.'pdf/fpdf.php');
|
|
require_once(PATH_INCLUDES.'pdf/pdf_invoice_'.$invcfg->fields['invoice_pdf_plugin'].'.inc.php');
|
|
|
|
ob_start();
|
|
$pdf = new pdf_invoice_overview();
|
|
$pdf->companyName = SITE_NAME;
|
|
$pdf->companyAddress = SITE_ADDRESS;
|
|
$pdf->companyCity = SITE_CITY;
|
|
$pdf->companyState = SITE_STATE;
|
|
$pdf->companyZip = SITE_ZIP;
|
|
$pdf->load_setup($invcfg);
|
|
$pagecount = $pdf->setSourceFile($pdf->getTemplate());
|
|
$tplidx = $pdf->ImportPage(1);
|
|
while(!$rs->EOF) {
|
|
$pdf->addPage();
|
|
$pdf->useTemplate($tplidx);
|
|
$this->pdfInvoiceSummary($rs->fields['id'], $pdf);
|
|
$rs->MoveNext();
|
|
unset($pdf->itemsSummary);
|
|
}
|
|
$pdf->Output();
|
|
$pdf->closeParsers();
|
|
ob_end_flush();
|
|
}
|
|
|
|
|
|
|
|
function pdfInvoiceSummary($id, &$pdf)
|
|
{
|
|
# Invoice details:
|
|
$db = &DB();
|
|
$invoice = $db->Execute( $sql = sqlSelect($db, array("invoice", "currency"), "A.*, B.symbol", "A.id = ::$id:: AND B.id = A.billed_currency_id"));
|
|
$pdf->setInvoiceFields($invoice->fields);
|
|
$pdf->setDueAmt($invoice->fields['total_amt'] - $invoice->fields['billed_amt']);
|
|
$pdf->setCurrency($invoice->fields['symbol']);
|
|
$pdf->setDateRange( mktime(0,0,0,date('m',$invoice->fields['due_date'])-1, date('d',$invoice->fields['due_date']), date('Y',$invoice->fields['due_date'])), $invoice->fields['due_date']);
|
|
$pdf->drawInvoiceNo();
|
|
$pdf->drawInvoiceDueDate();
|
|
$pdf->drawInvoiceTotalAmt();
|
|
$pdf->drawInvoiceDueAmt();
|
|
$pdf->drawInvoicePaidAmt();
|
|
$pdf->drawInvoiceDiscountAmt();
|
|
$pdf->drawInvoiceTaxAmt();
|
|
$pdf->drawInvoiceShippingAmt();
|
|
$pdf->drawInvoiceRange();
|
|
if($invoice->fields['billing_status'] !=1 && $invoice->fields['suspend_billing'] != 1 && $invoice->fields['due_date'] <= time())
|
|
$pdf->drawInvoiceDueNotice();
|
|
elseif($invoice->fields['billing_status'] == 1)
|
|
$pdf->drawInvoicePaidNotice();
|
|
|
|
# Account details:
|
|
$account = $db->Execute("SELECT * FROM ".AGILE_DB_PREFIX."account WHERE id = ".$db->qstr($invoice->fields['account_id'])." AND site_id = ".$db->qstr(DEFAULT_SITE));
|
|
$pdf->setAccountFields($account->fields);
|
|
$pdf->drawAccountId();
|
|
$pdf->drawAccountUsername();
|
|
$pdf->drawAccountName();
|
|
$pdf->drawAccountMailing();
|
|
|
|
# Company details:
|
|
$pdf->drawCompanyAddress();
|
|
$pdf->drawCompanyLogo();
|
|
|
|
## Get the summary items
|
|
$items = & $db->Execute("select sku, item_type, product_name, product_id, sum(quantity) as quantity, (sum(total_amt)) as amount, price_setup, price_base from ".AGILE_DB_PREFIX."invoice_item where invoice_id=".$db->qstr($id)." group by sku, item_type");
|
|
$i = 0;
|
|
if($items && $items->RecordCount()) {
|
|
while (!$items->EOF) {
|
|
$items_arr[$i] = $items->fields;
|
|
$desc = $this->getLineItemDesc($items->fields['sku'], $items->fields['product_id'], false, $items->fields['product_name']);
|
|
$items_arr[$i]['name'] = $desc;
|
|
$i++;
|
|
if ($items->fields['price_setup']) {
|
|
$items_arr[$i]['name'] = $desc." Set-up Charge";
|
|
$items_arr[$i]['amount'] = $items->fields['price_setup'];
|
|
$i++;
|
|
}
|
|
$items->MoveNext();
|
|
}
|
|
}
|
|
if ($invoice->fields['discount_amt']) {
|
|
$items_arr[$i]['name'] = 'Discount';
|
|
$items_arr[$i]['amount'] = -($invoice->fields['discount_amt']);
|
|
$i++;
|
|
}
|
|
if ($invoice->fields['tax_amt']) {
|
|
$trs = $db->Execute($sql=sqlSelect($db, Array('invoice_item_tax','tax'),"A.amount,B.description","A.tax_id=B.id AND A.invoice_id=::$id::"));
|
|
if($trs && $trs->RecordCount()) {
|
|
unset($taxes);
|
|
while(!$trs->EOF) {
|
|
$taxes["{$trs->fields['description']}"] += $trs->fields["amount"];
|
|
$trs->MoveNext();
|
|
}
|
|
foreach($taxes as $txds=>$txamt) {
|
|
$items_arr[$i]['name'] = $txds;
|
|
$items_arr[$i]['amount'] = $txamt;
|
|
$i++;
|
|
}
|
|
}
|
|
}
|
|
$pdf->drawSummaryLineItems($items_arr);
|
|
unset($items_arr);
|
|
unset($pdf->itemsSummary);
|
|
|
|
## BEGIN loop for enumerating information in multiple ways on the invoice
|
|
$iteration = 0;
|
|
while($pdf->drawLineItems_pre($iteration)) {
|
|
## Get the line items:
|
|
$items = & $db->Execute( sqlSelect($db, "invoice_item", "*", "invoice_id = ::$id::") );
|
|
if ($items && $items->RecordCount()) {
|
|
while ( !$items->EOF ) {
|
|
#$items_arr[] = $items->fields;
|
|
// get the date range if set
|
|
if(!empty($items->fields['date_start']) && !empty($items->fields['date_stop'])) {
|
|
global $C_translate;
|
|
$C_translate->value('invoice','start', date(UNIX_DATE_FORMAT,$items->fields['date_start']));
|
|
$C_translate->value('invoice','stop', date(UNIX_DATE_FORMAT,$items->fields['date_stop']));
|
|
#$smart_items[$ii]['range'] = $C_translate->translate('recur_date_range','invoice','');
|
|
}
|
|
|
|
$cost = $items->fields['price_base'];
|
|
$total = $cost * $items->fields['quantity'];
|
|
$desc = $this->getLineItemDesc($items->fields['sku'],$items->fields['product_id'], strtolower($items->fields['domain_name'].'.'.$items->fields['domain_tld']), $items->fields['product_name']);
|
|
$line = array(
|
|
"name" => $desc,
|
|
'amount' => $cost,
|
|
'sku'=>$items->fields['sku'],
|
|
'qty'=>$items->fields['quantity'],
|
|
'cost'=>$cost,
|
|
'attr'=>$items->fields['product_attr'],
|
|
'price_type'=>$items->fields['price_type'],
|
|
'price_base'=>$items->fields['price_base'],
|
|
'item_type'=>$items->fields['item_type'],
|
|
'total_amt'=>$items->fields['total_amt']
|
|
);
|
|
$pdf->drawLineItems($db, $line);
|
|
if ($items->fields['price_setup']) {
|
|
$desc .= " Set-up Charge";
|
|
$total = $items->fields['price_setup'];
|
|
$line = array("name" => $desc, 'amount' => $total, 'qty'=>'1', 'sku'=>$items->fields['sku'], 'cost'=>$total, 'price_base'=>$total, 'price_type'=>999);
|
|
$pdf->drawLineItems($db, $line);
|
|
}
|
|
$items->MoveNext();
|
|
}
|
|
}
|
|
if ($invoice->fields['discount_amt']) {
|
|
$desc = 'Discount';
|
|
$total = -($invoice->fields['discount_amt']);
|
|
$line = array("name" => $desc, 'amount' => $total, 'qty'=>'1', 'cost'=>$total, 'price_base'=>$total, 'price_type'=>999);
|
|
$pdf->drawLineItems($db, $line);
|
|
}
|
|
if ($invoice->fields['tax_amt']) {
|
|
$trs = $db->Execute($sql=sqlSelect($db, Array('invoice_item_tax','tax'),"A.amount,B.description","A.tax_id=B.id AND A.invoice_id=::$id::"));
|
|
if($trs && $trs->RecordCount()) {
|
|
unset($taxes);
|
|
while(!$trs->EOF) {
|
|
$taxes["{$trs->fields['description']}"] += $trs->fields["amount"];
|
|
$trs->MoveNext();
|
|
}
|
|
foreach($taxes as $txds=>$txamt) {
|
|
$line = array("name" => $txds, 'amount' => $txamt, 'qty'=>'1', 'cost'=>$txamt, 'price_base'=>$txamt, 'price_type'=>999);
|
|
$pdf->drawLineItems($db, $line);
|
|
}
|
|
}
|
|
}
|
|
# Increment the iteration
|
|
++$iteration;
|
|
}
|
|
# Custom functions:
|
|
$pdf->drawCustom();
|
|
unset($db);
|
|
}
|
|
|
|
|
|
/** RESEND DUE NOTICE
|
|
*/
|
|
function resend($VAR)
|
|
{
|
|
global $C_debug;
|
|
|
|
# User invoice creation confirmation
|
|
include_once(PATH_MODULES.'email_template/email_template.inc.php');
|
|
$mail = new email_template;
|
|
$mail->send('invoice_resend', $VAR['account_id'], $VAR['id'], '', '');
|
|
|
|
# Alert
|
|
$C_debug->alert('Sent payment due notice to user');
|
|
|
|
# Update invoice
|
|
$db = &DB();
|
|
$q = "SELECT notice_count FROM ".AGILE_DB_PREFIX."invoice WHERE
|
|
id = ".$db->qstr($VAR['id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($q);
|
|
$count = $rs->fields['notice_count'] + 1;
|
|
$q = "UPDATE ".AGILE_DB_PREFIX."invoice SET
|
|
notice_count = ".$db->qstr($count)." WHERE
|
|
id = ".$db->qstr($VAR['id'])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($q);
|
|
}
|
|
|
|
|
|
/**
|
|
* Generate all invoices for recurring services/charges/domains
|
|
*/
|
|
function generate() {
|
|
|
|
// check if charge module installed
|
|
global $C_list;
|
|
$charge_installed = $C_list->is_installed('charge');
|
|
|
|
// get services to be billed grouped by account and date
|
|
if(MAX_INV_GEN_PERIOD <= 0) $max_date = time()+86400; else $max_date = time()+(MAX_INV_GEN_PERIOD*86400);
|
|
$p=AGILE_DB_PREFIX; $s=DEFAULT_SITE;
|
|
$ids=false;
|
|
$account=false;
|
|
$date=false;
|
|
$invoice=false;
|
|
$sql = "SELECT DISTINCT service.id as serviceId, account.id as accountId, invoice.id as invoiceId, from_unixtime(service.date_next_invoice,'%Y-%m-%d') as dayGroup
|
|
FROM {$p}service as service
|
|
JOIN {$p}account as account ON ( service.account_id=account.id and account.site_id={$s} )
|
|
LEFT JOIN {$p}invoice as invoice ON ( service.invoice_id=invoice.id and invoice.site_id={$s} )
|
|
WHERE service.site_id={$s}
|
|
AND service.active = 1
|
|
AND ( service.suspend_billing IS NULL OR service.suspend_billing = 0 )
|
|
AND ( service.date_next_invoice > 0 AND service.date_next_invoice IS NOT NULL )
|
|
AND
|
|
((
|
|
( account.invoice_advance_gen!='' OR account.invoice_advance_gen is not null ) AND service.date_next_invoice <= (UNIX_TIMESTAMP(CURDATE())+(account.invoice_advance_gen*86400))
|
|
) OR (
|
|
( account.invoice_advance_gen='' OR account.invoice_advance_gen is null ) AND service.date_next_invoice <= {$max_date}
|
|
))
|
|
ORDER BY accountId, dayGroup, serviceId";
|
|
$db=&DB();
|
|
#$db->debug=true;
|
|
$rs=$db->Execute($sql);
|
|
if($rs === false) {global $C_debug; $C_debug->error('invoice.inc.php','generate()', $sql . " \r\n\r\n " . @$db->ErrorMsg()); }
|
|
if($rs && $rs->RecordCount()) {
|
|
while(!$rs->EOF) {
|
|
if( $ids && ($rs->fields['accountId'] != $account ) || ($rs->fields['dayGroup'] != $date) ) {
|
|
$this->generateInvoices($ids, $account, $invoice, $charge_installed);
|
|
$ids=false;
|
|
}
|
|
|
|
// set the current account and date
|
|
$account=$rs->fields['accountId'];
|
|
$invoice=$rs->fields['invoiceId'];
|
|
$date=$rs->fields['dayGroup'];
|
|
|
|
// add to id list
|
|
if($ids) $ids.=",";
|
|
$ids.=$rs->fields['serviceId'];
|
|
$rs->MoveNext();
|
|
}
|
|
if($ids) $this->generateInvoices($ids, $account, $invoice, $charge_installed);
|
|
}
|
|
|
|
// Generate invoices for any domains expiring in X days.
|
|
if($C_list->is_installed('host_tld')) $this->generateDomains();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
function generateInvoices($ids, $account_id, $invoice_id, $charge_installed=false) {
|
|
|
|
if(empty($ids)) return false;
|
|
|
|
# load required elements
|
|
include_once(PATH_MODULES . 'service/service.inc.php');
|
|
include_once(PATH_MODULES . 'discount/discount.inc.php');
|
|
include_once(PATH_MODULES . 'tax/tax.inc.php');
|
|
$taxObj = new tax;
|
|
$serviceObj = new service;
|
|
|
|
# start a transaction
|
|
$db=&DB();
|
|
#$db->debug=true;
|
|
if(AGILE_DB_TYPE == 'mysqlt') {
|
|
$db->StartTrans();
|
|
if(!$db->hasTransactions) {
|
|
global $C_debug;
|
|
$msg= "Transactions not supported in 'mysql' driver. Use 'mysqlt' or 'mysqli' driver";
|
|
$C_debug->alert($msg);
|
|
$C_debug->error('invoice.inc.php','generateInvoices()', "Transactions not supported in 'mysql' driver. Use 'mysqlt' or 'mysqli' driver");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
# generate an invoice id
|
|
$invoice = sqlGenID($db, 'invoice');
|
|
|
|
# check for any discounts for the parent invoice or account_id
|
|
# applied at checkout and should continue to be applied if recurring type discount
|
|
$discountObj = new discount;
|
|
$discountObj->available_discounts($account_id, 1, $invoice_id);
|
|
|
|
# beginning totals
|
|
$sub_total=0;
|
|
$taxable_amount=0;
|
|
$tax_amt=0;
|
|
$discount_amt=0;
|
|
|
|
# get the full account and service and invoice details
|
|
$p=AGILE_DB_PREFIX; $s=DEFAULT_SITE;
|
|
$sql = "SELECT DISTINCT
|
|
service.id, service.parent_id, service.invoice_id, service.invoice_item_id, service.account_id, service.account_billing_id, service.product_id,
|
|
service.sku, service.active, service.bind, service.type, service.price, service.price_type, service.taxable, service.date_last_invoice, service.date_next_invoice,
|
|
service.recur_type, service.recur_schedule, service.recur_weekday, service.recur_week, service.domain_name,
|
|
service.domain_tld, service.domain_type, service.domain_term, service.prod_attr, service.prod_attr_cart,
|
|
account.currency_id, account.first_name, account.last_name, account.country_id, account.state, account.invoice_grace, account.invoice_advance_gen, account.affiliate_id as account_affiliate_id,
|
|
invoice.affiliate_id, invoice.campaign_id, invoice.reseller_id, invoice.checkout_plugin_id, invoice.checkout_plugin_data, invoice.billed_currency_id, invoice.actual_billed_currency_id
|
|
FROM {$p}service as service
|
|
JOIN {$p}account as account ON ( service.account_id=account.id and account.site_id={$s} )
|
|
LEFT JOIN {$p}invoice as invoice ON ( service.invoice_id=invoice.id and invoice.site_id={$s} )
|
|
WHERE service.id in ({$ids})";
|
|
$service=$db->Execute($sql);
|
|
if($service === false) {global $C_debug; $C_debug->error('invoice.inc.php','generateInvoices()1', $sql . " \r\n\r\n " . @$db->ErrorMsg()); $db->FailTrans(); return false; }
|
|
if($service && $service->RecordCount()) {
|
|
while(!$service->EOF) {
|
|
|
|
if(empty($service->fields['billed_currency_id'])) $service->fields['billed_currency_id'] = DEFAULT_CURRENCY;
|
|
if(empty($service->fields['actual_billed_currency_id'])) $service->fields['actual_billed_currency_id'] = $service->fields['billed_currency_id'];
|
|
|
|
$this->account_id=$service->fields['account_id'];
|
|
$this->parent_id=$service->fields['invoice_id'];
|
|
$this->account_billing_id=$service->fields['account_billing_id'];
|
|
if(!empty($service->fields['account_affiliate_id']))
|
|
$this->affiliate_id=$service->fields['account_affiliate_id'];
|
|
else
|
|
$this->affiliate_id=$service->fields['affiliate_id'];
|
|
$this->campaign_id=$service->fields['campaign_id'];
|
|
$this->reseller_id=$service->fields['reseller_id'];
|
|
$this->checkout_plugin_id=$service->fields['checkout_plugin_id'];
|
|
$this->checkout_plugin_data=$service->fields['checkout_plugin_data'];
|
|
$this->billed_currency_id=$service->fields['billed_currency_id'];
|
|
$this->actual_billed_currency_id=$service->fields['actual_billed_currency_id'];
|
|
$this->invoice_grace=$service->fields['invoice_grace'];
|
|
|
|
$item_tax_amt=0;
|
|
$item_total_amt=0;
|
|
$item_discount_amt=0;
|
|
|
|
# gen item_id
|
|
$item = sqlGenID($db, "invoice_item");
|
|
|
|
# Calculate any recurring discounts for this item
|
|
$item_total_amt = $service->fields['price'];
|
|
$item_discount_amt = $discountObj->calc_all_discounts(1, $item, $service->fields['product_id'], $service->fields['price'], $service->fields['account_id'], $sub_total+$service->fields['price']);
|
|
$item_total_amt -= $item_discount_amt;
|
|
$sub_total += $item_total_amt;
|
|
$discount_amt += $item_discount_amt;
|
|
|
|
# calculate any taxes for this item
|
|
if($service->fields['taxable'] == 1) {
|
|
$item_tax_amt=0;
|
|
$item_tax_arr = $taxObj->calculate($item_total_amt, $service->fields['country_id'], $service->fields['state']);
|
|
if(is_array($item_tax_arr)) foreach($item_tax_arr as $tx) $item_tax_amt += $tx['rate'];
|
|
$tax_amt += $item_tax_amt;
|
|
}
|
|
|
|
# Calculate next invoice date
|
|
$next_invoice = $serviceObj->calcNextInvoiceDate($service->fields['date_next_invoice'], $service->fields['recur_schedule'], $service->fields['recur_type'], $service->fields['recur_weekday']);
|
|
$due_date = $service->fields['date_next_invoice'];
|
|
$recur_schedule=0;
|
|
if(!empty($service->fields['recur_schedule'])) $recur_schedule = $service->fields['recur_schedule'];
|
|
|
|
// create the invoice item
|
|
$sql="INSERT INTO {$p}invoice_item SET
|
|
id=$item,
|
|
site_id=$s,
|
|
date_orig=".time().",
|
|
invoice_id = $invoice,
|
|
account_id={$service->fields['account_id']},
|
|
service_id={$service->fields['id']},
|
|
product_id={$service->fields['product_id']},
|
|
product_attr=".$db->qstr($service->fields['prod_attr']).",
|
|
product_attr_cart=".$db->qstr($service->fields['prod_attr_cart']).",
|
|
sku=".$db->qstr($service->fields['sku']).",
|
|
quantity=1,
|
|
item_type=0,
|
|
price_type={$service->fields['price_type']},
|
|
price_base={$service->fields['price']},
|
|
price_setup=0,
|
|
recurring_schedule={$recur_schedule},
|
|
date_start={$service->fields['date_next_invoice']},
|
|
date_stop=$next_invoice,
|
|
domain_name=".$db->qstr($service->fields['domain_name']).",
|
|
domain_tld=".$db->qstr($service->fields['domain_tld']).",
|
|
domain_type=".$db->qstr($service->fields['domain_type']).",
|
|
tax_amt=$tax_amt,
|
|
total_amt=$item_total_amt,
|
|
discount_amt=$item_discount_amt";
|
|
$itemrs=$db->Execute($sql);
|
|
if($itemrs === false) {global $C_debug; $C_debug->error('invoice.inc.php','generateInvoices()2', $sql . " \r\n\r\n " . @$db->ErrorMsg()); $db->FailTrans(); return false; }
|
|
|
|
// Insert tax records
|
|
$taxObj->invoice_item($invoice, $item, $service->fields['account_id'], @$item_tax_arr);
|
|
|
|
# Insert discount records
|
|
$discountObj->invoice_item($invoice, $item, $service->fields['account_id'], @$discountObj->discount_arr);
|
|
|
|
// Update the last & next invoice date for this service
|
|
$sql="UPDATE {$p}service
|
|
SET
|
|
date_last_invoice = {$service->fields['date_next_invoice']},
|
|
date_next_invoice = $next_invoice
|
|
WHERE
|
|
site_id=$s AND id = {$service->fields['id']} ";
|
|
$srvsrs = $db->Execute($sql);
|
|
if($srvsrs === false) {global $C_debug; $C_debug->error('invoice.inc.php','generateInvoices()3', $sql . " \r\n\r\n " . @$db->ErrorMsg()); $db->FailTrans(); return false; }
|
|
|
|
// get any charges for this service and create them as invoice items
|
|
if($charge_installed) {
|
|
$sql = "SELECT * FROM ".AGILE_DB_PREFIX."charge WHERE (status=0 or status is null) and site_id=".DEFAULT_SITE." AND service_id = ".$service->fields['id']." AND date_orig < ". $service->fields['date_next_invoice'];
|
|
$charge = $db->Execute($sql);
|
|
if($charge && $charge->RecordCount()) {
|
|
while(!$charge->EOF) {
|
|
$item_tax_amt=0;
|
|
$item_total_amt=0;
|
|
$item_discount_amt=0;
|
|
|
|
// Calculate any recurring discounts for this charge item
|
|
$item_total_amt = ($charge->fields['quantity']*$charge->fields['amount']);
|
|
$item_discount_amt = $discountObj->calc_all_discounts(1, $item, $charge->fields['product_id'], $item_total_amt, $service->fields['account_id'], $sub_total+$item_total_amt);
|
|
$item_total_amt -= $item_discount_amt;
|
|
$sub_total += $item_total_amt;
|
|
$discount_amt += $item_discount_amt;
|
|
|
|
// calculate any taxes for this item
|
|
if($charge->fields['taxable'] == 1) {
|
|
$item_tax_amt=0;
|
|
$item_tax_arr = $taxObj->calculate($chargeamt, $service->fields['country_id'], $service->fields['state']);
|
|
if(is_array($item_tax_arr)) foreach($item_tax_arr as $tx) $item_tax_amt += $tx['rate'];
|
|
$tax_amt += $item_tax_amt;
|
|
}
|
|
|
|
// create the invoice item
|
|
$charge_item_id = sqlGenID($db, 'invoice_item');
|
|
|
|
$sql = "INSERT INTO {$p}invoice_item SET
|
|
id = $charge_item_id,
|
|
site_id = $s,
|
|
charge_id = {$charge->fields['id']},
|
|
date_orig = ".time().",
|
|
invoice_id = $invoice,
|
|
account_id = ".$this->account_id.",
|
|
service_id = ".$db->qstr($service->fields['id']).",
|
|
product_id = ".$db->qstr($charge->fields['product_id']).",
|
|
product_attr= ".$db->qstr($charge->fields['attributes']).",
|
|
sku = ".$db->qstr($service->fields['sku']).",
|
|
price_base = ".$db->qstr($charge->fields['amount']).",
|
|
quantity = ".$charge->fields['quantity'].",
|
|
item_type = 5,
|
|
price_type = 0,
|
|
price_setup = 0,
|
|
tax_amt = $item_tax_amt,
|
|
total_amt = $item_total_amt,
|
|
discount_amt= $item_discount_amt";
|
|
$itemrs=$db->Execute($sql);
|
|
if($itemrs === false) {global $C_debug; $C_debug->error('invoice.inc.php','generateInvoices()4', $sql . " \r\n\r\n " . @$db->ErrorMsg()); $db->FailTrans(); return false; }
|
|
|
|
# Insert tax records
|
|
$taxObj->invoice_item($invoice, $charge_item_id, $charge->fields['account_id'], @$item_tax_arr);
|
|
|
|
# Insert discount records
|
|
$discountObj->invoice_item($invoice, $charge_item_id, $charge->fields['account_id'], @$discountObj->discount_arr);
|
|
|
|
# update charge status
|
|
$chargers=$db->Execute("UPDATE ".AGILE_DB_PREFIX."charge set status=1 WHERE id={$charge->fields['id']} AND site_id=".DEFAULT_SITE);
|
|
if($chargers === false) {global $C_debug; $C_debug->error('invoice.inc.php','generateInvoices()2', $sql . " \r\n\r\n " . @$db->ErrorMsg()); $db->FailTrans(); return false; }
|
|
|
|
$charge->MoveNext();
|
|
}
|
|
}
|
|
}
|
|
$service->MoveNext();
|
|
}
|
|
|
|
// add any taxes
|
|
@$total = $sub_total + $tax_amt;
|
|
|
|
// get invoice grace period from global/account
|
|
if(!empty($this->invoice_grace)) $grace_period=$this->invoice_grace; else $grace_period=GRACE_PERIOD;
|
|
|
|
$sql = "INSERT INTO {$p}invoice SET
|
|
id=$invoice,
|
|
site_id=$s,
|
|
date_orig = ".time().",
|
|
date_last = ".time().",
|
|
notice_next_date = ".time().",
|
|
type = 1,
|
|
process_status = 0,
|
|
billing_status = 0,
|
|
suspend_billing = 0,
|
|
print_status = 0,
|
|
refund_status = 0,
|
|
billed_amt = 0,
|
|
actual_billed_amt = 0,
|
|
notice_count = 0,
|
|
parent_id = ".$db->qstr($this->parent_id).",
|
|
account_id = {$this->account_id},
|
|
account_billing_id = ".$db->qstr($this->account_billing_id).",
|
|
affiliate_id = ".$db->qstr($this->affiliate_id).",
|
|
campaign_id = ".$db->qstr($this->campaign_id).",
|
|
reseller_id = ".$db->qstr($this->reseller_id).",
|
|
checkout_plugin_id = ".$db->qstr($this->checkout_plugin_id).",
|
|
checkout_plugin_data = ".$db->qstr($this->checkout_plugin_data).",
|
|
actual_billed_currency_id = ".$db->qstr($this->actual_billed_currency_id).",
|
|
billed_currency_id = ".$db->qstr($this->billed_currency_id).",
|
|
notice_max = ".$db->qstr(MAX_BILLING_NOTICE).",
|
|
grace_period = ".$db->qstr($grace_period).",
|
|
tax_amt = ".$tax_amt.",
|
|
discount_amt = ".$discount_amt.",
|
|
total_amt = ".$total.",
|
|
due_date = $due_date";
|
|
$invoicers=$db->Execute($sql);
|
|
if($invoicers === false) {global $C_debug; $C_debug->error('invoice.inc.php','generateInvoices()2', $sql . " \r\n\r\n " . @$db->ErrorMsg()); $db->FailTrans(); return false; }
|
|
}
|
|
|
|
if(AGILE_DB_TYPE == 'mysqlt') $db->CompleteTrans();
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Invoice expiring domains
|
|
*/
|
|
function generateDomains()
|
|
{
|
|
$db = &DB();
|
|
define('DEFAULT_DOMAIN_INVOICE', 30); //how far out to generate expiring domain invoices
|
|
$expire = time() + (DEFAULT_DOMAIN_INVOICE*86400);
|
|
|
|
### Get domains expiring soon:
|
|
$rs = $db->Execute( sqlSelect( $db, 'service', '*', " active=1 AND domain_date_expire <= $expire AND type = 'domain' AND queue = 'none' AND
|
|
( domain_type = 'register' OR domain_type = 'transfer' OR domain_type = 'renew' ) AND
|
|
( suspend_billing = 0 OR suspend_billing IS NULL) " ) );
|
|
|
|
if($rs && $rs->RecordCount() > 0 ) {
|
|
while(!$rs->EOF) {
|
|
# Check that this domain has not already been invoiced
|
|
$invoiced = $db->Execute( sqlSelect ($db, Array('invoice_item','invoice'), Array('A.*','B.*'),
|
|
" A.invoice_id = B.id AND A.service_id = {$rs->fields['id']} AND A.sku = 'DOMAIN-RENEW' AND domain_type = 'renew' AND
|
|
date_start = {$rs->fields['date_last_invoice']} AND date_stop = {$rs->fields['domain_date_expire']}" ) );
|
|
|
|
if($invoiced && $invoiced->RecordCount() == 0) {
|
|
# Not previously invoiced, generate now!
|
|
$this->generatedomaininvoice( $rs->fields, $this );
|
|
}
|
|
$rs->MoveNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Invoice expiring domains p2
|
|
*/
|
|
function generatedomaininvoice( $VAR )
|
|
{
|
|
include_once(PATH_MODULES . 'tax/tax.inc.php');
|
|
$taxObj = new tax;
|
|
|
|
$db = &DB();
|
|
|
|
if( is_array( $VAR ) ) {
|
|
$expire = time();
|
|
$rs = $db->Execute( sqlSelect($db, 'service', '*', " id = ::{$VAR['id']}:: AND active=1
|
|
AND type = 'domain' AND queue = 'none' AND
|
|
( domain_type = 'register' OR domain_type = 'transfer' OR domain_type = 'renew' ) AND
|
|
( suspend_billing = 0 OR suspend_billing IS NULL ) " ));
|
|
$service = $rs->fields;
|
|
} else {
|
|
$service = $VAR;
|
|
}
|
|
|
|
if(empty($service['id'])) {
|
|
global $C_debug;
|
|
$C_debug->alert("Unable to generate domain renweal invoice due to domain status.");
|
|
return false;
|
|
}
|
|
|
|
# Get the parent invoice details:
|
|
if(!empty($service['invoice_id'])) {
|
|
$rs = $db->Execute( sqlSelect($db, 'invoice', '*', " id = {$service['invoice_id']} ", "" ) );
|
|
$invoice = $rs->fields;
|
|
} else {
|
|
$invoice = false;
|
|
}
|
|
|
|
# Get the account details:
|
|
$rs = $db->Execute( sqlSelect($db, 'account', '*', " id = {$service['account_id']} ", "" ) );
|
|
$account = $rs->fields;
|
|
|
|
# Get the account price
|
|
include_once(PATH_MODULES.'host_tld/host_tld.inc.php');
|
|
$tldObj=new host_tld;
|
|
$tld_arr = $tldObj->price_tld_arr($service['domain_tld'], 'renew', false, false, false, $service['account_id']);
|
|
foreach($tld_arr as $term => $price) break;
|
|
|
|
# Calculate taxes:
|
|
$rs = $db->Execute($sql=sqlSelect($db,"host_tld","taxable","name = ::{$service['domain_tld']}::"));
|
|
if( $service['taxable'] || @$rs->fields['taxable'] ) {
|
|
$tax_arr = $taxObj->calculate($price, $account["country_id"], $account["state"]);
|
|
} else {
|
|
$tax_arr = false;
|
|
}
|
|
|
|
$total = $price;
|
|
|
|
$tax_amt = 0;
|
|
if(is_array($tax_arr)) {
|
|
foreach($tax_arr as $tx) {
|
|
$tax_amt += $tx['rate'];
|
|
}
|
|
$total += $tax_amt;
|
|
}
|
|
|
|
# calculate the dates
|
|
$expire = $service['domain_date_expire'] + ($term*86400);
|
|
$due_date = $service['domain_date_expire'] - (86400*3);
|
|
|
|
# Create the invoice
|
|
$id = sqlGenID( $db, "invoice" );
|
|
$insert = $db->Execute( $sql = sqlInsert($db, "invoice",
|
|
Array(
|
|
'date_orig' => time(),
|
|
'date_last' => time(),
|
|
'type' => 2,
|
|
'process_status' => 0,
|
|
'billing_status' => 0,
|
|
'suspend_billing' => 0,
|
|
'print_status' => 0,
|
|
'parent_id' => $service['invoice_id'],
|
|
'account_id' => $service['account_id'],
|
|
'account_billing_id'=> $service['account_billing_id'],
|
|
'affiliate_id' => @$invoice['affiliate_id'],
|
|
'campaign_id' => @$invoice['campaign_id'],
|
|
'reseller_id' => @$invoice['reseller_id'],
|
|
'checkout_plugin_id'=> @$invoice['checkout_plugin_id'],
|
|
'tax_amt' => $tax_amt,
|
|
'discount_arr' => serialize(@$discount_arr),
|
|
'discount_amt' => @$discount_amt,
|
|
'total_amt' => $total,
|
|
'billed_amt' => 0,
|
|
'billed_currency_id'=> DEFAULT_CURRENCY,
|
|
'actual_billed_amt' => 0,
|
|
'actual_billed_currency_id' => @$invoice['actual_billed_currency_id'],
|
|
'notice_count' => 0,
|
|
'notice_next_date' => time(),
|
|
'notice_max' => MAX_BILLING_NOTICE,
|
|
'grace_period' => 0,
|
|
'due_date' => $due_date
|
|
), $id ) ) ;
|
|
|
|
# create the invoice item:
|
|
if($insert) {
|
|
$db->Execute ( $idx = sqlInsert($db, "invoice_item",
|
|
Array(
|
|
'date_orig' => time(),
|
|
'invoice_id' => $id,
|
|
'account_id' => $service['account_id'],
|
|
'service_id' => $service['id'],
|
|
'sku' => 'DOMAIN-RENEW',
|
|
'quantity' => 1,
|
|
'item_type' => 2,
|
|
'price_type' => 0,
|
|
'price_base' => $price,
|
|
'price_setup' => 0,
|
|
'domain_type' => 'renew',
|
|
'date_start' => $service['domain_date_expire'],
|
|
'date_stop' => $expire,
|
|
'domain_name' => $service['domain_name'],
|
|
'domain_tld' => $service['domain_tld'],
|
|
'domain_term' => $term,
|
|
'tax_amt' => $tax_amt,
|
|
'total_amt' => $price
|
|
) ) );
|
|
|
|
# Insert tax records
|
|
$taxObj->invoice_item($id, $idx, $service['account_id'], @$item_tax_arr);
|
|
|
|
# Update the service record
|
|
$fields=Array('active' => 0);
|
|
$db->Execute(sqlUpdate($db,"service",$fields,"id = {$service['id']}"));
|
|
|
|
global $C_debug;
|
|
$C_debug->alert("Generated domain renewal invoice for {$service['domain_name']}.{$service['domain_tld']}");
|
|
return $id;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** Run AutoBilling and Due Notices
|
|
*/
|
|
function autobill($VAR)
|
|
{
|
|
global $VAR, $C_debug, $C_list;
|
|
|
|
# User invoice creation confirmation
|
|
include_once(PATH_MODULES.'email_template/email_template.inc.php');
|
|
$mail = new email_template;
|
|
|
|
# get all due invoices
|
|
$db = &DB();
|
|
#$db->debug = true;
|
|
|
|
if(empty($VAR['invoice_id']))
|
|
{
|
|
$this->bill_one = false;
|
|
$sql = 'SELECT * FROM ' . AGILE_DB_PREFIX . 'invoice
|
|
WHERE notice_next_date <= ' . $db->qstr( time() ) . '
|
|
AND (
|
|
billing_status = 0 OR
|
|
billing_status IS NULL
|
|
) AND (
|
|
suspend_billing = 0 OR
|
|
suspend_billing IS NULL
|
|
)
|
|
AND site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$invoice = $db->Execute($sql);
|
|
if($invoice->RecordCount() == 0) {
|
|
$C_debug->alert('No Invoices to Autobill');
|
|
return false;
|
|
}
|
|
} else {
|
|
# get the specified invoice:
|
|
$this->bill_one = true;
|
|
$sql = 'SELECT * FROM ' . AGILE_DB_PREFIX . 'invoice
|
|
WHERE (
|
|
billing_status = 0 OR
|
|
billing_status IS NULL
|
|
)
|
|
AND id = ' . $db->qstr($VAR['invoice_id']) . '
|
|
AND site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$invoice = $db->Execute($sql);
|
|
}
|
|
|
|
# Check for results
|
|
if($invoice->RecordCount() == 0) {
|
|
$C_debug->alert('Invoice could not be billed!');
|
|
return false;
|
|
}
|
|
|
|
# Loop through results
|
|
while(!$invoice->EOF)
|
|
{
|
|
$db->StartTrans();
|
|
|
|
$due = true;
|
|
|
|
# get currency code
|
|
$cyid = $invoice->fields['actual_billed_currency_id'];
|
|
$billed_currency_id = $invoice->fields['billed_currency_id'];
|
|
if(empty($this->currency_iso[$cyid]))
|
|
{
|
|
$q = "SELECT three_digit,convert_array FROM ". AGILE_DB_PREFIX ."currency WHERE
|
|
id = ". $db->qstr($cyid)." AND
|
|
site_id = ". $db->qstr(DEFAULT_SITE);
|
|
$currb = $db->Execute($q);
|
|
$this->format_currency[$cyid] = Array ( 'convert' => unserialize($currb->fields["convert_array"]),
|
|
'iso' => $currb->fields["three_digit"]);
|
|
}
|
|
|
|
# get the currency codes (default)
|
|
if(empty($this->format_currency[$billed_currency_id]))
|
|
{
|
|
# Get the billed currency id currency info:
|
|
$q = "SELECT three_digit,convert_array FROM ".AGILE_DB_PREFIX."currency WHERE
|
|
id = ".$db->qstr($billed_currency_id)." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$currb = $db->Execute($q);
|
|
$this->format_currency[$billed_currency_id] = Array ( 'convert' => unserialize($currb->fields["convert_array"]),
|
|
'iso' => $currb->fields["three_digit"]);
|
|
}
|
|
|
|
# attempt to autobill?
|
|
if(!empty( $invoice->fields['account_billing_id'] ))
|
|
{
|
|
# get checkout plugin details:
|
|
$billing =& $db->Execute($sql=sqlSelect($db, array('account_billing','checkout'), 'A.*,B.checkout_plugin',
|
|
"A.id = ::{$invoice->fields['account_billing_id']}:: AND A.checkout_plugin_id=B.id"));
|
|
|
|
if($billing && $billing->RecordCount() == 1 && !empty($billing->fields['checkout_plugin'])) {
|
|
$plugin_file = PATH_PLUGINS.'checkout/'. $billing->fields['checkout_plugin'] .'.php';
|
|
if(!is_file($plugin_file)) {
|
|
$err = $plugin_file .' missing when autobilling invoice id ' . $invoice->fields['id'];
|
|
$C_debug->error('invoice.inc.php','autobill()', $err);
|
|
} else {
|
|
include_once ( $plugin_file );
|
|
eval( '$PLG = new plg_chout_' . $billing->fields['checkout_plugin'] . '("'.$billing->fields['checkout_plugin_id'].'");');
|
|
}
|
|
} else {
|
|
$err = 'account_billing.id '.$invoice->fields['account_billing_id'].' empty or not associated with a checkout plugin when autobilling invoice id ' . $invoice->fields['id'];
|
|
$C_debug->error('invoice.inc.php','autobill()', $err);
|
|
}
|
|
}
|
|
|
|
# get the actual billed amount
|
|
$amount = $invoice->fields['total_amt'] - $invoice->fields['billed_amt'];
|
|
$billed_amt = $invoice->fields['total_amt'];
|
|
$actual_billed_amt = $invoice->fields['total_amt'];
|
|
if($amount <= 0) $due = false;
|
|
|
|
if(!empty($PLG) && is_object($PLG) && $PLG->type == 'gateway' && $amount > 0)
|
|
{
|
|
# attempt autobilling if account billing exists and gateway plugin
|
|
if($invoice->fields['account_billing_id'] > 0 )
|
|
{
|
|
/* get the account details */
|
|
$account = $db->Execute(sqlSelect($db,"account","id,email","id=::{$invoice->fields['account_id']}"));
|
|
|
|
/* Convert the invoice amount to the actual billed currency amount */
|
|
if($cyid != $invoice->fields['billed_currency_id']) {
|
|
$conversion = $this->format_currency[$billed_currency_id]["convert"][$cyid]["rate"];
|
|
$amount *= $conversion;
|
|
$actual_billed_amt = $invoice->fields['actual_billed_amt'] + $amount;
|
|
}
|
|
|
|
/* load the billing details from the database */
|
|
$PLG->setBillingFromDBObj($billing, true);
|
|
|
|
/* attempt to auto-bill */
|
|
if(!$checkout_plugin_data = $PLG->bill_checkout( number_format($amount,2), $invoice->fields['id'], $this->format_currency[$cyid]['iso'], $account->fields, 0,0) ) {
|
|
$due = true;
|
|
$email = new email_template;
|
|
$email->send('invoice_decline_user', $invoice->fields['account_id'], $invoice->fields['id'],$C_list->format_currency($invoice->fields['total_amt'],$cyid), $C_list->date($invoice->fields['due_date']));
|
|
$email = new email_template;
|
|
$email->send('admin->invoice_decline_admin', $invoice->fields['account_id'], $invoice->fields['id'], $C_list->format_currency($invoice->fields['total_amt'],''), $C_list->date($invoice->fields['due_date']));
|
|
} else {
|
|
$due = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
# send proper alert & manage services
|
|
if ($due)
|
|
{
|
|
# determine if overdue
|
|
$due = $invoice->fields['due_date'];
|
|
$grace = $invoice->fields['grace_period'];
|
|
if(time() < $due+(86400*$grace))
|
|
{
|
|
if($invoice->fields['notice_count'] <= 0)
|
|
{
|
|
# send out first alert - new invoice created!
|
|
$email = new email_template;
|
|
$email->send('invoice_recur_user', $invoice->fields['account_id'], $invoice->fields['id'], $C_list->format_currency($invoice->fields['total_amt'],$cyid), $C_list->date($invoice->fields['due_date']));
|
|
$email = new email_template;
|
|
$email->send('admin->invoice_recur_admin', $invoice->fields['account_id'], $invoice->fields['id'], $C_list->format_currency($invoice->fields['total_amt'],''), $C_list->date($invoice->fields['due_date']));
|
|
}
|
|
else
|
|
{
|
|
# send out payment due notice
|
|
if(empty($PLG) || $PLG->type == 'gateway') {
|
|
$email = new email_template;
|
|
$email->send('invoice_due_user', $invoice->fields['account_id'], $invoice->fields['id'], $this->format_currency[$cyid]["iso"], $C_list->date($invoice->fields['due_date']));
|
|
$email = new email_template;
|
|
$email->send('admin->invoice_due_admin', $invoice->fields['account_id'], $invoice->fields['id'], $this->format_currency[$billed_currency_id]["iso"], $C_list->date($invoice->fields['due_date']));
|
|
}
|
|
elseif($PLG->type == 'redirect') {
|
|
$email = new email_template;
|
|
$email->send('invoice_due_user', $invoice->fields['account_id'], $invoice->fields['id'], $this->format_currency[$cyid]["iso"], $C_list->date($invoice->fields['due_date']));
|
|
} elseif ($PLG->type == 'other') {
|
|
$email = new email_template;
|
|
$email->send('admin->invoice_due_admin', $invoice->fields['account_id'], $invoice->fields['id'], $this->format_currency[$billed_currency_id]["iso"], $C_list->date($invoice->fields['due_date']));
|
|
}
|
|
}
|
|
|
|
# increment notice counter
|
|
$sql = 'UPDATE ' . AGILE_DB_PREFIX . 'invoice SET
|
|
notice_count = ' . $db->qstr($invoice->fields['notice_count']+1) . ',
|
|
notice_next_date = ' . $db->qstr(time()+86400*3) . '
|
|
WHERE
|
|
id = ' . $db->qstr( $invoice->fields['id'] ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$db->Execute($sql);
|
|
}
|
|
else
|
|
{
|
|
# send service cancelation notice
|
|
$email = new email_template;
|
|
$email->send('service_suspend_user', $invoice->fields['account_id'], $invoice->fields['id'], $C_list->format_currency($invoice->fields['total_amt'],$cyid), $C_list->date($invoice->fields['due_date']));
|
|
$email = new email_template;
|
|
$email->send('admin->service_suspend_admin', $invoice->fields['account_id'], $invoice->fields['id'], $C_list->format_currency($invoice->fields['total_amt'],''), $C_list->date($invoice->fields['due_date']));
|
|
|
|
# overdue - cancel services
|
|
$vara['id'] = $invoice->fields['id'];
|
|
$this->voidInvoice($vara, $this);
|
|
|
|
# suspend billing activity
|
|
$sql = 'UPDATE ' . AGILE_DB_PREFIX . 'invoice SET
|
|
notice_count = ' . $db->qstr($invoice->fields['notice_count']+1) . ',
|
|
suspend_billing = ' . $db->qstr('1') . '
|
|
WHERE
|
|
id = ' . $db->qstr( $invoice->fields['id'] ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$db->Execute($sql);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# update billing stauts
|
|
$sql = 'UPDATE ' . AGILE_DB_PREFIX . 'invoice SET
|
|
notice_count = ' . $db->qstr($invoice->fields['notice_count']+1) . ',
|
|
billing_status = ' . $db->qstr('1') . ',
|
|
billed_amt = ' . $db->qstr($billed_amt) . ',
|
|
actual_billed_amt = ' . $db->qstr($actual_billed_amt) . '
|
|
WHERE
|
|
id = ' . $db->qstr( $invoice->fields['id'] ) . ' AND
|
|
site_id = ' . $db->qstr(DEFAULT_SITE);
|
|
$db->Execute($sql);
|
|
|
|
# update invoice via autoapproveInvoice
|
|
$this->autoApproveInvoice($invoice->fields['id']);
|
|
|
|
# User alert of payment processed
|
|
$email = new email_template;
|
|
$email->send('invoice_paid_user', $invoice->fields['account_id'], $invoice->fields['id'], $this->format_currency[$cyid]['iso'], '');
|
|
|
|
# Admin alert of payment processed
|
|
$email = new email_template;
|
|
$email->send('admin->invoice_paid_admin', $invoice->fields['account_id'], $invoice->fields['id'], $this->format_currency[$billed_currency_id]['iso'], '');
|
|
}
|
|
$invoice->MoveNext();
|
|
unset($PLG);
|
|
|
|
/* finish transaction */
|
|
$db->CompleteTrans();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Find out if a user has unpaid invoices
|
|
*/
|
|
function has_unpaid($VAR) {
|
|
if(!SESS_LOGGED) return false;
|
|
$db=&DB();
|
|
$inv=$db->Execute($sql=sqlSelect($db,"invoice","SUM(total_amt-billed_amt) as total",
|
|
"account_id=".SESS_ACCOUNT." AND billing_status=0 AND refund_status=0"));
|
|
if($inv && $inv->RecordCount() && $inv->fields['total']>0) {
|
|
global $smarty, $C_list;
|
|
//$act= $db->Execute(sqlSelect($db,"account","currency_id","id=));
|
|
$smarty->assign('has_unpaid', $C_list->format_currency_num($inv->fields['total'],SESS_CURRENCY));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the totals for multiple invoices or for a group of invoices stored in temp
|
|
*/
|
|
function multiple_invoice_total($invoice,$account_id=SESS_ACCOUNT)
|
|
{
|
|
$db = &DB();
|
|
if(empty($invoice) || eregi(",", $invoice)) {
|
|
$id_list='';
|
|
if(!empty($invoice)) {
|
|
$id = split(',', $invoice);
|
|
for($i=0; $i<count($id); $i++) {
|
|
if($id[$i] != '') {
|
|
if($i == 0) {
|
|
$id_list .= " id = " .$db->qstr($id[$i])." ";
|
|
$ii++;
|
|
} else {
|
|
$id_list .= " OR id = " .$db->qstr($id[$i]). " ";
|
|
$ii++;
|
|
}
|
|
}
|
|
}
|
|
if(!empty($id_list)) $id_list = "( $id_list ) AND ";
|
|
}
|
|
// get invoice totals
|
|
$total=0;
|
|
$inv=$db->Execute($sql=sqlSelect($db,"invoice","id,total_amt,billed_amt", "$id_list account_id=".SESS_ACCOUNT." AND billing_status=0 AND refund_status=0"));
|
|
if($inv && $inv->RecordCount()) {
|
|
while(!$inv->EOF) {
|
|
$this->invoice[] = $inv->fields['id'];
|
|
$total += ($inv->fields['total_amt']-$inv->fields['billed_amt']);
|
|
$inv->MoveNext();
|
|
}
|
|
return $total;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
// get total from temp data
|
|
$inv=$db->Execute($sql=sqlSelect($db,"temporary_data","data,field1 as total","field2=::$invoice::"));
|
|
if($inv && $inv->RecordCount() && $inv->fields['total'] > 0) {
|
|
if(!empty($inv->fields['field2'])) $this->invoice=unserialize($inv->fields['data']);
|
|
return $inv->fields['total'];
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Preview checkout of multiple invoices
|
|
*/
|
|
function checkout_multiple_preview($VAR)
|
|
{
|
|
global $smarty,$C_list;
|
|
if(!SESS_LOGGED) return false;
|
|
|
|
$db=&DB();
|
|
$total = $this->multiple_invoice_total(@$VAR['id'],SESS_ACCOUNT);
|
|
if($total > 0 && count($this->invoice) > 1)
|
|
{
|
|
// get country id for checkout options
|
|
$account=sqlSelect($db, "account", "country_id", "id=".SESS_ACCOUNT);
|
|
|
|
// get payment options
|
|
include_once(PATH_MODULES.'checkout/checkout.inc.php');
|
|
$checkout = new checkout;
|
|
$checkoutoptions = $checkout->get_checkout_options(SESS_ACCOUNT, $total, false, $account->fields['country_id'],true);
|
|
|
|
// get a temporary id (48 hours)
|
|
$id=sqlGenID($db, "temporary_data");
|
|
$invoice["id"] = "MULTI-$id";
|
|
$invoice["total"] = $total;
|
|
$fields=Array('date_orig'=>time(), 'date_expire'=>time()+86400*3, 'field2'=> $invoice['id'], 'field1'=>$total, 'data'=>serialize($this->invoice));
|
|
$id = & $db->Execute(sqlInsert($db,"temporary_data",$fields));
|
|
|
|
$smarty->assign('invoice', $invoice);
|
|
$smarty->assign('total', $C_list->format_currency_num($total,SESS_CURRENCY));
|
|
$smarty->assign('checkoutoptions', $checkoutoptions);
|
|
|
|
} elseif (count($this->invoice) == 1) {
|
|
$id = $this->invoice[0];
|
|
echo "<script language=javascript>document.location.href='?_page=invoice:user_view&id=".$id."';</script>";
|
|
} else {
|
|
echo "No due invoices selected for payment.";
|
|
}
|
|
}
|
|
|
|
|
|
/** Run checkout plugin for billing
|
|
*/
|
|
function checkoutnow($VAR)
|
|
{
|
|
global $C_translate, $smarty, $C_list, $VAR;
|
|
|
|
# Validate user logged in:
|
|
if(SESS_LOGGED != '1') {
|
|
echo '<script language="JavaScript">alert("You must be logged in to complete this purchase! Please refresh this page in your browser to login now...");</script>';
|
|
return false;
|
|
}
|
|
|
|
$db = &DB();
|
|
if(eregi("MULTI-", @$VAR['invoice_id'])) {
|
|
// get multi-invoice details
|
|
$total = $this->multiple_invoice_total(@$VAR['invoice_id'],SESS_ACCOUNT);
|
|
if(!$total) return false;
|
|
$recur_amt=false;
|
|
$recur_arr=false;
|
|
$account_id=SESS_ACCOUNT;
|
|
$this->invoice[]=$VAR['invoice_id'];
|
|
$this->invoice_id=$VAR['invoice_id'];
|
|
$CURRENCY = DEFAULT_CURRENCY;
|
|
$multi=true;
|
|
} else {
|
|
# Validate the invoice selected, & get the totals:
|
|
$sql = 'SELECT * FROM ' . AGILE_DB_PREFIX . 'invoice WHERE site_id = '.$db->qstr(DEFAULT_SITE).' AND id = ' . $db->qstr($VAR['invoice_id']);
|
|
$result = $db->Execute($sql);
|
|
if(!$result || $result->RecordCount() == 0) return false;
|
|
|
|
# Determine the price & currency
|
|
if($result->fields['billed_currency_id'] != $result->fields['actual_billed_currency_id']) {
|
|
global $C_list;
|
|
$CURRENCY = $result->fields['actual_billed_currency_id'];
|
|
if($result->fields['billed_amt'] <= 0)
|
|
$total = $C_list->format_currency_decimal ($result->fields['total_amt'], $CURRENCY);
|
|
else
|
|
$total = $C_list->format_currency_decimal ($result->fields['total_amt'], $CURRENCY) - $result->fields['actual_billed_amt'];
|
|
} else {
|
|
$CURRENCY = $result->fields['billed_currency_id'];
|
|
$total = $result->fields['total_amt']-$result->fields['billed_amt'];
|
|
}
|
|
$recur_amt=$result->fields['recur_amt'];
|
|
if($recur_amt>0) $recur_amt = $C_list->format_currency_decimal ($recur_amt, $CURRENCY);
|
|
@$recur_arr=unserialize($result->fields['recur_arr']);
|
|
$account_id=$result->fields['account_id'];
|
|
$this->invoice_id=$result->fields['id'];
|
|
$this->invoice[]=$result->fields['id'];
|
|
$multi=false;
|
|
}
|
|
$amount = round($total, 2);
|
|
|
|
# Get the account details:
|
|
$sql = 'SELECT * FROM ' . AGILE_DB_PREFIX . 'account WHERE site_id = ' . $db->qstr(DEFAULT_SITE) . ' AND id = ' . $db->qstr($account_id);
|
|
$account = $db->Execute($sql);
|
|
if (!$account || !$account->RecordCount()) return false;
|
|
|
|
# Validate checkout option selected is allowed for purchase:
|
|
$q = "SELECT * FROM ".AGILE_DB_PREFIX."checkout WHERE site_id = ".$db->qstr(DEFAULT_SITE)." AND id = ".$db->qstr(@$VAR['option'])." AND active = 1 AND ";
|
|
if($recur_amt>0 && @$billed_amt == 0 ) $q .= "allow_recurring = 1 "; else $q .= "allow_new = 1 ";
|
|
$chopt = $db->Execute($q);
|
|
if (!$chopt || !$chopt->RecordCount()) return false;
|
|
if($chopt && $chopt->RecordCount()) {
|
|
$show = true;
|
|
if ( @$chopt->fields["total_maximum"] != "" && $total > $chopt->fields["total_maximum"] ) $show = false;
|
|
if ( @$chopt->fields["total_miniumum"] != "" && $total < $chopt->fields["total_miniumum"] ) $show = false;
|
|
}
|
|
if(!$show) {
|
|
echo '<script language=Javascript> alert("Unable to checkout with the selected method, please select another."); </script> ';
|
|
return false;
|
|
}
|
|
|
|
# Load the checkout plugin:
|
|
$plugin_file = PATH_PLUGINS . 'checkout/'. $chopt->fields["checkout_plugin"] . '.php';
|
|
include_once ( $plugin_file );
|
|
eval ( '$PLG = new plg_chout_' . $chopt->fields["checkout_plugin"] . '("'.@$VAR["option"].'");');
|
|
|
|
if(!empty($VAR['account_billing_id']) && @$VAR['new_card']==2) {
|
|
/* validate credit card on file details */
|
|
$account_billing_id=$VAR['account_billing_id'];
|
|
if(!$PLG->setBillingFromDB($account_id, $account_billing_id, $VAR['option'])) {
|
|
global $C_debug;
|
|
$C_debug->alert("Sorry, we cannot use that billing record for this purchase.");
|
|
return false;
|
|
}
|
|
} else {
|
|
/* use passed in vars */
|
|
$PLG->setBillingFromParams($VAR);
|
|
}
|
|
|
|
# Set Invoice Vars:
|
|
$this->total_amt = $amount;
|
|
$this->currency_iso = $C_list->currency_iso($CURRENCY);
|
|
$this->currency_iso_admin = $C_list->currency_iso($CURRENCY);
|
|
$this->account_id = $account_id;
|
|
$this->actual_billed_currency_id = $CURRENCY;
|
|
$this->billed_currency_id = $CURRENCY;
|
|
$this->checkout_plugin_id = @$VAR["option"];
|
|
|
|
# Run the plugin bill_checkout() method:
|
|
$this->checkout_plugin_data = $PLG->bill_checkout( $amount, $this->invoice_id, $this->currency_iso, $account->fields, $recur_amt, $recur_arr);
|
|
|
|
# redirect
|
|
if(!empty($this->checkout_plugin_data['redirect'])) echo $this->checkout_plugin_data['redirect'];
|
|
|
|
# determine results
|
|
if( $this->checkout_plugin_data === false ) {
|
|
if(!empty($PLG->redirect)) echo $PLG->redirect;
|
|
return false;
|
|
} elseif ($PLG->type == "gateway" && empty($PLG->redirect)) {
|
|
if(empty($this->admin_checkout)) {
|
|
$VAR['_page'] = "invoice:thankyou";
|
|
} else {
|
|
$VAR['_page'] = "invoice:view";
|
|
}
|
|
} elseif ($PLG->type == "redirect") {
|
|
echo "<html><head></head><body><center>
|
|
Please wait while we redirect you to the secure payment site....
|
|
{$PLG->redirect}</center></body></html>";
|
|
}
|
|
|
|
# Call the Plugin method for storing the checkout data, if new data entered:
|
|
$this->account_billing_id = $PLG->store_billing($VAR, $PLG);
|
|
|
|
# Load the email template module
|
|
include_once(PATH_MODULES.'email_template/email_template.inc.php');
|
|
$mail = new email_template;
|
|
|
|
# Update billing details for this invoice, if realtime billing succeeded:
|
|
if($PLG->type == 'gateway' || $amount == 0) {
|
|
$q = "UPDATE ".AGILE_DB_PREFIX."invoice
|
|
SET
|
|
account_billing_id = " .$db->qstr($this->account_billing_id). ",
|
|
billing_status = " .$db->qstr(1). ",
|
|
billed_amt = " .$db->qstr($total). ",
|
|
actual_billed_amt = " .$db->qstr($amount). ",
|
|
date_last = " .$db->qstr(time()). ",
|
|
checkout_plugin_id = " .$db->qstr($this->checkout_plugin_id) .",
|
|
checkout_plugin_data = " .$db->qstr(serialize($this->checkout_plugin_data)). "
|
|
WHERE
|
|
site_id = ".$db->qstr(DEFAULT_SITE)." AND
|
|
id = ".$db->qstr($this->invoice_id);
|
|
$rst = $db->Execute($q);
|
|
if ($rst === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','checkoutnow', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
|
|
// loop through each invoice paid
|
|
foreach($this->invoice as $this->invoice_id) {
|
|
# Send billed e-mail notice to user
|
|
$email = new email_template;
|
|
$email->send('invoice_paid_user', $this->account_id, $this->invoice_id, $this->currency_iso, '');
|
|
|
|
# Admin alert of payment processed
|
|
$email = new email_template;
|
|
$email->send('admin->invoice_paid_admin', $this->account_id, $this->invoice_id, $this->currency_iso_admin, '');
|
|
|
|
# Submit the invoice for approval
|
|
$arr['id'] = $this->invoice_id;
|
|
$this->approveInvoice($arr, $this);
|
|
}
|
|
|
|
} else {
|
|
|
|
# Just update the last_date and plugin data
|
|
$q = "UPDATE ".AGILE_DB_PREFIX."invoice
|
|
SET
|
|
account_billing_id = " .$db->qstr($this->account_billing_id). ",
|
|
date_last = " .$db->qstr(time()). ",
|
|
checkout_plugin_id = " .$db->qstr($this->checkout_plugin_id) .",
|
|
checkout_plugin_data = " .$db->qstr(serialize($this->checkout_plugin_data)). "
|
|
WHERE
|
|
site_id = ".$db->qstr(DEFAULT_SITE)." AND
|
|
id = ".$db->qstr($this->invoice_id);
|
|
$rst = $db->Execute($q);
|
|
if ($rst === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','checkoutnow', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
|
|
# Admin e-mail alert of manual payment processing
|
|
if ( $PLG->name == 'MANUAL' ) {
|
|
$date_due = $C_list->date(time());
|
|
foreach($this->invoice as $this->invoice_id) {
|
|
$email = new email_template;
|
|
$email->send('admin->invoice_due_admin', $this->account_id, $this->invoice_id, '', $date_due);
|
|
}
|
|
|
|
global $C_debug;
|
|
$C_debug->alert($C_translate->translate('manual_alert','checkout'));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/** create modified array for invoice summarization
|
|
*/
|
|
function summarizeLineItems($smart_items)
|
|
{
|
|
//$ignore['SKU']=true;
|
|
$sum=false;
|
|
if(is_array($smart_items)) {
|
|
foreach($smart_items as $it) {
|
|
if(empty($sum["{$it["sku"]}"])) {
|
|
// unique line item
|
|
if(empty($ignore["{$it["sku"]}"])) $sum["{$it["sku"]}"][] = $it;
|
|
} else {
|
|
// is unique price/attributes?
|
|
$unique=true;
|
|
foreach($sum["{$it["sku"]}"] as $sid => $flds) {
|
|
if( $flds["price_base"] == $it["price_base"] && $flds["price_setup"] == $it["price_setup"] && $flds['product_attr'] == $it['product_attr'] ) {
|
|
$sum["{$it["sku"]}"]["$sid"]["quantity"] += 1;
|
|
$unique = false;
|
|
break;
|
|
}
|
|
}
|
|
// unique line item
|
|
if($unique) $sum["{$it["sku"]}"][] = $it;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!empty($sum)) {
|
|
unset($smart_items);
|
|
foreach($sum as $sku => $item) foreach($item as $sitem) $smart_items[] = $sitem;
|
|
return $smart_items;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** VIEW
|
|
*/
|
|
function view($VAR)
|
|
{
|
|
global $C_translate, $C_list;
|
|
$this->invoice_construct();
|
|
$type = "view";
|
|
$this->method["$type"] = split(",", $this->method["$type"]);
|
|
|
|
$db = &DB();
|
|
|
|
# set the field list for this method:
|
|
$arr = $this->method[$type];
|
|
|
|
# loop through the field list to create the sql queries
|
|
$field_list = '';
|
|
$i=0;
|
|
while (list ($key, $value) = each ($arr))
|
|
{
|
|
if($i == 0)
|
|
{
|
|
$field_var = $this->table . '_' . $value;
|
|
$field_list .= $value;
|
|
}
|
|
else
|
|
{
|
|
$field_var = $this->table . '_' . $value;
|
|
$field_list .= "," . $value;
|
|
}
|
|
$i++;
|
|
}
|
|
|
|
if(isset($VAR["id"]))
|
|
{
|
|
$id = split(',',$VAR["id"]);
|
|
for($i=0; $i<count($id); $i++)
|
|
{
|
|
if($id[$i] != '')
|
|
{
|
|
if($i == 0)
|
|
{
|
|
$id_list .= " id = " .$db->qstr($id[$i])." ";
|
|
$ii++;
|
|
}
|
|
else
|
|
{
|
|
$id_list .= " OR id = " .$db->qstr($id[$i]). " ";
|
|
$ii++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if($ii>0)
|
|
{
|
|
$any_trial = false;
|
|
$any_recurring = false;
|
|
$any_new = false;
|
|
|
|
# generate the full query
|
|
$q = "SELECT
|
|
$field_list
|
|
FROM
|
|
".AGILE_DB_PREFIX."$this->table
|
|
WHERE
|
|
$id_list
|
|
AND site_id = '" . DEFAULT_SITE . "'
|
|
ORDER BY $this->order_by
|
|
LIMIT 0,1";
|
|
$result = $db->Execute($q);
|
|
if ($result === false)
|
|
{
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','view', $db->ErrorMsg());
|
|
|
|
if(isset($this->trigger["$type"]))
|
|
{
|
|
include_once(PATH_CORE . 'trigger.inc.php');
|
|
$trigger = new CORE_trigger;
|
|
$trigger->trigger($this->trigger["$type"], 0, $VAR);
|
|
}
|
|
return;
|
|
}
|
|
|
|
### Set it as a class variable:
|
|
$this->result = $result;
|
|
|
|
# put the results into a smarty accessable array
|
|
$i=0;
|
|
$ii=0;
|
|
$class_name = TRUE;
|
|
while (!$result->EOF)
|
|
{
|
|
$smart[$i] = $result->fields;
|
|
|
|
## get the product plugin name
|
|
if(!empty($result->fields['checkout_plugin_id'])) {
|
|
$cplg = $db->Execute(sqlSelect($db,"checkout","name","id = {$result->fields['checkout_plugin_id']}"));
|
|
if($cplg && $cplg->RecordCount()) $smart[$i]['checkout_plugin'] = $cplg->fields['name'];
|
|
}
|
|
|
|
if($result->fields['total_amt'] == 0)
|
|
$smart[$i]['balance'] = 0;
|
|
else
|
|
$smart[$i]['balance'] = $result->fields['total_amt'] - $result->fields['billed_amt'];
|
|
|
|
## Get the tax details
|
|
if( !empty($result->fields['tax_amt']) ) {
|
|
$trs = $db->Execute($sql=sqlSelect($db, Array('invoice_item_tax','tax'),"A.amount,B.description","A.tax_id=B.id AND A.invoice_id={$result->fields['id']}"));
|
|
if($trs && $trs->RecordCount()) {
|
|
while(!$trs->EOF) {
|
|
$taxes["{$trs->fields['description']}"] += $trs->fields["amount"];
|
|
$trs->MoveNext();
|
|
}
|
|
foreach($taxes as $txds=>$txamt)
|
|
$smart[$i]["tax_arr"][] = Array('description'=>$txds, 'amount'=>$txamt);
|
|
}
|
|
}
|
|
|
|
## Get the discount details
|
|
if( !empty($result->fields['discount_amt']) ) {
|
|
$drs = $db->Execute($sql=sqlSelect($db, 'invoice_item_discount',"amount,discount","invoice_id={$result->fields['id']}"));
|
|
if($drs && $drs->RecordCount()) {
|
|
while(!$drs->EOF) {
|
|
$discounts["{$drs->fields['discount']}"] += $drs->fields["amount"];
|
|
$drs->MoveNext();
|
|
}
|
|
$dhtml='';
|
|
foreach($discounts as $dsds=>$dsamt) $dhtml .= '<a href=\'?_page=core:search&module=discount&discount_name='.$dsds.'\'>'.$dsds.'</a> - '. number_format($dsamt, 2) . "<br>";
|
|
$smart[$i]['discount_popup'] = $dhtml;
|
|
$dhtml='';
|
|
foreach($discounts as $dsds=>$dsamt) $dhtml .= $dsds.' - '. number_format($dsamt, 2) . "<br>";
|
|
$smart[$i]['discount_popup_user'] = $dhtml;
|
|
|
|
}
|
|
}
|
|
|
|
## Get the checkout plugin details:
|
|
if(!empty($result->fields['checkout_plugin_data'])) {
|
|
$plugin_data = unserialize($result->fields['checkout_plugin_data']);
|
|
if(is_array($plugin_data)) {
|
|
$smart[$i]['checkout_plugin_data'] = $plugin_data;
|
|
} else {
|
|
$smart[$i]['checkout_plugin_data'] = Array(0 => $result->fields['checkout_plugin_data']);
|
|
}
|
|
}
|
|
|
|
## Get the line items:
|
|
$q = "SELECT * FROM ".AGILE_DB_PREFIX."invoice_item WHERE
|
|
invoice_id = ". $db->qstr($result->fields['id'])." AND
|
|
site_id = ". $db->qstr(DEFAULT_SITE);
|
|
if($C_list->is_installed('voip')) {
|
|
$q .= " AND item_type!=5";
|
|
}
|
|
$items = $db->Execute($q);
|
|
if ($items === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','view', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
$ii =0;
|
|
while ( !$items->EOF )
|
|
{
|
|
$smart_items[$ii] = $items->fields;
|
|
|
|
// get the product attribs
|
|
if(!empty($items->fields['product_attr']))
|
|
{
|
|
@$attrib = explode("\r\n", $items->fields['product_attr']);
|
|
$js='';
|
|
for($attr_i = 0; $attr_i < count( $attrib ); $attr_i++)
|
|
{
|
|
$attributei = explode('==', $attrib[$attr_i]);
|
|
if(!empty($attributei[0]) && !empty($attributei[1])) {
|
|
$js .= "<u>" . $attributei[0] . "</u> : ". $attributei[1] . " <BR>";
|
|
}
|
|
}
|
|
$smart_items[$ii]['attribute_popup'] = $js;
|
|
}
|
|
|
|
// get the date range if set
|
|
if(!empty($items->fields['date_start']) && !empty($items->fields['date_stop']))
|
|
{
|
|
$C_translate->value('invoice','start', date(UNIX_DATE_FORMAT,$items->fields['date_start']));
|
|
$C_translate->value('invoice','stop', date(UNIX_DATE_FORMAT,$items->fields['date_stop']));
|
|
$smart_items[$ii]['range'] = $C_translate->translate('recur_date_range','invoice','');
|
|
}
|
|
|
|
// Set charge type for payment option list:
|
|
$any_new = true;
|
|
if ($items->fields["price_type"] == '1' && !empty($result->fields['recurr_arr']) && is_array(unserialize($result->fields['recurr_arr'])))
|
|
$any_recurring = true;
|
|
$items->MoveNext();
|
|
$ii++;
|
|
}
|
|
|
|
## Create a summary (for duplicate skus w/identical price,and attributes, roll into a single value
|
|
if($this->summarizeInvoice) {
|
|
$tmp = $smart_items;
|
|
unset($smart_items);
|
|
$smart_items = $this->summarizeLineItems($tmp);
|
|
}
|
|
|
|
### GET THE CHECKOUT (PAYMENT) OPTIONS
|
|
if($VAR['_page'] != 'invoice:view')
|
|
{
|
|
# get the converted amount due:
|
|
if($result->fields['billed_currency_id'] != $result->fields['actual_billed_currency_id'])
|
|
{
|
|
global $C_list;
|
|
$CURRENCY = $result->fields['actual_billed_currency_id'];
|
|
if($result->fields['billed_amt'] <= 0)
|
|
$total = $C_list->format_currency_decimal ($result->fields['total_amt'], $CURRENCY);
|
|
else
|
|
$total = $C_list->format_currency_decimal ($result->fields['total_amt'], $CURRENCY) - $result->fields['actual_billed_amt'];
|
|
} else {
|
|
$CURRENCY = $result->fields['billed_currency_id'];
|
|
$total = $result->fields['total_amt']-$result->fields['billed_amt'];
|
|
}
|
|
|
|
$q = "SELECT * FROM ".AGILE_DB_PREFIX."checkout WHERE site_id = ". DEFAULT_SITE ." AND active = 1";
|
|
if($any_trial) $q .= " AND allow_trial = ".$db->qstr('1');
|
|
if($any_recurring) $q .= " AND allow_recurring = ".$db->qstr('1');
|
|
if($any_new) $q .= " AND allow_new = ".$db->qstr('1');
|
|
$chopt = $db->Execute($q);
|
|
if ($chopt === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','view', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
if($chopt != false && $chopt->RecordCount() > 0) {
|
|
while( !$chopt->EOF ) {
|
|
$show = true;
|
|
|
|
# Check that the cart total is not to high:
|
|
if ( $chopt->fields["total_maximum"] != "" &&
|
|
$result->fields['total_amt'] >= $chopt->fields["total_maximum"] ) {
|
|
$show = false;
|
|
}
|
|
|
|
# Check that the cart total is not to low:
|
|
if ( $chopt->fields["total_miniumum"] != "" &&
|
|
$result->fields['total_amt'] <= $chopt->fields["total_miniumum"] ) {
|
|
$show = false;
|
|
}
|
|
|
|
# Check that the group requirement is met:
|
|
if ( $show && !empty ( $chopt->fields["required_groups"] ) ) {
|
|
global $C_auth;
|
|
$arr = unserialize ( $chopt->fields["required_groups"] );
|
|
if(count($arr) > 0 && !empty($arr[0])) $show = false;
|
|
for ( $i=0; $i<count($arr); $i++ ) {
|
|
if($C_auth->auth_group_by_id($arr[$i])) {
|
|
$show = true;
|
|
$i=count($arr);
|
|
}
|
|
}
|
|
}
|
|
|
|
# Check that the customer is not ordering a blocked SKU:
|
|
if ( $show && !empty ( $chopt->fields["excluded_products"] ) ) {
|
|
$arr = unserialize ( $chopt->fields["excluded_products"] );
|
|
if(count($arr) > 0) {
|
|
for($i=0; $i<count($smart_items); $i++) {
|
|
for($isk=0; $isk<count($arr); $isk++) {
|
|
if($smart_items[$i]['product_id'] == $arr[$isk] && !empty($arr[$isk]) && !empty($smart_items[$i]['product_id']) ) {
|
|
$show = false;
|
|
$i=count($smart);
|
|
$isk=count($arr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
$list_ord = 100;
|
|
if ( $show ) {
|
|
|
|
# Check if this method should be the default method:
|
|
# By Amount:
|
|
if ( !empty ( $chopt->fields["default_when_amount"] ) ) {
|
|
$arr = unserialize ( $chopt->fields["default_when_amount"] );
|
|
for ( $idx=0; $idx<count($arr); $idx++ ) {
|
|
if ( $total >= $arr[$idx] ) $list_ord--;
|
|
$idx=count($arr);
|
|
}
|
|
}
|
|
|
|
# By Currency
|
|
if ( !empty ( $chopt->fields["default_when_currency"] ) ) {
|
|
$arr = unserialize ( $chopt->fields["default_when_currency"] );
|
|
for ( $idx=0; $idx<count($arr); $idx++ ) {
|
|
if ( $CURRENCY == $arr[$idx] ) $list_ord--;
|
|
$idx=count($arr);
|
|
}
|
|
}
|
|
|
|
# By Group
|
|
if ( !empty ( $chopt->fields["default_when_group"] ) ) {
|
|
$arr = unserialize ( $chopt->fields["default_when_group"] );
|
|
global $C_auth;
|
|
for ( $idx=0; $idx<count($arr); $idx++ ) {
|
|
if ( $C_auth->auth_group_by_id( $arr[$idx] ) ) $list_ord--;
|
|
$idx=count($arr);
|
|
}
|
|
}
|
|
|
|
# By Country
|
|
if ( !empty ( $chopt->fields["default_when_country"] ) ) {
|
|
$arr = unserialize ( $chopt->fields["default_when_country"] );
|
|
for ( $idx=0; $idx<count($arr); $idx++ ) {
|
|
if ( $account->fields["country_id"] == $arr[$idx] ) $list_ord--;
|
|
$idx=count($arr);
|
|
}
|
|
}
|
|
|
|
# Add to the array
|
|
$checkout_optionsx[] = Array ('sort' => $list_ord,
|
|
'fields' => $chopt->fields);
|
|
}
|
|
$chopt->MoveNext();
|
|
}
|
|
|
|
# Sort the checkout_options array by the [fields] element
|
|
if(count($checkout_optionsx) > 0 ) {
|
|
foreach ( $checkout_optionsx as $key => $row )
|
|
$sort[$key] = $row["sort"];
|
|
array_multisort ( $sort, SORT_ASC, $checkout_optionsx );
|
|
}
|
|
}
|
|
}
|
|
|
|
$result->MoveNext();
|
|
$i++;
|
|
}
|
|
|
|
|
|
# get the result count:
|
|
$results = $result->RecordCount();
|
|
|
|
### No results:
|
|
if($result->RecordCount() == 0)
|
|
{
|
|
global $C_debug;
|
|
$C_debug->error("CORE:database.inc.php", "view()", "The selected record does not
|
|
exist any longer, or your account is not authorized to view it");
|
|
return;
|
|
}
|
|
|
|
# define the DB vars as a Smarty accessible block
|
|
global $smarty;
|
|
|
|
# define the results
|
|
$smarty->assign('cart', $smart_items);
|
|
$smarty->assign($this->table, $smart);
|
|
#$smarty->assign('results', $search->results);
|
|
$smarty->assign('checkoutoptions', $checkout_optionsx);
|
|
}
|
|
}
|
|
|
|
/** UPDATE
|
|
*/
|
|
function update($VAR)
|
|
{
|
|
$this->invoice_construct();
|
|
$type = "update";
|
|
$this->method["$type"] = split(",", $this->method["$type"]);
|
|
$db = new CORE_database;
|
|
$db->update($VAR, $this, $type);
|
|
}
|
|
|
|
/** DELETE
|
|
*/
|
|
function delete($VAR)
|
|
{
|
|
$this->invoice_construct();
|
|
$dbx = new CORE_database;
|
|
$db = &DB();
|
|
|
|
### Get the array
|
|
if(isset($VAR["delete_id"]))
|
|
$id = split(',', $VAR["delete_id"]);
|
|
elseif (isset($VAR["id"]))
|
|
$id = split(',', $VAR["id"]);
|
|
|
|
### Load the service module
|
|
include_once(PATH_MODULES.'service/service.inc.php');
|
|
$service = new service;
|
|
|
|
### Loop:
|
|
for($i=0; $i<count($id); $i++)
|
|
{
|
|
### Loop through all services for this invoice and delete:
|
|
$q = "SELECT * FROM ".AGILE_DB_PREFIX."service WHERE
|
|
invoice_id = ".$db->qstr( $id[$i] )." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);;
|
|
$rs = $db->Execute($q);
|
|
if ($rs === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','delete', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
if (@$rs->RecordCount() > 0) {
|
|
while ( !$rs->EOF ) {
|
|
$arr['id'] = $rs->fields['id'];
|
|
$service->delete($arr, $service);
|
|
$rs->MoveNext();
|
|
}
|
|
}
|
|
|
|
### Delete the service record
|
|
$arr['id'] = $id[$i];
|
|
$this->associated_DELETE[] = Array ('table' => 'invoice_commission', 'field' => 'invoice_id');
|
|
$this->associated_DELETE[] = Array ('table' => 'invoice_item', 'field' => 'invoice_id');
|
|
$this->associated_DELETE[] = Array ('table' => 'invoice_memo', 'field' => 'invoice_id');
|
|
$this->associated_DELETE[] = Array ('table' => 'service', 'field' => 'invoice_id');
|
|
$this->associated_DELETE[] = Array ('table' => 'invoice_item_tax', 'field' => 'invoice_id');
|
|
$this->associated_DELETE[] = Array ('table' => 'invoice_item_discount', 'field' => 'invoice_id');
|
|
$dbx->mass_delete($arr, $this, "");
|
|
}
|
|
}
|
|
|
|
/** SEARCH FORM
|
|
*/
|
|
function search_form($VAR)
|
|
{
|
|
$this->invoice_construct();
|
|
$type = "search";
|
|
$this->method["$type"] = split(",", $this->method["$type"]);
|
|
$db = new CORE_database;
|
|
$db->search_form($VAR, $this, $type);
|
|
}
|
|
|
|
/** SEARCH
|
|
*/
|
|
function search($VAR)
|
|
{
|
|
$this->invoice_construct();
|
|
$type = "search";
|
|
$this->method["$type"] = split(",", $this->method["$type"]);
|
|
|
|
$db = &DB();
|
|
|
|
include_once(PATH_CORE . 'validate.inc.php');
|
|
$validate = new CORE_validate;
|
|
|
|
# set the search criteria array
|
|
$arr = $VAR;
|
|
|
|
# convert invoice_discount_arr
|
|
if(!empty($VAR['invoice_discount_arr']))
|
|
$arr['invoice_discount_arr'] = '%"'.$VAR['invoice_discount_arr'].'"%';
|
|
|
|
|
|
# loop through the submitted field_names to get the WHERE statement
|
|
$where_list = '';
|
|
$i=0;
|
|
while (list ($key, $value) = each ($arr))
|
|
{
|
|
if($i == 0)
|
|
{
|
|
if($value != '')
|
|
{
|
|
$pat = "^" . $this->module . "_";
|
|
if(eregi($pat, $key))
|
|
{
|
|
$field = eregi_replace($pat,"",$key);
|
|
if(eregi('%',$value))
|
|
{
|
|
# do any data conversion for this field (date, encrypt, etc...)
|
|
if(isset($this->field["$field"]["convert"]) && $this->field["$field"]["convert"] != 'array')
|
|
{
|
|
$value = $validate->convert($field, $value, $this->field["$field"]["convert"]);
|
|
}
|
|
|
|
$where_list .= " WHERE ".AGILE_DB_PREFIX."invoice.".$field . " LIKE " . $db->qstr($value, get_magic_quotes_gpc());
|
|
$i++;
|
|
}
|
|
else
|
|
{
|
|
# check if array
|
|
if(is_array($value))
|
|
{
|
|
for($i_arr=0; $i_arr < count($value); $i_arr++)
|
|
{
|
|
if($value["$i_arr"] != '')
|
|
{
|
|
# determine any field options (=, >, <, etc...)
|
|
$f_opt = '=';
|
|
$pat_field = $this->module.'_'.$field;
|
|
$VAR['field_option']["$pat_field"]["$i_arr"];
|
|
if(isset($VAR['field_option']["$pat_field"]["$i_arr"]))
|
|
{
|
|
$f_opt = $VAR['field_option']["$pat_field"]["$i_arr"];
|
|
# error checking, safety precaution
|
|
if($f_opt != '=' && $f_opt != '>' && $f_opt != '<' && $f_opt != '>=' && $f_opt != '<=' && $f_opt != '!=')
|
|
$f_opt = '=';
|
|
}
|
|
|
|
# do any data conversion for this field (date, encrypt, etc...)
|
|
if(isset($this->field["$field"]["convert"]) && $this->field["$field"]["convert"] != 'array')
|
|
{
|
|
$value["$i_arr"] = $validate->convert($field, $value["$i_arr"], $this->field["$field"]["convert"]);
|
|
}
|
|
|
|
|
|
if($i_arr == 0)
|
|
{
|
|
$where_list .= " WHERE ".AGILE_DB_PREFIX."invoice.".$field . " $f_opt " . $db->qstr($value["$i_arr"], get_magic_quotes_gpc());
|
|
$i++;
|
|
}
|
|
else
|
|
{
|
|
$where_list .= " AND ".AGILE_DB_PREFIX."invoice.".$field . " $f_opt " . $db->qstr($value["$i_arr"], get_magic_quotes_gpc());
|
|
$i++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$where_list .= " WHERE ".AGILE_DB_PREFIX."invoice.".$field . " = " . $db->qstr($value, get_magic_quotes_gpc());
|
|
$i++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if($value != '')
|
|
{
|
|
$pat = "^" . $this->module . "_";
|
|
if(eregi($pat, $key))
|
|
{
|
|
$field = eregi_replace($pat,"",$key);
|
|
if(eregi('%',$value))
|
|
{
|
|
# do any data conversion for this field (date, encrypt, etc...)
|
|
if(isset($this->field["$field"]["convert"]) && $this->field["$field"]["convert"] != 'array')
|
|
{
|
|
$value = $validate->convert($field, $value, $this->field["$field"]["convert"]);
|
|
}
|
|
|
|
$where_list .= " AND ".AGILE_DB_PREFIX."invoice.".$field . " LIKE " . $db->qstr($value, get_magic_quotes_gpc());
|
|
$i++;
|
|
}
|
|
else
|
|
{
|
|
# check if array
|
|
if(is_array($value))
|
|
{
|
|
for($i_arr=0; $i_arr < count($value); $i_arr++)
|
|
{
|
|
if($value["$i_arr"] != '')
|
|
{
|
|
# determine any field options (=, >, <, etc...)
|
|
$f_opt = '=';
|
|
$pat_field = $this->module.'_'.$field;
|
|
if(isset($VAR['field_option']["$pat_field"]["$i_arr"]))
|
|
{
|
|
$f_opt = $VAR['field_option']["$pat_field"]["$i_arr"];
|
|
|
|
# error checking, safety precaution
|
|
if($f_opt != '=' && $f_opt != '>' && $f_opt != '<' && $f_opt != '>=' && $f_opt != '<=' && $f_opt != '!=')
|
|
$f_opt = '=';
|
|
}
|
|
|
|
# do any data conversion for this field (date, encrypt, etc...)
|
|
if(isset($this->field["$field"]["convert"]) && $this->field["$field"]["convert"] != 'array')
|
|
{
|
|
$value["$i_arr"] = $validate->convert($field, $value["$i_arr"], $this->field["$field"]["convert"]);
|
|
}
|
|
|
|
$where_list .= " AND ".AGILE_DB_PREFIX."invoice.". $field . " $f_opt " . $db->qstr($value["$i_arr"], get_magic_quotes_gpc());
|
|
$i++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$where_list .= " AND ".AGILE_DB_PREFIX."invoice.". $field . " = ". $db->qstr($value, get_magic_quotes_gpc());
|
|
$i++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
# Code for attribute searches:
|
|
if(!empty($VAR['join_product_id']) && !empty($VAR['item_attributes']))
|
|
{
|
|
$attr_arr = $VAR['item_attributes'];
|
|
for($ati=0; $ati<count($attr_arr); $ati++)
|
|
{
|
|
if(!empty($attr_arr[$ati]['0']))
|
|
{
|
|
if($where_list == '')
|
|
$where_list .= ' WHERE ';
|
|
else
|
|
$where_list .= ' AND ';
|
|
$where_list .= AGILE_DB_PREFIX."invoice_item.product_attr LIKE " .
|
|
$db->qstr("%{$attr_arr[$ati]['0']}=={$attr_arr[$ati]['1']}%");
|
|
}
|
|
}
|
|
}
|
|
|
|
# get limit type
|
|
if(isset($VAR['limit']))
|
|
{
|
|
$limit = $VAR['limit'];
|
|
}
|
|
else
|
|
{
|
|
$limit = $this->limit;
|
|
}
|
|
|
|
# get order by
|
|
if(isset($VAR['order_by']))
|
|
{
|
|
$order_by = $VAR['order_by'];
|
|
}
|
|
else
|
|
{
|
|
$order_by = $this->order_by;
|
|
}
|
|
|
|
|
|
## SELECT FROM
|
|
$p = AGILE_DB_PREFIX;
|
|
$q = "SELECT DISTINCT {$p}invoice.id FROM ".AGILE_DB_PREFIX."invoice ";
|
|
$q_save = "SELECT DISTINCT %%fieldList%%,{$p}invoice.id FROM {$p}invoice ";
|
|
|
|
## LEFT JOIN
|
|
if( !empty($VAR['join_product_id']) || !empty($VAR['join_service_id']) ||
|
|
!empty($VAR['join_domain_name']) || !empty($VAR['join_domain_tld']) ||
|
|
!empty($VAR['join_memo_text']) )
|
|
{
|
|
# JOIN ON PRODUCT DETAILS:
|
|
if(!empty($VAR['join_product_id']) || !empty($VAR['join_service_id']) || !empty($VAR['join_domain_name']) || !empty($VAR['join_domain_tld']))
|
|
{
|
|
$q .= " LEFT JOIN {$p}invoice_item ON {$p}invoice_item.invoice_id = {$p}invoice.id";
|
|
$q_save .= " LEFT JOIN {$p}invoice_item ON {$p}invoice_item.invoice_id = {$p}invoice.id";
|
|
|
|
if($where_list == '') {
|
|
$q .= " WHERE {$p}invoice_item.site_id = " . $db->qstr(DEFAULT_SITE);
|
|
$q_save .= " WHERE {$p}invoice_item.site_id = " . $db->qstr(DEFAULT_SITE);
|
|
} else {
|
|
$q .= $where_list ." AND {$p}invoice_item.site_id = " . $db->qstr(DEFAULT_SITE);
|
|
$q_save .= $where_list ." AND {$p}invoice_item.site_id = " . $db->qstr(DEFAULT_SITE);
|
|
}
|
|
|
|
# AND (invoice_item.product_id)
|
|
if(!empty($VAR['join_product_id'])) {
|
|
$q .= " AND {$p}invoice_item.product_id = " . $db->qstr($VAR['join_product_id']);
|
|
$q_save .= " AND {$p}invoice_item.product_id = " . $db->qstr($VAR['join_product_id']);
|
|
}
|
|
|
|
# AND (invoice_item.service_id)
|
|
if(!empty($VAR['join_service_id'])) {
|
|
$q .= " AND {$p}invoice_item.service_id = " . $db->qstr($VAR['join_service_id']);
|
|
$q_save .= " AND {$p}invoice_item.service_id = " . $db->qstr($VAR['join_service_id']);
|
|
}
|
|
|
|
# AND (invoice_item.domain_name)
|
|
if(!empty($VAR['join_domain_name'])) {
|
|
if(!ereg('%',$VAR['join_domain_name']) ) $qtype = ' = '; else $qtype = ' LIKE ';
|
|
$q .= " AND {$p}invoice_item.domain_name $qtype " . $db->qstr($VAR['join_domain_name']);
|
|
$q_save .= " AND {$p}invoice_item.domain_name $qtype " . $db->qstr($VAR['join_domain_name']);
|
|
|
|
}
|
|
|
|
# AND (invoice_item.domain_tld)
|
|
if(!empty($VAR['join_domain_tld'])) {
|
|
if(!ereg('%',$VAR['join_domain_tld']) ) $qtype = ' = '; else $qtype = ' LIKE ';
|
|
$q .= " AND {$p}invoice_item.domain_tld $qtype " . $db->qstr($VAR['join_domain_tld']);
|
|
$q_save .= " AND {$p}invoice_item.domain_tld $qtype " . $db->qstr($VAR['join_domain_tld']);
|
|
}
|
|
}
|
|
|
|
# JOIN ON MEMO TEXT:
|
|
if(!empty($VAR['join_memo_text']))
|
|
{
|
|
$q .= " LEFT JOIN {$p}invoice_memo ON {$p}invoice_memo.invoice_id = {$p}invoice.id";
|
|
$q_save .= " LEFT JOIN {$p}invoice_memo ON {$p}invoice_memo.invoice_id = {$p}invoice.id";
|
|
|
|
if($where_list == '') {
|
|
$q .= " WHERE {$p}invoice_memo.site_id = " . $db->qstr(DEFAULT_SITE);
|
|
$q_save .= " WHERE {$p}invoice_memo.site_id = " . $db->qstr(DEFAULT_SITE);
|
|
} else {
|
|
$q .= $where_list ." AND {$p}invoice_memo.site_id = " . $db->qstr(DEFAULT_SITE);
|
|
$q_save .= $where_list ." AND {$p}invoice_memo.site_id = " . $db->qstr(DEFAULT_SITE);
|
|
}
|
|
|
|
$q .= " AND {$p}invoice_memo.memo LIKE " . $db->qstr('%'. $VAR['join_memo_text'] .'%');
|
|
$q_save .= " AND {$p}invoice_memo.memo LIKE " . $db->qstr('%'. $VAR['join_memo_text'] .'%');
|
|
}
|
|
|
|
$q .= " AND {$p}invoice.site_id = ". DEFAULT_SITE;
|
|
$q_save .= ' AND ';
|
|
}
|
|
else
|
|
{
|
|
if($where_list == '') {
|
|
$q .= "WHERE {$p}invoice.site_id = ". DEFAULT_SITE;
|
|
$q_save .= ' WHERE ';
|
|
}
|
|
else
|
|
{
|
|
$q .= $where_list . " AND {$p}invoice.site_id = ". DEFAULT_SITE;
|
|
$q_save .= $where_list . ' AND ';
|
|
}
|
|
}
|
|
|
|
|
|
///////////////// debug
|
|
#echo $q;
|
|
#exit;
|
|
|
|
# run the database query
|
|
$result = $db->Execute($q);
|
|
|
|
# error reporting
|
|
if ($result === false)
|
|
{
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','search', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
|
|
# get the result count:
|
|
$results = $result->RecordCount();
|
|
|
|
# get the first record id:
|
|
if($results == 1) $record_id = $result->fields['id'];
|
|
|
|
# define the DB vars as a Smarty accessible block
|
|
global $smarty;
|
|
|
|
# Create the definition for fast-forwarding to a single record:
|
|
if ($results == 1 && !isset($this->fast_forward))
|
|
{
|
|
$smarty->assign('record_id', $record_id);
|
|
}
|
|
|
|
# create the search record:
|
|
if($results > 0)
|
|
{
|
|
# create the search record
|
|
include_once(PATH_CORE . 'search.inc.php');
|
|
$search = new CORE_search;
|
|
$arr['module'] = $this->module;
|
|
$arr['sql'] = $q_save;
|
|
$arr['limit'] = $limit;
|
|
$arr['order_by']= $order_by;
|
|
$arr['results'] = $results;
|
|
$search->add($arr);
|
|
|
|
# define the search id and other parameters for Smarty
|
|
$smarty->assign('search_id', $search->id);
|
|
|
|
# page:
|
|
$smarty->assign('page', '1');
|
|
|
|
# limit:
|
|
$smarty->assign('limit', $limit);
|
|
|
|
# order_by:
|
|
$smarty->assign('order_by', $order_by);
|
|
}
|
|
|
|
# define the result count
|
|
$smarty->assign('results', $results);
|
|
}
|
|
|
|
/** SEARCH SHOW
|
|
*/
|
|
function search_show($VAR)
|
|
{
|
|
$this->invoice_construct();
|
|
$type = "search";
|
|
$this->method["$type"] = split(",", $this->method["$type"]);
|
|
|
|
# set the field list for this method:
|
|
$arr = $this->method[$type];
|
|
$field_list = '';
|
|
$i=0;
|
|
while (list ($key, $value) = each ($arr))
|
|
{
|
|
if($i == 0)
|
|
{
|
|
$field_var = $this->table . '_' . $value;
|
|
$field_list .= AGILE_DB_PREFIX . "invoice" . "." . $value;
|
|
|
|
// determine if this record is linked to another table/field
|
|
if($this->field[$value]["asso_table"] != "")
|
|
{
|
|
$this->linked[] = array('field' => $value, 'link_table' => $this->field[$value]["asso_table"], 'link_field' => $this->field[$value]["asso_field"]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$field_var = $this->table . '_' . $value;
|
|
$field_list .= "," . AGILE_DB_PREFIX . "invoice" . "." . $value;
|
|
|
|
// determine if this record is linked to another table/field
|
|
if($this->field[$value]["asso_table"] != "")
|
|
{
|
|
$this->linked[] = array('field' => $value, 'link_table' => $this->field[$value]["asso_table"], 'link_field' => $this->field[$value]["asso_field"]);
|
|
}
|
|
}
|
|
$i++;
|
|
}
|
|
|
|
|
|
# get the search details:
|
|
if(isset($VAR['search_id'])) {
|
|
include_once(PATH_CORE . 'search.inc.php');
|
|
$search = new CORE_search;
|
|
$search->get($VAR['search_id']);
|
|
} else {
|
|
# invalid search!
|
|
echo '<BR> The search terms submitted were invalid!'; # translate... # alert
|
|
|
|
if(isset($this->trigger["$type"])) {
|
|
include_once(PATH_CORE . 'trigger.inc.php');
|
|
$trigger = new CORE_trigger;
|
|
$trigger->trigger($this->trigger["$type"], 0, $VAR);
|
|
}
|
|
}
|
|
|
|
# get the sort order details:
|
|
if(isset($VAR['order_by']) && $VAR['order_by'] != "") {
|
|
$order_by = ' ORDER BY ' . $VAR['order_by'];
|
|
$smarty_order = $VAR['order_by'];
|
|
} else {
|
|
$order_by = ' ORDER BY ' . $this->order_by;
|
|
$smarty_order = $search->order_by;
|
|
}
|
|
|
|
|
|
# determine the sort order
|
|
if(isset($VAR['desc'])) {
|
|
$order_by .= ' DESC';
|
|
$smarty_sort = 'desc=';
|
|
} else if(isset($VAR['asc'])) {
|
|
$order_by .= ' ASC';
|
|
$smarty_sort = 'asc=';
|
|
} else {
|
|
if (!eregi('date',$smarty_order)) {
|
|
$order_by .= ' ASC';
|
|
$smarty_sort = 'asc=';
|
|
} else {
|
|
$order_by .= ' DESC';
|
|
$smarty_sort = 'desc=';
|
|
}
|
|
}
|
|
|
|
|
|
# determine the offset & limit
|
|
$current_page=1;
|
|
$offset=-1;
|
|
if (!empty($VAR['page'])) $current_page = $VAR['page'];
|
|
if (empty($search->limit)) $search->limit=25;
|
|
if($current_page>1) $offset = (($current_page * $search->limit) - $search->limit);
|
|
|
|
# generate the full query
|
|
$db = &DB();
|
|
$q = eregi_replace("%%fieldList%%", $field_list, $search->sql);
|
|
$q = eregi_replace("%%tableList%%", AGILE_DB_PREFIX.$construct->table, $q);
|
|
$q = eregi_replace("%%whereList%%", "", $q);
|
|
$q .= " ".AGILE_DB_PREFIX . "invoice.site_id = '" . DEFAULT_SITE . "'";
|
|
$q .= $order_by;
|
|
|
|
//////////////////
|
|
#echo "<BR> $q <BR>";
|
|
|
|
$result = $db->SelectLimit($q, $search->limit, $offset);
|
|
|
|
# error reporting
|
|
if ($result === false)
|
|
{
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','search', $db->ErrorMsg());
|
|
|
|
if(isset($this->trigger["$type"]))
|
|
{
|
|
include_once(PATH_CORE . 'trigger.inc.php');
|
|
$trigger = new CORE_trigger;
|
|
$trigger->trigger($this->trigger["$type"], 0, $VAR);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
# put the results into a smarty accessable array
|
|
$i=0;
|
|
$class_name = TRUE;
|
|
while (!$result->EOF) {
|
|
$smart[$i] = $result->fields;
|
|
$amount += $result->fields['total_amt'];
|
|
if($class_name)
|
|
{
|
|
$smart[$i]['_C'] = 'row1';
|
|
$class_name = FALSE;
|
|
} else {
|
|
$smart[$i]['_C'] = 'row2';
|
|
$class_name = TRUE;
|
|
}
|
|
|
|
$result->MoveNext();
|
|
$i++;
|
|
}
|
|
|
|
|
|
# get any linked fields
|
|
if($i > 0)
|
|
{
|
|
$db_join = new CORE_database;
|
|
$this->result = $db_join->join_fields($smart, $this->linked);
|
|
}
|
|
else
|
|
{
|
|
$this->result = $smart;
|
|
}
|
|
|
|
# get the result count:
|
|
$results = $result->RecordCount();
|
|
|
|
# define the DB vars as a Smarty accessible block
|
|
global $smarty;
|
|
|
|
# define the results
|
|
$smarty->assign($this->table, $this->result);
|
|
$smarty->assign('page', $VAR['page']);
|
|
$smarty->assign('order', $smarty_order);
|
|
$smarty->assign('sort', $smarty_sort);
|
|
$smarty->assign('limit', $search->limit);
|
|
$smarty->assign('search_id',$search->id);
|
|
$smarty->assign('results', $search->results);
|
|
|
|
global $C_list;
|
|
$smarty->assign('total_amount', $C_list->format_currency($amount,DEFAULT_CURRENCY));
|
|
|
|
# get the total pages for this search:
|
|
if(empty($search->limit))
|
|
$this->pages = 1;
|
|
else
|
|
$this->pages = intval($search->results / $search->limit);
|
|
if ($search->results % $search->limit) $this->pages++;
|
|
|
|
# total pages
|
|
$smarty->assign('pages', $this->pages);
|
|
|
|
# current page
|
|
$smarty->assign('page', $current_page);
|
|
$page_arr = '';
|
|
for($i=0; $i <= $this->pages; $i++)
|
|
{
|
|
if ($this->page != $i) $page_arr[] = $i;
|
|
}
|
|
|
|
# page array for menu
|
|
$smarty->assign('page_arr', $page_arr);
|
|
}
|
|
|
|
/** USER SEARCH
|
|
*/
|
|
function user_search($VAR)
|
|
{
|
|
if(!SESS_LOGGED) return false;
|
|
$VAR['invoice_account_id'] = SESS_ACCOUNT;
|
|
$this->invoice_construct();
|
|
$type = "search";
|
|
$this->method["$type"] = split(",", $this->method["$type"]);
|
|
$db = new CORE_database;
|
|
$db->search($VAR, $this, $type);
|
|
}
|
|
|
|
/** USER SEARCH SHOW
|
|
*/
|
|
function user_search_show($VAR)
|
|
{
|
|
if(!SESS_LOGGED) return false;
|
|
$this->invoice_construct();
|
|
$type = "search";
|
|
$this->method["$type"] = split(",", $this->method["$type"]);
|
|
$db = new CORE_database;
|
|
$db->search_show($VAR, $this, $type);
|
|
}
|
|
|
|
/** USER VIEW
|
|
*/
|
|
function user_view($VAR)
|
|
{
|
|
global $C_auth;
|
|
if(!SESS_LOGGED) return false;
|
|
|
|
// verify the account_id for this order is the SESS_ACCOUNT
|
|
if ( $C_auth->auth_method_by_name('invoice','view') == false)
|
|
{
|
|
$id = split(',',$VAR['id']);
|
|
$db = &DB();
|
|
$q = "SELECT account_id FROM ".AGILE_DB_PREFIX."invoice WHERE
|
|
id = ".$db->qstr($id[0])." AND
|
|
site_id = ".$db->qstr(DEFAULT_SITE);
|
|
$rs = $db->Execute($q);
|
|
if ($rs === false) {
|
|
global $C_debug;
|
|
$C_debug->error('invoice.inc.php','user_view', $db->ErrorMsg());
|
|
return false;
|
|
}
|
|
if ($rs->fields['account_id'] != SESS_ACCOUNT) return false;
|
|
}
|
|
$this->view($VAR, $this);
|
|
}
|
|
|
|
/** SEARCH EXPORT
|
|
*/
|
|
function search_export($VAR)
|
|
{
|
|
$this->invoice_construct();
|
|
|
|
# require the export class
|
|
require_once (PATH_CORE . "export.inc.php");
|
|
|
|
# Call the correct export function for inline browser display, download, email, or web save.
|
|
if($VAR["format"] == "excel")
|
|
{
|
|
$type = "export_excel";
|
|
$this->method["$type"] = split(",", $this->method["$type"]);
|
|
$export = new CORE_export;
|
|
$export->search_excel($VAR, $this, $type);
|
|
}
|
|
|
|
else if ($VAR["format"] == "pdf")
|
|
{
|
|
$type = "export_pdf";
|
|
$this->method["$type"] = split(",", $this->method["$type"]);
|
|
$export = new CORE_export;
|
|
$export->pdf_invoice($VAR, $this, $type);
|
|
}
|
|
|
|
else if ($VAR["format"] == "xml")
|
|
{
|
|
$type = "export_xml";
|
|
$this->method["$type"] = split(",", $this->method["$type"]);
|
|
$export = new CORE_export;
|
|
$export->search_xml($VAR, $this, $type);
|
|
}
|
|
|
|
else if ($VAR["format"] == "csv")
|
|
{
|
|
$type = "export_csv";
|
|
$this->method["$type"] = split(",", $this->method["$type"]);
|
|
$export = new CORE_export;
|
|
$export->search_csv($VAR, $this, $type);
|
|
}
|
|
|
|
else if ($VAR["format"] == "tab")
|
|
{
|
|
$type = "export_tab";
|
|
$this->method["$type"] = split(",", $this->method["$type"]);
|
|
$export = new CORE_export;
|
|
$export->search_tab($VAR, $this, $type);
|
|
}
|
|
}
|
|
|
|
function invoice_construct()
|
|
{
|
|
$this->module = "invoice";
|
|
$this->xml_construct = PATH_MODULES . "" . $this->module . "/" . $this->module . "_construct.xml";
|
|
include_once(PATH_CORE.'xml.inc.php');
|
|
$C_xml = new CORE_xml;
|
|
$construct = $C_xml->xml_to_array($this->xml_construct);
|
|
$this->method = $construct["construct"]["method"];
|
|
$this->trigger = $construct["construct"]["trigger"];
|
|
$this->field = $construct["construct"]["field"];
|
|
$this->table = $construct["construct"]["table"];
|
|
$this->module = $construct["construct"]["module"];
|
|
$this->cache = $construct["construct"]["cache"];
|
|
$this->order_by = $construct["construct"]["order_by"];
|
|
$this->limit = $construct["construct"]["limit"];
|
|
}
|
|
}
|
|
?>
|