This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
khosb/modules/discount/discount.inc.php
2011-05-03 09:49:04 +10:00

409 lines
12 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
*
* Originally authored by Tony Landis, AgileBill LLC
*
* Recent modifications by Deon George
*
* @author Deon George <deonATleenooksDOTnet>
* @copyright 2009 Deon George
* @link http://osb.leenooks.net
*
* @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
* @subpackage Module:Discount
*/
/**
* The main AgileBill Discount Class
*
* @package AgileBill
* @subpackage Module:Discount
*/
class discount extends OSB_module {
# Array of available discounts
private $discounts = array();
# The cumulative amount of the current discount
private $discount_total = 0;
# The array of discounts applied to the line_items
public $discount_arr = array();
# Array that contains list of discount plugins in the /plugins/discount/ directory to load
private $plugins = array();
/**
* Load a specific discount plugin and validate the results
*
* @param string $plugin The plugin name
* @param string $discount The discount code
* @return bool
*/
private function plugin_validate($plugin,$code) {
$plugin_file = sprintf('%sdiscount/%s.php',PATH_PLUGINS,$plugin);
if (is_file($plugin_file)) {
include_once($plugin_file);
eval('$plg = new plgn_discount_'. $plugin .';');
if (is_object($plg) && is_callable(array($plg,'validate'))) {
$plg->discount = $code;
return $plg->validate($code);
}
}
return false;
}
/**
* Add a discount code to our session record, it'll be used/evaluated later to calculate the discounts.
*
* @param array $VAR
* @return bool
* @uses session
*/
public function add_cart_discount($VAR) {
global $C_debug, $C_translate, $smarty;
$db = &DB();
# Validate input
if (empty($VAR['discount'])) {
$C_debug->alert(_('The discount code was entered incorrectly or is not valid.'));
return false;
}
$discount_code = $VAR['discount'];
# Check the supplied discount
$check = $this->sql_GetRecords(
array('where'=>sprintf('(date_start IS NULL OR date_start=0 OR date_start>%s) AND date_expire<=%s AND name=::%s::',time(),time(),$discount_code)));
# Local check failed, attempt any discount plugins
if (! $check || count($check)>1 || $check[0]['status'] != '1') {
$plg = false;
foreach ($this->plugins as $plugin) {
if ($discount_code = $this->plugin_validate($plugin,$discount_code)) {
$plg = true;
break;
}
}
# No plugins returned true...
if (! $plg) {
$C_debug->alert(_('The discount code was entered incorrectly or is not valid.'));
return false;
}
}
# Get existing discounts:
require_once(PATH_MODULES.'session/session.inc.php');
$seo = new session(SESS);
$arr = array();
if (is_string($seo->getRecordAttr('discounts')))
$arr = unserialize($seo->getRecordAttr('discounts'));
# Check for duplicates
if (is_array($arr))
foreach ($arr as $key=>$discount)
if ($discount == $discount_code)
return true;
# Update session data
array_push($arr,$discount_code);
$seo->setRecordAttr('discounts',serialize($arr));
$seo->sql_SaveRecord(true,true);
return true;
}
/**
* Commit current discounts to the database (call after creating an invoice_item record)
*/
public function invoice_item($invoice_id,$invoice_item_id,$account_id,$discount_arr=false) {
if ($discount_arr && is_array($discount_arr))
$this->discount_arr = $discount_arr;
if (is_array($this->discount_arr)) {
$db =& DB();
foreach ($this->discount_arr as $dsc)
$db->Execute(sqlInsert($db,'invoice_item_discount',
array('invoice_id'=>$invoice_id,'account_id'=>$account_id,'invoice_item_id'=>$invoice_item_id,'discount'=>$dsc['discount'],'amount'=>$dsc['amount'])));
}
}
/**
* Get the avialable discounts for an account, session, or service
*
* @param $account
* @param $type 0=initial order, 1=recurring charge
*/
private function available_discounts($account,$type=0,$invoice=false) {
$db =& DB();
# Get account specific discounts
if ($type)
$sqltype = 'recurr_status=1';
else
$sqltype = 'new_status=1';
foreach ($this->sql_GetRecords(array('where'=>sprintf('avail_account_id=%s AND status=1 AND %s',$account,$sqltype))) as $record)
$this->discounts[$record['name']] = $record;
# Get session discounts from cart
if ($type == 0) {
$rs = $db->Execute(
sqlSelect('session','discounts',array('where'=>sprintf('(account_id=%s OR id=::%s::) AND discounts!=:::: AND discounts IS NOT NULL',$account,SESS))));
if ($rs && $rs->RecordCount()) {
$arr = unserialize($rs->fields['discounts']);
if (is_array($arr))
foreach ($arr as $discount)
if (! empty($discount))
foreach ($this->sql_GetRecords(array('where'=>sprintf('name=%s AND status=1',$discount))) as $record)
$this->discounts[$record['name']] = $record;
}
# Get recurring discounts
} elseif ($type==1 && $invoice) {
$rs = $db->Execute(
sqlSelect($db,array('invoice_item_discount','discount'),'B.*',sprintf('A.invoice_id=%s AND A.discount=B.name AND status=1 AND %s',$invoice,$sqltype)));
if ($rs && $rs->RecordCount()) {
while (! $rs->EOF) {
$this->discounts[$rs->fields['name']] = $rs->fields;
$rs->MoveNext();
}
}
}
}
/**
* Calculate all applicable discounts for the current line item
*
* @param $type bool 0=initial product, 1=recurring product, 2=initial_domain, 3=recurring domain
* @param $invoice_item_id int The invoice item id for the discount
* @param $product_id int The product ID if type=0,1 or The TLD if type = 2,3
* @param $account_id int The account ID
* @param $invoice_amt float The cumulative invoice amount
* @param $prod_amt float The product price before any discounts
*/
public function calc_all_discounts($type=0,$pid,$pamt,$aid,$iamt) {
# Populate our discounts
$this->available_discounts($aid,$type,$iamt);
if (! count($this->discounts))
return array();
foreach ($this->discounts as $did => $discount) {
$amt = $this->calc_item_discount($type,$did,$pid,$aid,$iamt,$pamt);
if ($amt > 0)
array_push($this->discount_arr,array('discount'=>$discount['name'],'amount'=>$amt));
}
return $this->discount_arr;
}
/**
* Calculate Recurring Discount
*
* @param $type bool 0=initial product, 1=recurring product, 2=initial_domain, 3=recurring domain
* @param $did string The Discount ID (must be set to $this->discount["$discounts"] containing the fields of the discount)
* @param $pid int The product ID if type=0,1 or The TLD if type = 2,3
* @param $aid int The account ID
* @param $iamt float The cumulative invoice amount
* @param $pamt float The product price before any discounts
*/
private function calc_item_discount($type,$did,$pid,$aid,$iamt,$pamt) {
if (empty($this->discounts[$did]))
return false;
$discount = $this->discounts[$did];
if ($type == 0 || $type == 2) {
$rate_type = $discount['new_type'];
$rate = $discount['new_rate'];
$min_cost = $discount['new_min_cost'];
$max_usage_amt = $discount['new_max_discount'];
} else {
$rate_type = $discount['recurr_type'];
$rate = $discount['recurr_rate'];
$min_cost = $discount['recurr_min_cost'];
$max_usage_amt = $discount['recurr_max_discount'];
}
if ((! empty($discount['date_start']) && $discount['date_start']>time()) ||
(! empty($discount['date_expire']) && $discount['date_expire']<time()) ||
(! empty($min_cost) && $min_cost > $iamt))
return 0;
if (($discount['max_usage_account']>0 || $discount['max_usage_global']>0) &&
(! $this->discount_check_usage($discount['max_usage_account'],$discount['max_usage_global'],$aid,$did)))
return 0;
if (! empty($discount['avail_account_id']) && $discount['avail_account_id'] != $aid)
return 0;
if ($type==0 || $type==2) {
if (! empty($discount['avail_account_id']) && $discount['avail_account_id'] != $aid) {
return 0;
} else {
if (! empty($discount['avail_group_id'])) {
$arr = unserialize($discount['avail_group_id']);
if (is_array($arr) && count($arr) > 0 && ! empty($arr[0])) {
global $C_auth;
$do = false;
for ($i=0; $i<count($arr); $i++) {
if ($C_auth->auth_group_by_id($arr[$i])) {
$do=true;
$i=count($arr);
}
}
if (! $do)
return 0;
}
}
}
}
if ($type<2 && ! empty($pid) && ! empty($discount['avail_product_id'])) {
$arr = unserialize($discount['avail_product_id']);
if (is_array($arr) && count($arr)>0 && ! in_array($pid,$arr))
return 0;
} elseif ($type>1) {
if (! empty($discount['avail_tld_id'])) {
$do = false;
$tld = $pid;
$db = &DB();
$rstld = $db->Execute(sqlSelect($db,"host_tld","id","name=::$tld::"));
if($rstld && $rstld->RecordCount()) {
$tld_id = $rstld->fields['id'];
$arr = unserialize($discount['avail_tld_id']);
if (is_array($arr) && count($arr) > 0 && ! empty($arr[0])) {
for ($i=0; $i<count($arr); $i++)
if ($arr[$i] == $tld_id) {
$do=true;
$i=count($arr);
}
if (! $do)
return 0;
}
}
}
}
if ($rate_type == '0') {
$discount_amt = $rate*$pamt;
if (! empty($max_usage_amt) && $discount_amt > $max_usage_amt)
$discount_amt = $max_usage_amt;
} else {
$discount_amt = $rate;
}
if (! empty($max_usage_amt)) {
if ($discount_amt+$this->discount_total > $max_usage_amt)
$discount_amt = $max_usage_amt-$this->discount_total;
}
$this->discount_total += $discount_amt;
return round($discount_amt,2);
}
/**
* Check discount usage for account/global restrictions
*/
private function discount_check_usage($max_acct,$max_global,$account_id,$did) {
if (! isset($this->discounts[$did]))
return 0;
$db = &DB();
$rs = $db->Execute(
sqlSelect('invoice_item_discount','account_id,COUNT(account_id) AS count',
array('where'=>array('discount'=>$this->discounts[$did]['name']),'groupby'=>'account_id')));
if ($rs && $rs->RecordCount()) {
# Check global usage
if (! empty($max_global) && $max_global>0 && $rs->RecordCount()>=$max_global)
return false;
# Check usage by this account
if (! empty($max_acct) && $max_acct>0) {
$i = 0;
while (! $rs->EOF) {
if ($rs->fields['account_id'] == $account_id && $rs->fields['count']>=$max_acct)
return false;
$rs->MoveNext();
}
}
}
return true;
}
public function search_show($VAR) {
$db =& DB();
$smart = parent::search_show($VAR);
for ($i=0; $i<count($smart); $i++) {
$smart[$i]['savings'] = 0;
$smart[$i]['orders'] = 0;
$smart[$i]['revenue'] = 0;
$rs = $db->Execute(sqlSelect(array('invoice','invoice_item_discount'),'SUM(A.total_amt) as sum',
array('where'=>sprintf('B.invoice_id=A.id AND A.billing_status=1 AND B.discount=::%s::',$smart[$i]['name']),'distinct'=>true)));
if ($rs && $rs->RecordCount())
$smart[$i]['revenue'] = $rs->fields['sum'];
$rs = $db->Execute(sqlSelect('invoice_item_discount','invoice_id,amount',array('where'=>sprintf('discount=::%s::',$smart[$i]['name']))));
if ($rs && $rs->RecordCount()>0) {
while (! $rs->EOF) {
$smart[$i]['savings'] += $rs->fields['amount'];
if (empty($invoices[$rs->fields['invoice_id']])) {
$smart[$i]['orders']++;
$invoices[$rs->fields['invoice_id']]=true;
}
$rs->MoveNext();
}
}
}
global $smarty;
$smarty->clear_assign('discount');
$smarty->assign('discount',$smart);
}
}
?>