2008-11-26 22:50:40 +00:00
< ? 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
2009-08-03 04:10:16 +00:00
*
* 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
2008-11-26 22:50:40 +00:00
*
* @ link http :// www . agileco . com /
* @ copyright 2004 - 2008 Agileco , LLC .
* @ license http :// www . agileco . com / agilebill / license1 - 4. txt
2009-08-03 04:10:16 +00:00
* @ author Tony Landis < tony @ agileco . com >
2008-11-26 22:50:40 +00:00
* @ package AgileBill
2009-08-03 04:10:16 +00:00
* @ subpackage Module : Discount
2008-11-26 22:50:40 +00:00
*/
2009-08-03 04:10:16 +00:00
/**
* The main AgileBill Discount Class
*
* @ package AgileBill
* @ subpackage Module : Discount
*/
class discount extends OSB_module {
2010-11-29 22:41:08 +00:00
# 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 ();
2008-11-26 22:50:40 +00:00
/**
* Load a specific discount plugin and validate the results
*
* @ param string $plugin The plugin name
* @ param string $discount The discount code
* @ return bool
*/
2010-11-29 22:41:08 +00:00
private function plugin_validate ( $plugin , $code ) {
$plugin_file = sprintf ( '%sdiscount/%s.php' , PATH_PLUGINS , $plugin );
if ( is_file ( $plugin_file )) {
2008-11-26 22:50:40 +00:00
include_once ( $plugin_file );
eval ( '$plg = new plgn_discount_' . $plugin . ';' );
2010-11-29 22:41:08 +00:00
if ( is_object ( $plg ) && is_callable ( array ( $plg , 'validate' ))) {
$plg -> discount = $code ;
return $plg -> validate ( $code );
2008-11-26 22:50:40 +00:00
}
2010-11-29 22:41:08 +00:00
}
return false ;
2008-11-26 22:50:40 +00:00
}
2010-11-29 22:41:08 +00:00
2008-11-26 22:50:40 +00:00
/**
2010-11-29 22:41:08 +00:00
* Add a discount code to our session record , it ' ll be used / evaluated later to calculate the discounts .
2008-11-26 22:50:40 +00:00
*
* @ param array $VAR
* @ return bool
2010-11-29 22:41:08 +00:00
* @ uses session
2008-11-26 22:50:40 +00:00
*/
2010-11-29 22:41:08 +00:00
public function add_cart_discount ( $VAR ) {
2008-11-26 22:50:40 +00:00
global $C_debug , $C_translate , $smarty ;
2010-11-29 22:41:08 +00:00
$db = & DB ();
2008-11-26 22:50:40 +00:00
# Validate input
2010-11-29 22:41:08 +00:00
if ( empty ( $VAR [ 'discount' ])) {
$C_debug -> alert ( _ ( 'The discount code was entered incorrectly or is not valid.' ));
2008-11-26 22:50:40 +00:00
return false ;
}
2010-11-29 22:41:08 +00:00
$discount_code = $VAR [ 'discount' ];
2008-11-26 22:50:40 +00:00
# Check the supplied discount
2010-11-29 22:41:08 +00:00
$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 ;
2008-11-26 22:50:40 +00:00
}
}
2010-11-29 22:41:08 +00:00
# No plugins returned true...
if ( ! $plg ) {
$C_debug -> alert ( _ ( 'The discount code was entered incorrectly or is not valid.' ));
2008-11-26 22:50:40 +00:00
return false ;
}
}
2010-11-29 22:41:08 +00:00
# Get existing discounts:
require_once ( PATH_MODULES . 'session/session.inc.php' );
$seo = new session ( SESS );
2008-11-26 22:50:40 +00:00
$arr = array ();
2010-11-29 22:41:08 +00:00
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 ;
2008-11-26 22:50:40 +00:00
}
2010-11-29 22:41:08 +00:00
2008-11-26 22:50:40 +00:00
/**
2010-11-29 22:41:08 +00:00
* 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' ])));
2008-11-26 22:50:40 +00:00
}
}
/**
2010-11-29 22:41:08 +00:00
* 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 ) {
2008-11-26 22:50:40 +00:00
$db =& DB ();
2010-11-29 22:41:08 +00:00
# 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 ;
2008-11-26 22:50:40 +00:00
}
2010-11-29 22:41:08 +00:00
# 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 ;
2008-11-26 22:50:40 +00:00
$rs -> MoveNext ();
}
}
}
}
/**
2010-11-29 22:41:08 +00:00
* 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 ));
2008-11-26 22:50:40 +00:00
}
2010-11-29 22:41:08 +00:00
return $this -> discount_arr ;
2008-11-26 22:50:40 +00:00
}
/**
2010-11-29 22:41:08 +00:00
* 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 ;
2008-11-26 22:50:40 +00:00
2010-11-29 22:41:08 +00:00
$discount = $this -> discounts [ $did ];
2008-11-26 22:50:40 +00:00
2010-11-29 22:41:08 +00:00
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' ];
2008-11-26 22:50:40 +00:00
2010-11-29 22:41:08 +00:00
} else {
$rate_type = $discount [ 'recurr_type' ];
$rate = $discount [ 'recurr_rate' ];
$min_cost = $discount [ 'recurr_min_cost' ];
$max_usage_amt = $discount [ 'recurr_max_discount' ];
}
2008-11-26 22:50:40 +00:00
2010-11-29 22:41:08 +00:00
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 ;
2008-11-26 22:50:40 +00:00
2010-11-29 22:41:08 +00:00
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 ;
2008-11-26 22:50:40 +00:00
2010-11-29 22:41:08 +00:00
if ( ! empty ( $discount [ 'avail_account_id' ]) && $discount [ 'avail_account_id' ] != $aid )
return 0 ;
2008-11-26 22:50:40 +00:00
2010-11-29 22:41:08 +00:00
if ( $type == 0 || $type == 2 ) {
if ( ! empty ( $discount [ 'avail_account_id' ]) && $discount [ 'avail_account_id' ] != $aid ) {
2008-11-26 22:50:40 +00:00
return 0 ;
2010-11-29 22:41:08 +00:00
2008-11-26 22:50:40 +00:00
} else {
2010-11-29 22:41:08 +00:00
if ( ! empty ( $discount [ 'avail_group_id' ])) {
$arr = unserialize ( $discount [ 'avail_group_id' ]);
if ( is_array ( $arr ) && count ( $arr ) > 0 && ! empty ( $arr [ 0 ])) {
2008-11-26 22:50:40 +00:00
global $C_auth ;
2010-11-29 22:41:08 +00:00
$do = false ;
for ( $i = 0 ; $i < count ( $arr ); $i ++ ) {
if ( $C_auth -> auth_group_by_id ( $arr [ $i ])) {
$do = true ;
$i = count ( $arr );
}
2008-11-26 22:50:40 +00:00
}
2010-11-29 22:41:08 +00:00
if ( ! $do )
return 0 ;
2008-11-26 22:50:40 +00:00
}
}
}
}
2010-11-29 22:41:08 +00:00
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 ;
2008-11-26 22:50:40 +00:00
} elseif ( $type > 1 ) {
2010-11-29 22:41:08 +00:00
if ( ! empty ( $discount [ 'avail_tld_id' ])) {
$do = false ;
$tld = $pid ;
2008-11-26 22:50:40 +00:00
$db = & DB ();
$rstld = $db -> Execute ( sqlSelect ( $db , " host_tld " , " id " , " name=:: $tld :: " ));
2010-11-29 22:41:08 +00:00
2008-11-26 22:50:40 +00:00
if ( $rstld && $rstld -> RecordCount ()) {
2010-11-29 22:41:08 +00:00
$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 ;
2008-11-26 22:50:40 +00:00
}
}
}
}
2010-11-29 22:41:08 +00:00
if ( $rate_type == '0' ) {
$discount_amt = $rate * $pamt ;
if ( ! empty ( $max_usage_amt ) && $discount_amt > $max_usage_amt )
$discount_amt = $max_usage_amt ;
2008-11-26 22:50:40 +00:00
} else {
$discount_amt = $rate ;
}
2010-11-29 22:41:08 +00:00
if ( ! empty ( $max_usage_amt )) {
if ( $discount_amt + $this -> discount_total > $max_usage_amt )
$discount_amt = $max_usage_amt - $this -> discount_total ;
2008-11-26 22:50:40 +00:00
}
2010-11-29 22:41:08 +00:00
$this -> discount_total += $discount_amt ;
2008-11-26 22:50:40 +00:00
return round ( $discount_amt , 2 );
}
/**
2010-11-29 22:41:08 +00:00
* 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 ;
2008-11-26 22:50:40 +00:00
$db = & DB ();
2010-11-29 22:41:08 +00:00
$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 ()) {
2008-11-26 22:50:40 +00:00
# Check global usage
2010-11-29 22:41:08 +00:00
if ( ! empty ( $max_global ) && $max_global > 0 && $rs -> RecordCount () >= $max_global )
return false ;
2008-11-26 22:50:40 +00:00
# Check usage by this account
2010-11-29 22:41:08 +00:00
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 ;
2008-11-26 22:50:40 +00:00
$rs -> MoveNext ();
}
}
}
2010-11-29 22:41:08 +00:00
2008-11-26 22:50:40 +00:00
return true ;
}
2010-11-29 22:41:08 +00:00
public function search_show ( $VAR ) {
$db =& DB ();
$smart = parent :: search_show ( $VAR );
2008-11-26 22:50:40 +00:00
2010-11-29 22:41:08 +00:00
for ( $i = 0 ; $i < count ( $smart ); $i ++ ) {
$smart [ $i ][ 'savings' ] = 0 ;
$smart [ $i ][ 'orders' ] = 0 ;
$smart [ $i ][ 'revenue' ] = 0 ;
2008-11-26 22:50:40 +00:00
2010-11-29 22:41:08 +00:00
$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 ;
2008-11-26 22:50:40 +00:00
}
2010-11-29 22:41:08 +00:00
2008-11-26 22:50:40 +00:00
$rs -> MoveNext ();
}
}
}
2010-11-29 22:41:08 +00:00
2008-11-26 22:50:40 +00:00
global $smarty ;
$smarty -> clear_assign ( 'discount' );
2010-11-29 22:41:08 +00:00
$smarty -> assign ( 'discount' , $smart );
}
2008-11-26 22:50:40 +00:00
}
2009-08-03 04:10:16 +00:00
?>