Page MenuHomeIn-Portal Phabricator

in-commerce
No OneTemporary

File Metadata

Created
Tue, Aug 5, 12:09 AM

in-commerce

Index: branches/5.1.x/units/affiliates/affiliates_event_handler.php
===================================================================
--- branches/5.1.x/units/affiliates/affiliates_event_handler.php (revision 13490)
+++ branches/5.1.x/units/affiliates/affiliates_event_handler.php (revision 13491)
@@ -1,534 +1,535 @@
<?php
/**
* @version $Id$
* @package In-Commerce
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license Commercial License
* This software is protected by copyright law and international treaties.
* Unauthorized reproduction or unlicensed usage of the code of this program,
* or any portion of it may result in severe civil and criminal penalties,
* and will be prosecuted to the maximum extent possible under the law
* See http://www.in-portal.org/commercial-license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class AffiliatesEventHandler extends kDBEventHandler {
/**
* Allows to override standart permission mapping
*
*/
function mapPermissions()
{
parent::mapPermissions();
$permissions = Array(
'OnItemBuild' => Array ('self' => true),
'OnChangePaymentType' => Array ('self' => true),
'OnBecomeAffiliate' => Array ('self' => true),
);
$this->permMapping = array_merge($this->permMapping, $permissions);
}
/**
* Generate new affiliate code
*
* @param kEvent $event
* @return string
*/
function generateAffiliateCode(&$event)
{
// accepts 1 - 36
$number_length = 11;
$num_chars = Array( '1'=>'a','2'=>'b','3'=>'c','4'=>'d','5'=>'e','6'=>'f',
'7'=>'g','8'=>'h','9'=>'i','10'=>'j','11'=>'k','12'=>'l',
'13'=>'m','14'=>'n','15'=>'o','16'=>'p','17'=>'q','18'=>'r',
'19'=>'s','20'=>'t','21'=>'u','22'=>'v','23'=>'w','24'=>'x',
'25'=>'y','26'=>'z','27'=>'0','28'=>'1','29'=>'2','30'=>'3',
'31'=>'4','32'=>'5','33'=>'6','34'=>'7','35'=>'8','36'=>'9');
$ret = '';
for($i=1; $i<=$number_length; $i++)
{
mt_srand((double)microtime() * 1000000);
$num = mt_rand(1,36);
$ret .= $num_chars[$num];
}
$ret = strtoupper($ret);
$idfield = $this->Application->getUnitOption($event->Prefix, 'IDField');
$table = $this->Application->getUnitOption($event->Prefix, 'TableName');
$sql = 'SELECT %s FROM %s WHERE AffiliateCode = %s';
$code_found = $this->Conn->GetOne( sprintf($sql, $idfield, $table, $this->Conn->qstr($ret) ) );
if($code_found) return $this->generateAffiliateCode($event);
return $ret;
}
/**
* Creates new affiliate code when new affiliate is created
*
* @param kEvent $event
*/
function OnBeforeItemCreate(&$event)
{
$object =& $event->getObject( Array('skip_autoload'=>true) );
$object->SetDBField('AffiliateCode', $this->generateAffiliateCode($event) );
}
/**
* Stores affiliate id using method from Config (session or cookie) if correct code is present in url
*
* @param kEvent $event
* @return bool
*/
function OnStoreAffiliate(&$event)
{
$event->Init($event->Prefix, '-item');
$object =& $event->getObject( Array('skip_autoload'=>true) );
$affiliate_storage_method = $this->Application->ConfigValue('Comm_AffiliateStorageMethod');
$affiliate = $this->Application->GetVar('affiliate');
if($affiliate)
{
$object->Load($affiliate, 'AffiliateCode');
}
elseif($affiliate_storage_method == 2)
{
$affiliate_id = $this->Application->GetVar('affiliate_id');
$object->Load($affiliate_id);
}
if( $object->isLoaded() && ($object->GetDBField('Status') == 1) )
{
// user is found with such email
$affiliate_user =& $this->Application->recallObject('u.affiliate', null, Array('skip_autoload'=>true) );
$affiliate_user->Load( $object->GetDBField('PortalUserId') );
if($affiliate_user->GetDBField('Status') == 1)
{
$affiliate_id = $object->GetDBField('AffiliateId');
$this->Application->setVisitField('AffiliateId', $affiliate_id);
if($affiliate_storage_method == 1)
{
$this->Application->StoreVar('affiliate_id', $affiliate_id); // per session
}
else
{
- setcookie('affiliate_id', $affiliate_id, $this->getCookieExpiration(), BASE_PATH, '.'.SERVER_NAME); // in cookie
+ // in cookie
+ $this->Application->Session->SetCookie('affiliate_id', $affiliate_id, $this->getCookieExpiration());
}
}
}
}
/**
* Returns affiliate cookie expiration date
*
* @return int
*/
function getCookieExpiration()
{
$expire = $this->Application->ConfigValue('Comm_AffiliateCookieDuration'); // days
return adodb_mktime() + $expire * 24 * 60 * 60;
}
/**
* Calculate what amount is earned by affiliate based on it's affiliate plan & store it
*
* @param kEvent $event
* @author Alex
*/
function OnOrderApprove(&$event)
{
$order =& $this->Application->recallObject( $event->getEventParam('Order_PrefixSpecial') );
$affiliate_id = $order->GetDBField('AffiliateId');
if(!$affiliate_id) return false;
$object =& $event->getObject( Array('ship_autoload' => true) );
if( $object->Load($affiliate_id) )
{
$affiliate_plan =& $this->Application->recallObject('ap', null, Array('skip_autoload'=>true) );
$affiliate_plan->Load( $object->GetDBField('AffiliatePlanId') );
if( $affiliate_plan->isLoaded() )
{
$sql = 'SELECT SUM(Quantity) FROM %s WHERE OrderId = %s';
$orderitems_table = $this->Application->getUnitOption('orditems', 'TableName');
$items_sold = $this->Conn->GetOne( sprintf($sql, $orderitems_table, $order->GetID() ) );
$object->SetDBField('AccumulatedAmount', $object->GetDBField('AccumulatedAmount') + $order->GetDBField('TotalAmount') );
$object->SetDBField('ItemsSold', $object->GetDBField('ItemsSold') + $items_sold);
switch( $affiliate_plan->GetDBField('PlanType') )
{
case 1: // by amount
$value = $object->GetDBField('AccumulatedAmount');
break;
case 2: // by items sold (count)
$value = $object->GetDBField('ItemsSold');
break;
}
$apb_table = $this->Application->getUnitOption('apbrackets', 'TableName');
$sql = 'SELECT Percent FROM %1$s WHERE (%2$s >= FromAmount) AND ( (%2$s <= ToAmount) OR (ToAmount = -1) ) AND (AffiliatePlanId = %3$s)';
$commission_percent = $this->Conn->GetOne( sprintf($sql, $apb_table, $this->Conn->qstr($value), $affiliate_plan->GetID() ) );
// process only orders of current affiliate from period start to this order date
$period_ends = $order->GetDBField('OrderDate');
$period_starts = $this->getPeriodStartTS( $period_ends, $affiliate_plan->GetDBField('ResetInterval') );
$sql = 'SELECT AffiliateCommission, (SubTotal+ShippingCost+VAT) AS TotalAmount, OrderId FROM '.$order->TableName.' WHERE OrderDate >= %s AND OrderDate <= %s';
$amount_to_pay_before = 0;
$amount_to_pay_after = 0;
$order_update_sql = 'UPDATE '.$order->TableName.' SET AffiliateCommission = %s WHERE '.$order->IDField.' = %s';
$orders = $this->Conn->Query( sprintf($sql, $period_starts, $period_ends), 'OrderId' );
if($orders)
{
foreach($orders as $order_id => $order_data)
{
$amount_to_pay_before += $order_data['AffiliateCommission'];
$commission = $order_data['TotalAmount'] * ($commission_percent / 100);
$this->Conn->Query( sprintf($order_update_sql, $this->Conn->qstr($commission), $order_id) );
$amount_to_pay_after += $commission;
}
}
$object->SetDBField('AmountToPay', $object->GetDBField('AmountToPay') - $amount_to_pay_before + $amount_to_pay_after );
$object->SetDBField('LastOrderDate_date', $order->GetDBField('OrderDate_date') );
$object->SetDBField('LastOrderDate_time', $order->GetDBField('OrderDate_time') );
$object->Update();
$order->SetDBField('AffiliateCommission', $commission); // set last commission to this order, because ApproveEvent was called for him
}
}
}
function OnCheckAffiliateAgreement(&$event)
{
$user_object =& $this->Application->recallObject('u', null, Array('skip_autoload' => true));
$items_info = $this->Application->GetVar('u');
if($items_info)
{
list($id,$field_values) = each($items_info);
$user_object->SetFieldsFromHash($field_values);
$user_object->setID($id);
$user_object->setLogin();
}
$require_affiliate = ($this->Application->GetVar('RegisterAsAffiliate') == 'on');
if($require_affiliate && !$this->Application->GetVar('AgreeToAffiliateTerms') )
{
$this->Application->SetVar('MustAgreeToTerms', 1);
$event->MasterEvent->status = erFATAL;
}
if($require_affiliate && !$this->Application->GetVar('SSN') )
{
$this->Application->SetVar('SSNRequiredError', 1);
$event->MasterEvent->status = erFATAL;
}
if( ($event->MasterEvent->status == erFATAL) && $items_info ) $user_object->Validate();
}
/**
* [AFTER HOOK] to u:OnCreate
*
* @param kEvent $event
*/
function OnRegisterAsAffiliate(&$event)
{
if($this->Application->GetVar('RegisterAsAffiliate') != 'on' || $event->MasterEvent->status != erSUCCESS)
{
return;
}
$object =& $event->getObject( Array('skip_autoload' => true) );
$sql = 'SELECT AffiliatePlanId FROM '.$this->Application->getUnitOption('ap', 'TableName').'
WHERE IsPrimary = 1';
$affiliate_plan = $this->Conn->GetOne($sql);
$object->SetDBField('PortalUserId', $this->Application->GetVar('u.current_id'));
$object->SetDBField('Status', 2);
$object->SetDBField('AffiliatePlanId', $affiliate_plan);
$object->SetDBField('SSN', $this->Application->GetVar('SSN'));
$object->SetDBField('Comments', $this->Application->GetVar('Comments'));
$object->SetDBField('PaymentTypeId', $this->Application->GetVar('PaymentTypeId'));
$object->Create();
$email_event_user =& $this->Application->EmailEventUser('AFFILIATE.REGISTER', $this->Application->GetVar('u.current_id'));
$email_event_admin =& $this->Application->EmailEventAdmin('AFFILIATE.REGISTER');
}
function OnBecomeAffiliate(&$event)
{
if(!$this->Application->GetVar('AgreeToAffiliateTerms'))
{
$this->Application->SetVar('MustAgreeToTerms', 1);
$event->status = erFATAL;
}
if(!$this->Application->GetVar('SSN'))
{
$this->Application->SetVar('SSNRequiredError', 1);
$event->status = erFATAL;
}
if($event->status == erFATAL)
{
return;
}
$object =& $event->getObject( Array('skip_autoload' => true) );
$sql = 'SELECT AffiliatePlanId FROM '.$this->Application->getUnitOption('ap', 'TableName').'
WHERE IsPrimary = 1';
$affiliate_plan = $this->Conn->GetOne($sql);
$object->SetDBField('PortalUserId', $this->Application->RecallVar('user_id'));
$object->SetDBField('Status', 2);
$object->SetDBField('AffiliatePlanId', $affiliate_plan);
$object->SetDBField('SSN', $this->Application->GetVar('SSN'));
$object->SetDBField('Comments', $this->Application->GetVar('Comments'));
$object->SetDBField('PaymentTypeId', $this->Application->GetVar('PaymentTypeId'));
$object->Create();
if($next_template = $this->Application->GetVar('next_template'))
{
$event->redirect = $next_template;
}
$email_event_user =& $this->Application->EmailEventUser('AFFILIATE.REGISTER', $this->Application->RecallVar('user_id'));
$email_event_admin =& $this->Application->EmailEventAdmin('AFFILIATE.REGISTER');
}
function OnChangePaymentType(&$event)
{
$user_id = $this->Application->RecallVar('user_id');
$object =& $event->getObject( Array('skip_autoload' => true) );
$object->Load( Array('PortalUserId' => $user_id) );
$object->SetDBField('Comments', $this->Application->GetVar('Comments'));
$object->SetDBField('PaymentTypeId', $this->Application->GetVar('PaymentTypeId'));
$object->Update();
$email_event_user =& $this->Application->EmailEventUser('AFFILIATE.PAYMENT.TYPE.CHANGED', $user_id);
$email_event_admin =& $this->Application->EmailEventAdmin('AFFILIATE.PAYMENT.TYPE.CHANGED');
$event->redirect = $this->Application->GetVar('next_template');
$event->status = erSUCCESS;
}
/**
* If new payments made, then send email about that
*
* @param kEvent $event
*/
function OnBeforeDeleteFromLive(&$event)
{
$payment_object =& $this->Application->recallObject('apayments', 'apayments', Array('skip_autoload' => true) );
$id = $event->getEventParam('id');
$ap_table = $this->Application->getUnitOption('apayments', 'TableName');
$sql = 'SELECT AffiliatePaymentId FROM '.$ap_table.' WHERE AffiliateId = '.$id;
$live_ids = $this->Conn->GetCol($sql);
$sql = 'SELECT AffiliatePaymentId FROM '.$payment_object->TableName.' WHERE AffiliateId = '.$id;
$temp_ids = $this->Conn->GetCol($sql);
$new_ids = array_diff($temp_ids, $live_ids);
foreach($new_ids as $payment_id)
{
$payment_object->Load($payment_id);
$email_event_user =& $this->Application->EmailEventUser('AFFILIATE.PAYMENT', $payment_object->GetDBField('PortalUserId'));
$email_event_admin =& $this->Application->EmailEventAdmin('AFFILIATE.PAYMENT');
}
$object =& $event->getObject();
$passed_id = $event->getEventParam('id');
if( $object->GetID() != $passed_id )
{
$object->Load($passed_id);
}
$sql = 'SELECT Status FROM '.$this->Application->getUnitOption( $event->Prefix, 'TableName' ).' WHERE '.$object->IDField.' = '.$object->GetID();
$old_status = $this->Conn->GetOne($sql);
if( $old_status == 2 && $object->GetDBField('Status') == 1 )
{
$email_event_user =& $this->Application->EmailEventUser('AFFILIATE.REGISTRATION.APPROVED', $object->GetDBField('PortalUserId'));
$email_event_admin =& $this->Application->EmailEventAdmin('AFFILIATE.REGISTRATION.APPROVED');
}
}
/**
* Resets statistics (accumulated amount & items sold) for affiliates based on ResetInterval in their plan
*
* @param kEvent $event
* @author Alex
*/
function OnResetStatistics(&$event)
{
$intervals = Array(86400 => 'la_day', 604800 => 'la_week', 2628000 => 'la_month', 7884000 => 'la_quartely', 31536000 => 'la_year');
$affil_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
$ap_table = $this->Application->getUnitOption('ap', 'TableName');
$sql = 'SELECT AffiliateId
FROM '.$affil_table.' a
LEFT JOIN '.$ap_table.' ap ON a.AffiliatePlanId = ap.AffiliatePlanId';
$base_time = adodb_mktime();
$where_clause = Array();
foreach($intervals as $interval_length => $interval_description)
{
$start_timestamp = $this->getPeriodStartTS($base_time, $interval_length);
$where_clause[] = 'ap.ResetInterval = '.$interval_length.' AND LastOrderDate < '.$start_timestamp;
}
$sql .= ' WHERE ('.implode(') OR (', $where_clause).')';
$affiliate_ids = $this->Conn->GetCol($sql);
if ($affiliate_ids && defined('DEBUG_MODE') && DEBUG_MODE && $this->Application->isDebugMode()) {
$this->Application->Debugger->appendHTML('Affiliates Pending Totals Reset: ');
print_pre($affiliate_ids);
}
$sql = 'UPDATE '.$affil_table.' SET AccumulatedAmount = 0, ItemsSold = 0, LastOrderDate = %s WHERE AffiliateId IN (%s)';
if($affiliate_ids) $this->Conn->Query( sprintf($sql, $base_time, implode(',', $affiliate_ids) ) );
}
/**
* Returns calendar period start timestamp based on current timestamp ($base_time) and $period_length
*
* @param int $base_time
* @param int $period_length
* @return int
* @author Alex
*/
function getPeriodStartTS($base_time, $period_length)
{
switch($period_length)
{
case 86400: // day
$start_timestamp = adodb_mktime(0,0,0, adodb_date('m', $base_time), adodb_date('d', $base_time), adodb_date('Y', $base_time) );
break;
case 604800: // week
$day_seconds = 86400;
$first_week_day = $this->Application->ConfigValue('FirstDayOfWeek');
$morning = adodb_mktime(0,0,0, adodb_date('m', $base_time), adodb_date('d', $base_time), adodb_date('Y', $base_time) );
$week_day = adodb_date('w', $morning);
if($week_day == $first_week_day)
{
// if it is already first week day, then don't search for previous week day
$day_diff = 0;
}
else
{
// this way, because sunday is 0, but not 7 as it should be
$day_diff = $week_day != 0 ? $week_day - $first_week_day: 7 - $first_week_day;
}
$start_timestamp = $morning - $day_diff * $day_seconds;
break;
case 2628000: // month
$start_timestamp = adodb_mktime(0,0,0, adodb_date('m', $base_time), 1, adodb_date('Y', $base_time) );
break;
case 7884000: // quartal
$first_quartal_month = (ceil( adodb_date('m', $base_time) / 3)-1)*3 + 1;
$start_timestamp = adodb_mktime(0,0,0, $first_quartal_month, 1, adodb_date('Y', $base_time) );
break;
case 31536000:
$start_timestamp = adodb_mktime(0,0,0,1,1, adodb_date('Y', $base_time) );
break;
}
return $start_timestamp;
}
function iterateItems(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = erFAIL;
return;
}
$object =& $event->getObject( Array('skip_autoload' => true) );
$ids = $this->StoreSelectedIDs($event);
if($ids)
{
$status_field = array_shift( $this->Application->getUnitOption($event->Prefix,'StatusField') );
foreach($ids as $id)
{
$object->Load($id);
switch ($event->Name)
{
case 'OnMassApprove':
$object->SetDBField($status_field, 1);
break;
case 'OnMassDecline':
$object->SetDBField($status_field, 0);
break;
case 'OnMassMoveUp':
$object->SetDBField('Priority', $object->GetDBField('Priority') + 1);
break;
case 'OnMassMoveDown':
$object->SetDBField('Priority', $object->GetDBField('Priority') - 1);
break;
}
if( $object->Update() )
{
switch ($event->Name)
{
case 'OnMassApprove':
$email_event_user =& $this->Application->EmailEventUser('AFFILIATE.REGISTRATION.APPROVED', $object->GetDBField('PortalUserId'));
$email_event_admin =& $this->Application->EmailEventAdmin('AFFILIATE.REGISTRATION.APPROVED');
break;
case 'OnMassDecline':
$email_event_user =& $this->Application->EmailEventUser('AFFILIATE.REGISTRATION.DENIED', $object->GetDBField('PortalUserId'));
$email_event_admin =& $this->Application->EmailEventAdmin('AFFILIATE.REGISTRATION.DENIED');
break;
}
$event->status=erSUCCESS;
$event->redirect_params = Array('opener' => 's'); //stay!
}
else
{
$event->status=erFAIL;
$event->redirect=false;
break;
}
}
}
}
/**
* Checks that user in affiliate record matches current user
* (non permission-based)
*
* @param kEvent $event
* @return bool
*/
function checkItemStatus(&$event)
{
if ($this->Application->isAdminUser) {
return true;
}
$object =& $event->getObject();
if (!$object->isLoaded()) {
return true;
}
return $object->GetDBField('PortalUserId') == $this->Application->RecallVar('user_id');
}
}
\ No newline at end of file

Event Timeline