[+] Project : Add specific prices to a specific customer

This commit is contained in:
jBreux
2011-12-19 15:31:18 +00:00
parent a83b71541f
commit bd27a0ea15
7 changed files with 182 additions and 22 deletions
@@ -24,6 +24,102 @@
* International Registered Trademark & Property of PrestaShop SA
*}
{* BEGIN CUSTOMER AUTO-COMPLETE / TO REFACTO *}
{literal}
<script type="text/javascript">
var Customer = {
"hiddenField": jQuery('#id_customer'),
"field": jQuery('#customer'),
"container": jQuery('#customers'),
"loader": jQuery('#customerLoader'),
"init": function() {
jQuery(Customer.field).typeWatch({
"captureLength": 1,
"highlight": true,
"wait": 50,
"callback": Customer.search
}).focus(Customer.placeholderIn).blur(Customer.placeholderOut);
},
"placeholderIn": function() {
if (this.value == '{/literal}{l s='All customers'}{literal}') {
this.value = '';
}
},
"placeholderOut": function() {
if (this.value == '') {
this.value = '{/literal}{l s='All customers'}{literal}';
}
},
"search": function()
{
Customer.showLoader();
jQuery.ajax({
"type": "POST",
"url": "{/literal}{$link->getAdminLink('AdminProducts')}{literal}",
"async": true,
"dataType": "json",
"data": {
"ajax": "1",
"token": "{/literal}{$token}{literal}",
"tab": "AdminProducts",
"action": "searchCustomers",
"customer_search": Customer.field.val()
},
"success": Customer.success
});
},
"success": function(result)
{
if(result.found) {
var html = '<ul class="clearfix">';
jQuery.each(result.customers, function() {
html += '<li><a class="fancybox" href="{/literal}{$link->getAdminLink('AdminCustomers')}{literal}&id_customer='+this.id_customer+'&viewcustomer&liteDisplaying=1">'+this.firstname+' '+this.lastname+'</a>'+(this.birthday ? ' - '+this.birthday:'')+'<br/>';
html += '<a href="mailto:'+this.email+'">'+this.email+'</a><br />';
html += '<a onclick="Customer.select('+this.id_customer+', \''+this.firstname+' '+this.lastname+'\'); return false;" href="#" class="button">{/literal}{l s='Choose'}{literal}</a></li>';
});
html += '</ul>';
}
else
html = '<div class="warn">{/literal}{l s='No customers found'}{literal}</div>';
Customer.hideLoader();
Customer.container.html(html);
jQuery('.fancybox', Customer.container).fancybox();
},
"select": function(id_customer, fullname)
{
Customer.hiddenField.val(id_customer);
Customer.field.val(fullname);
Customer.container.empty();
return false;
},
"showLoader": function() {
Customer.loader.fadeIn();
},
"hideLoader": function() {
Customer.loader.fadeOut();
}
};
jQuery(document).ready(Customer.init);
</script>
<style type="text/css">
#content #customers .warn {
margin: 10px 0 0 0;
}
#customers li {
background-color: #ABDFF7;
border: 1px solid #ccc;
float: left;
margin: 5px;
padding: 5px;
}
#customers li .button {
display: block;
margin-top: 5px;
}
</style>
{/literal}
{* END CUSTOMER AUTO-COMPLETE / TO REFACTO *}
<script type="text/javascript">
$(document).ready(function() {
@@ -195,6 +291,13 @@
{/foreach}
</select>
</div>
<label>{l s='Customer:'}</label>
<div class="margin-form">
<input type="hidden" name="sp_id_customer" id="id_customer" value="0" />
<input type="text" name="customer" value="{l s='All customers'}" id="customer" autocomplete="off" />
<img src="../img/admin/field-loader.gif" id="customerLoader" alt="{l s='Loading...'}" style="display: none;" />
<div id="customers"></div>
</div>
{if $combinations|@count != 0}
<label>{l s='Combination:'}</label>
<div class="margin-form">
@@ -281,6 +384,7 @@
<th class="cell border" style="width: 12%;">{l s='Currency'}</th>
<th class="cell border" style="width: 11%;">{l s='Country'}</th>
<th class="cell border" style="width: 13%;">{l s='Group'}</th>
<th class="cell border" style="width: 13%;">{l s='Customer'}</th>
<th class="cell border" style="width: 12%;">{l s='Price'} {if $country_display_tax_label}{l s='(tax excl)'}{/if}</th>
<th class="cell border" style="width: 10%;">{l s='Reduction'}</th>
<th class="cell border" style="width: 15%;">{l s='Period'}</th>
+17 -5
View File
@@ -2195,7 +2195,8 @@ class ProductCore extends ObjectModel
*/
public static function getPriceStatic($id_product, $usetax = true, $id_product_attribute = null, $decimals = 6, $divisor = null,
$only_reduc = false, $usereduc = true, $quantity = 1, $force_associated_tax = false, $id_customer = null, $id_cart = null,
$id_address = null, &$specific_price_output = null, $with_ecotax = true, $use_group_reduction = true, Context $context = null)
$id_address = null, &$specific_price_output = null, $with_ecotax = true, $use_group_reduction = true, Context $context = null,
$use_customer_price = true)
{
if (!$context)
$context = Context::getContext();
@@ -2282,6 +2283,10 @@ class ProductCore extends ObjectModel
&& Configuration::get('VATNUMBER_MANAGEMENT'))
$usetax = false;
$id_customer = 0;
if (Validate::isLoadedObject($context->customer))
$id_customer = $context->customer->id;
return Product::priceCalculation(
$context->shop->getID(),
$id_product,
@@ -2298,7 +2303,9 @@ class ProductCore extends ObjectModel
$usereduc,
$with_ecotax,
$specific_price_output,
$use_group_reduction
$use_group_reduction,
$id_customer,
$use_customer_price
);
}
@@ -2324,8 +2331,12 @@ class ProductCore extends ObjectModel
* @return float Product price
**/
public static function priceCalculation($id_shop, $id_product, $id_product_attribute, $id_country, $id_state, $zipcode, $id_currency,
$id_group, $quantity, $use_tax, $decimals, $only_reduc, $use_reduc, $with_ecotax, &$specific_price, $use_group_reduction)
$id_group, $quantity, $use_tax, $decimals, $only_reduc, $use_reduc, $with_ecotax, &$specific_price, $use_group_reduction,
$id_customer = 0, $use_customer_price = true)
{
if (!$use_customer_price)
$id_customer = 0;
// Caching
if ($id_product_attribute === null)
$product_attribute_label = 'null';
@@ -2333,7 +2344,7 @@ class ProductCore extends ObjectModel
$product_attribute_label = ($id_product_attribute === false ? 'false' : $id_product_attribute);
$cache_id = $id_product.'-'.$id_shop.'-'.$id_currency.'-'.$id_country.'-'.$id_state.'-'.$zipcode.'-'.$id_group.
'-'.$quantity.'-'.$product_attribute_label.'-'.($use_tax?'1':'0').'-'.$decimals.'-'.($only_reduc?'1':'0').
'-'.($use_reduc?'1':'0').'-'.$with_ecotax;
'-'.($use_reduc?'1':'0').'-'.$with_ecotax.'-'.$id_customer;
// reference parameter is filled before any returns
$specific_price = SpecificPrice::getSpecificPrice(
@@ -2343,7 +2354,8 @@ class ProductCore extends ObjectModel
$id_country,
$id_group,
$quantity,
$id_product_attribute
$id_product_attribute,
$id_customer
);
if (isset(self::$_prices[$cache_id]))
+16 -9
View File
@@ -35,6 +35,7 @@ class SpecificPriceCore extends ObjectModel
public $id_currency;
public $id_country;
public $id_group;
public $id_customer;
public $price;
public $from_quantity;
public $reduction;
@@ -57,6 +58,7 @@ class SpecificPriceCore extends ObjectModel
'id_specific_price_rule' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
'id_country' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true),
'id_group' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true),
'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true),
'price' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true),
'from_quantity' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true),
'reduction' => array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true),
@@ -108,7 +110,7 @@ class SpecificPriceCore extends ObjectModel
}
// score generation for quantity discount
protected static function _getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group)
protected static function _getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_customer)
{
$select = '(';
@@ -141,10 +143,11 @@ class SpecificPriceCore extends ObjectModel
if (!$priority)
$priority = Configuration::get('PS_SPECIFIC_PRICE_PRIORITIES');
$priority = 'id_customer;'.$priority;
return preg_split('/;/', $priority);
}
public static function getSpecificPrice($id_product, $id_shop, $id_currency, $id_country, $id_group, $quantity, $id_product_attribute = null)
public static function getSpecificPrice($id_product, $id_shop, $id_currency, $id_country, $id_group, $quantity, $id_product_attribute = null, $id_customer = 0)
{
if (!self::isFeatureActive())
return array();
@@ -158,7 +161,7 @@ class SpecificPriceCore extends ObjectModel
{
$now = date('Y-m-d H:i:s');
self::$_specificPriceCache[$key] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
SELECT *, '.self::_getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group).'
SELECT *, '.self::_getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_customer).'
FROM `'._DB_PREFIX_.'specific_price`
WHERE `id_product` IN (0, '.(int)$id_product.')
AND `id_product_attribute` IN (0, '.(int)$id_product_attribute.')
@@ -166,6 +169,7 @@ class SpecificPriceCore extends ObjectModel
AND `id_currency` IN (0, '.(int)$id_currency.')
AND `id_country` IN (0, '.(int)$id_country.')
AND `id_group` IN (0, '.(int)$id_group.')
AND `id_customer` IN (0, '.(int)$id_customer.')
AND `from_quantity` <= '.(int)$quantity.'
AND
(
@@ -209,7 +213,7 @@ class SpecificPriceCore extends ObjectModel
');
}
public static function getQuantityDiscounts($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_product_attribute = null, $all_combinations = false)
public static function getQuantityDiscounts($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_product_attribute = null, $all_combinations = false, $id_customer = 0)
{
if (!self::isFeatureActive())
return array();
@@ -217,7 +221,7 @@ class SpecificPriceCore extends ObjectModel
$now = date('Y-m-d H:i:s');
$res = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
SELECT *,
'.self::_getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group).'
'.self::_getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_customer).'
FROM `'._DB_PREFIX_.'specific_price`
WHERE
`id_product` IN(0, '.(int)$id_product.') AND
@@ -225,7 +229,8 @@ class SpecificPriceCore extends ObjectModel
`id_shop` IN(0, '.(int)$id_shop.') AND
`id_currency` IN(0, '.(int)$id_currency.') AND
`id_country` IN(0, '.(int)$id_country.') AND
`id_group` IN(0, '.(int)$id_group.')
`id_group` IN(0, '.(int)$id_group.') AND
`id_customer` IN(0, '.(int)$id_customer.')
AND
(
(`from` = \'0000-00-00 00:00:00\' OR \''.$now.'\' >= `from`)
@@ -253,7 +258,7 @@ class SpecificPriceCore extends ObjectModel
return $targeted_prices;
}
public static function getQuantityDiscount($id_product, $id_shop, $id_currency, $id_country, $id_group, $quantity, $id_product_attribute = null)
public static function getQuantityDiscount($id_product, $id_shop, $id_currency, $id_country, $id_group, $quantity, $id_product_attribute = null, $id_customer = 0)
{
if (!self::isFeatureActive())
return array();
@@ -261,7 +266,7 @@ class SpecificPriceCore extends ObjectModel
$now = date('Y-m-d H:i:s');
return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
SELECT *,
'.self::_getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group).'
'.self::_getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_customer).'
FROM `'._DB_PREFIX_.'specific_price`
WHERE
`id_product` IN(0, '.(int)$id_product.') AND
@@ -270,6 +275,7 @@ class SpecificPriceCore extends ObjectModel
`id_currency` IN(0, '.(int)$id_currency.') AND
`id_country` IN(0, '.(int)$id_country.') AND
`id_group` IN(0, '.(int)$id_group.') AND
`id_customer` IN(0, '.(int)$id_customer.') AND
`from_quantity` >= '.(int)$quantity.'
AND
(
@@ -281,7 +287,7 @@ class SpecificPriceCore extends ObjectModel
');
}
public static function getProductIdByDate($id_shop, $id_currency, $id_country, $id_group, $beginning, $ending)
public static function getProductIdByDate($id_shop, $id_currency, $id_country, $id_group, $beginning, $ending, $id_customer = 0)
{
if (!self::isFeatureActive())
return array();
@@ -293,6 +299,7 @@ class SpecificPriceCore extends ObjectModel
`id_currency` IN(0, '.(int)$id_currency.') AND
`id_country` IN(0, '.(int)$id_country.') AND
`id_group` IN(0, '.(int)$id_group.') AND
`id_customer` IN(0, '.(int)$id_customer.') AND
`from_quantity` = 1 AND
(
(`from` = \'0000-00-00 00:00:00\' OR \''.pSQL($beginning).'\' >= `from`)
+38 -7
View File
@@ -689,6 +689,7 @@ class AdminProductsControllerCore extends AdminController
$id_currencies = Tools::getValue('spm_id_currency');
$id_countries = Tools::getValue('spm_id_country');
$id_groups = Tools::getValue('spm_id_group');
$id_customers = Tools::getValue('spm_id_customer');
$prices = Tools::getValue('spm_price');
$from_quantities = Tools::getValue('spm_from_quantity');
$reductions = Tools::getValue('spm_reduction');
@@ -697,13 +698,14 @@ class AdminProductsControllerCore extends AdminController
$tos = Tools::getValue('spm_to');
foreach ($id_specific_prices as $key => $id_specific_price)
if ($this->_validateSpecificPrice($id_shops[$key], $id_currencies[$key], $id_countries[$key], $id_groups[$key], $prices[$key], $from_quantities[$key], $reductions[$key], $reduction_types[$key], $froms[$key], $tos[$key]))
if ($this->_validateSpecificPrice($id_shops[$key], $id_currencies[$key], $id_countries[$key], $id_groups[$key], $id_customers[$key], $prices[$key], $from_quantities[$key], $reductions[$key], $reduction_types[$key], $froms[$key], $tos[$key]))
{
$specific_price = new SpecificPrice((int)($id_specific_price));
$specific_price->id_shop = (int)$id_shops[$key];
$specific_price->id_currency = (int)($id_currencies[$key]);
$specific_price->id_country = (int)($id_countries[$key]);
$specific_price->id_group = (int)($id_groups[$key]);
$specific_price->id_customer = (int)$id_customers[$key];
$specific_price->price = (float)($prices[$key]);
$specific_price->from_quantity = (int)($from_quantities[$key]);
$specific_price->reduction = (float)($reduction_types[$key] == 'percentage' ? ($reductions[$key] / 100) : $reductions[$key]);
@@ -725,13 +727,14 @@ class AdminProductsControllerCore extends AdminController
$id_currency = Tools::getValue('sp_id_currency');
$id_country = Tools::getValue('sp_id_country');
$id_group = Tools::getValue('sp_id_group');
$id_customer = Tools::getValue('sp_id_customer');
$price = Tools::getValue('sp_price');
$from_quantity = Tools::getValue('sp_from_quantity');
$reduction = (float)(Tools::getValue('sp_reduction'));
$reduction_type = !$reduction ? 'amount' : Tools::getValue('sp_reduction_type');
$from = Tools::getValue('sp_from');
$to = Tools::getValue('sp_to');
if ($this->_validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $price, $from_quantity, $reduction, $reduction_type, $from, $to))
if ($this->_validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $id_customer, $price, $from_quantity, $reduction, $reduction_type, $from, $to))
{
$specificPrice = new SpecificPrice();
$specificPrice->id_product = $id_product;
@@ -740,6 +743,7 @@ class AdminProductsControllerCore extends AdminController
$specificPrice->id_currency = (int)($id_currency);
$specificPrice->id_country = (int)($id_country);
$specificPrice->id_group = (int)($id_group);
$specificPrice->id_customer = (int)$id_customer;
$specificPrice->price = (float)($price);
$specificPrice->from_quantity = (int)($from_quantity);
$specificPrice->reduction = (float)($reduction_type == 'percentage' ? $reduction / 100 : $reduction);
@@ -1138,6 +1142,19 @@ class AdminProductsControllerCore extends AdminController
$this->status = 'ok';
}
/**
* Search customers
*/
public function ajaxProcessSearchCustomers()
{
if ($customers = Customer::searchByName(pSQL(Tools::getValue('customer_search'))))
$to_return = array('customers' => $customers, 'found' => true);
else
$to_return = array('found' => false);
$this->content = Tools::jsonEncode($to_return);
}
public function ajaxProcessUpdateImagePosition()
{
$this->json = true;
@@ -1197,9 +1214,9 @@ class AdminProductsControllerCore extends AdminController
}
}
protected function _validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $price, $from_quantity, $reduction, $reduction_type, $from, $to)
protected function _validateSpecificPrice($id_shop, $id_currency, $id_country, $id_group, $id_customer, $price, $from_quantity, $reduction, $reduction_type, $from, $to)
{
if (!Validate::isUnsignedId($id_shop) || !Validate::isUnsignedId($id_currency) || !Validate::isUnsignedId($id_country) || !Validate::isUnsignedId($id_group))
if (!Validate::isUnsignedId($id_shop) || !Validate::isUnsignedId($id_currency) || !Validate::isUnsignedId($id_country) || !Validate::isUnsignedId($id_group) || !Validate::isUnsignedId($id_customer))
$this->_errors[] = Tools::displayError('Wrong ID\'s');
else if ((empty($price) && empty($reduction)) || (!empty($price) && !Validate::isPrice($price)) || (!empty($reduction) && !Validate::isPrice($reduction)))
$this->_errors[] = Tools::displayError('Invalid price/reduction amount');
@@ -2068,7 +2085,9 @@ class AdminProductsControllerCore extends AdminController
return $this->tpl_form_vars['custom_form'];
}
return parent::renderForm();
$parent = parent::renderForm();
$this->addJqueryPlugin(array('autocomplete', 'fancybox', 'typewatch'));
return $parent;
}
public function getPreviewUrl(Product $product)
@@ -2540,7 +2559,9 @@ class AdminProductsControllerCore extends AdminController
'countries' => $countries,
'groups' => $groups,
'combinations' => $combinations,
'product' => $product
'product' => $product,
'link' => new Link,
'token' => $this->token
));
}
else
@@ -2745,7 +2766,7 @@ class AdminProductsControllerCore extends AdminController
if (!is_array($specific_prices) || !count($specific_prices))
$content .= '
<tr>
<td colspan="9">'.$this->l('No specific prices').'</td>
<td colspan="13">'.$this->l('No specific prices').'</td>
</tr>';
else
{
@@ -2777,6 +2798,14 @@ class AdminProductsControllerCore extends AdminController
$rule = new SpecificPriceRule((int)$specific_price['id_specific_price_rule']);
$rule_name = ($rule->id ? $rule->name : '--');
if ($specific_price['id_customer'])
{
$customer = new Customer((int)$specific_price['id_customer']);
if (Validate::isLoadedObject($customer))
$customer_full_name = $customer->firstname.' '.$customer->lastname;
unset($customer);
}
$content .= '
<tr '.($i%2 ? 'class="alt_row"' : '').'>
<td class="cell border">'.$rule_name.'</td>
@@ -2785,6 +2814,7 @@ class AdminProductsControllerCore extends AdminController
<td class="cell border">'.($specific_price['id_currency'] ? $currencies[$specific_price['id_currency']]['name'] : $this->l('All currencies')).'</td>
<td class="cell border">'.($specific_price['id_country'] ? $countries[$specific_price['id_country']]['name'] : $this->l('All countries')).'</td>
<td class="cell border">'.($specific_price['id_group'] ? $groups[$specific_price['id_group']]['name'] : $this->l('All groups')).'</td>
<td class="cell border" title="'.$this->l('ID:').' '.$specific_price['id_customer'].'">'.(isset($customer_full_name) ? $customer_full_name : $this->l('All customers')).'</td>
<td class="cell border">'.Tools::displayPrice((float)$specific_price['price'], $current_specific_currency).'</td>
<td class="cell border">'.$reduction.'</td>
<td class="cell border">'.$period.'</td>
@@ -2793,6 +2823,7 @@ class AdminProductsControllerCore extends AdminController
<td class="cell border">'.(!$rule->id ? '<a href="'.self::$currentIndex.(Tools::getValue('id_category') ? '&id_category='.Tools::getValue('id_category') : '').'&id_product='.(int)(Tools::getValue('id_product')).'&updateproduct&deleteSpecificPrice&action=Prices&id_specific_price='.(int)($specific_price['id_specific_price']).'&token='.Tools::getValue('token').'"><img src="../img/admin/delete.gif" alt="'.$this->l('Delete').'" /></a>': '').'</td>
</tr>';
$i++;
unset($customer_full_name);
}
}
$content .= '
Binary file not shown.

After

Width:  |  Height:  |  Size: 723 B

+2 -1
View File
@@ -1588,6 +1588,7 @@ CREATE TABLE `PREFIX_specific_price` (
`id_currency` INT UNSIGNED NOT NULL,
`id_country` INT UNSIGNED NOT NULL,
`id_group` INT UNSIGNED NOT NULL,
`id_customer` INT UNSIGNED NOT NULL,
`id_product_attribute` INT UNSIGNED NOT NULL,
`price` DECIMAL(20, 6) NOT NULL,
`from_quantity` mediumint(8) UNSIGNED NOT NULL,
@@ -1596,7 +1597,7 @@ CREATE TABLE `PREFIX_specific_price` (
`from` DATETIME NOT NULL,
`to` DATETIME NOT NULL,
PRIMARY KEY(`id_specific_price`),
KEY (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `from_quantity`, `from`, `to`),
KEY (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `id_customer`, `from_quantity`, `from`, `to`),
KEY (`id_specific_price_rule`)
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8;
+5
View File
@@ -51,6 +51,11 @@ ALTER TABLE `PREFIX_order_invoice` ADD `note` TEXT NOT NULL AFTER `total_wrappin
ALTER TABLE `PREFIX_order_state` ADD `paid` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `shipped`;
UPDATE `PREFIX_order_state` SET `paid` = 1 WHERE `id_order_state` IN (2, 3, 4, 5, 9, 12);
/* SPECIFIC PRICE */
ALTER TABLE `PREFIX_specific_price` ADD `id_customer` INT UNSIGNED NOT NULL AFTER `id_group`;
ALTER TABLE `PREFIX_specific_price` DROP INDEX `id_product` ,
ADD INDEX `id_product` (`id_product`, `id_shop`, `id_currency`, `id_country`, `id_group`, `id_customer`, `from_quantity`, `from`, `to`);
/************************
* STOCK MANAGEMENT
*************************/