Vendor promotions has been a requested feature for some time - see, for example, http://cscart.uservo…or-multi-vendor
However, CS Cart development has been too busy on other things to get around to it.
It turns out that it is quite easy to get a fairly workable partial implementation going - with minimal changes to core CS Cart code. I am sharing what I have done here in the hope that:[list]
[]Others may find it useful
[]Those with development skills might check and extend what I have done
[*]CS Cart will eventually take over the code and incorporate it into the standard MV code
[/list]
My changes are based on MV 4.1.2
Limitations:
Gift certificates and coupons are not supported. Currently these are tied to the store rather than the vendor. I have not attempted to get them working.
Core code changes:
app/functions/fn.promotions.php - 3 lines changed. In function fn_promotion_apply $promotions is no longer static and $promotions are fetched on every function call
app/schemas/permissions/vendor_multivendor.php - 2 lines changed. Enables the Marketing|Promotions menu for vendors (thanks TBirnseth!)
app/schemas/promotions/schema.php - a number of lines commented out to removed unsupported promotion condition and bonus options. For example, gift certificates and coupons are not supported.
design/backend/templates/views/promotions/manage.tpl - This is optional. I chose to disable vendor catalog promotions because I think they are confusing for my vendors. Vendors can achieve the same effect simply by modifying product prices in the usual way. However, although I haven’t tested them as much, I think that catalog promotions do seem to work for vendors. If you want to allow them, you do not need to apply this core change. (I have uploaded this as manage.tpl.php because it wouldn’t let me upload a .tpl file - you will need to rename it)
Other changes:
All the other changes are in external add on code which I have placed under app/addons/my_changes. These changes are:
app/addons/my_changes/controllers/backend/promotions.pre.php is needed so that vendor promotions are associated with the vendor id - rather than being global “store” promotions
app/addons/my_changes/init.php needs to register the following hooks:
<br />
fn_register_hooks(<br />
'calculate_cart_taxes_post',<br />
'get_promotions',<br />
...<br />
```<br />
<br />
[u][b][u][b]app/addons/my_changes/[/b][/u]func.php[/b][/u] needs to implement the hook code. This is the major amount of code - but it is all quite straight forward. I have really just copied and pasted the standard CS Cart promotion code so that it is applied to vendor sub orders.<br />
Here are the hook functions:<br />
<br />
```php
<br />
/**<br />
* This hook is used in customer code to fetch promotions by company_id if<br />
* appropriate.<br />
*/<br />
function fn_my_changes_get_promotions(<br />
&$params, &$fields, &$sortings, &$condition, &$join)<br />
{<br />
if (AREA == 'C') {<br />
//Customer case. This is called when...<br />
// a) calculating promotions by vendor. ie group.company_id is defined<br />
// <img src="upload://koLv6Nwy6blpxWjsJR7cOIcv8Nz.png" class="bbc_emoticon" alt="B)"> calculating global promotions only. We do not want to get vendor<br />
// promotions as well so we need to explicitly specify<br />
// company_id = 0.<br />
$company_id = Registry::get('group.company_id');<br />
if (empty($company_id)) {<br />
if (strpos($condition, ':promotions.promotion_id') !== false) {<br />
//If promotions are being retrieved by promotion_id we don't<br />
//need to append a new condition, leave company_id empty.<br />
} else {<br />
//Set it to an explicit version of 0 that won't get filtered out<br />
//by the "if (!$company_id)" code in fn_get_company_condition.<br />
//That means that will add a ?:promotions.company_id = 0 to the<br />
//SQL and return only global promotions - not vendor specific ones.<br />
$company_id = '00';<br />
}<br />
}<br />
$condition .= fn_get_company_condition(<br />
'?:promotions.company_id', true, $company_id, false, true);<br />
}<br />
}<br />
<br />
/**<br />
* Hooks into fn_calculate_cart_content of fn.cart.php which is called by<br />
* checkout.php.<br />
* <p/><br />
* This hook is placed after product groups have been established and global<br />
* promotions have been applied.<br />
* We use the product groups as promotion groups, iterating through each<br />
* group applying promotions for a given vendor and that vendor's products.<br />
*/<br />
function fn_my_changes_calculate_cart_taxes_post(<br />
&$cart, &$cart_products, &$shipping_rates, &$calculate_taxes, &$auth)<br />
{<br />
<br />
// Apply cart promotions<br />
$cart['subtotal_discount'] = 0;<br />
<br />
$product_groups = $cart['product_groups'];<br />
<br />
foreach ($product_groups as $key_group => $group) {<br />
$company_id = $group['company_id'];<br />
Registry::set('group.company_id', $company_id);<br />
<br />
//Compute group totals.<br />
$amount_totals = array();<br />
if (Registry::get('settings.General.disregard_options_for_discounts') == 'Y') {<br />
foreach ($group['products'] as $k => $v) {<br />
if (!empty($amount_totals[$v['product_id']])) {<br />
$amount_totals[$v['product_id']] += $v['amount'];<br />
} else {<br />
$amount_totals[$v['product_id']] = $v['amount'];<br />
}<br />
}<br />
}<br />
<br />
$group_products = array();<br />
foreach ($group['products'] as $k => $v) {<br />
$group['products'][$k]['amount_total'] = isset($amount_totals[$v['product_id']]) ? $amount_totals[$v['product_id']] : $v['amount'];<br />
<br />
$_cproduct = fn_get_cart_product_data($k, $group['products'][$k], false, $group, $auth);<br />
if (empty($_cproduct)) { // FIXME - for deleted products for OM<br />
unset($group['products'][$k]);<br />
continue;<br />
}<br />
<br />
$group_products[$k] = $_cproduct;<br />
}<br />
<br />
//If there is anything in the group, apply the promotion rules to it.<br />
if ($group['subtotal'] >= 0) {<br />
//Accumulate promotions<br />
$applied_promotions = fn_promotion_apply('cart', $group, $auth, $group_products);<br />
<br />
if (!empty($applied_promotions)) {<br />
if (empty($cart['applied_promotions'])) {<br />
$cart['applied_promotions'] = $applied_promotions;<br />
} else {<br />
$cart['applied_promotions'] += $applied_promotions;<br />
}<br />
}<br />
<br />
if (!empty($group['promotions'])) {<br />
if (empty($cart['promotions'])) {<br />
$cart['promotions'] = $group['promotions'];<br />
} else {<br />
$cart['promotions'] += $group['promotions'];<br />
}<br />
}<br />
<br />
if (!$group['no_promotions']) {<br />
$cart['no_promotions'] = false;<br />
}<br />
<br />
//Need to sum the group promotion discounts in the overall cart discount<br />
$cart['subtotal_discount'] += $group['subtotal_discount'];<br />
}<br />
}<br />
<br />
Registry::del('group.company_id');<br />
fn_check_promotion_notices();<br />
<br />
}<br />
```<p><a href="127.0.0.1/uploads/monthly_02_2014/post-20481-0-47544900-1392774901.ipb">fn.promotions.php</a></p><p><a href="127.0.0.1/uploads/monthly_02_2014/post-20481-0-62958900-1392775185.ipb">vendor_multivendor.php</a></p><p><a href="127.0.0.1/uploads/monthly_02_2014/post-20481-0-60934600-1392775375.ipb">schema.php</a></p><p><a href="127.0.0.1/uploads/monthly_02_2014/post-20481-0-72785300-1392775955.ipb">manage.tpl.php</a></p><p><a href="127.0.0.1/uploads/monthly_02_2014/post-20481-0-79031300-1392776970.ipb">promotions.pre.php</a></p>