[-] FO : #PSFV-797 - Fix bug with order detail and customized products

[-] BO : #PSFV-797 - Fix bug with order editing  and customized products

git-svn-id: http://dev.prestashop.com/svn/v1/branches/1.5.x@14607 b9a71923-0436-4b27-9f14-aed3839534dd
This commit is contained in:
mDeflotte
2012-04-12 13:02:18 +00:00
parent 713b9323c6
commit 99beaf6ed0
5 changed files with 218 additions and 124 deletions
@@ -23,9 +23,9 @@
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*}
{if ($product.customizedDatas)}
<tr>
{if $product.customizedDatas}
<tr class="customized customized-{$product.id_order_detail}">
<input type="hidden" class="edit_product_id_order_detail" value="{$product.id_order_detail}" />
<td align="center">{if ($product.image->id)}{$product.image_tag}{else}'--'{/if}</td>
<td>
<a href="index.php?controller=adminproducts&id_product={$product['product_id']}&updateproduct&token={getAdminToken tab='AdminProducts'}">
@@ -34,76 +34,89 @@
{if ($product['product_supplier_reference'])}{l s='Ref Supplier:'} {$product['product_supplier_reference']}{/if}
</a>
</td>
<td align="center">{displayPrice price=$product['product_price_wt'] currency=$currency->id}</td>
<td align="center">
<span class="product_price_show">{displayPrice price=$product['product_price_wt'] currency=$currency->id}</span>
{if $can_edit}
<span class="product_price_edit" style="display:none;">
<input type="hidden" name="product_id_order_detail" class="edit_product_id_order_detail" value="{$product['id_order_detail']}" />
{if $currency->sign % 2}{$currency->sign}{/if}<input type="text" name="product_price_tax_excl" class="edit_product_price_tax_excl edit_product_price" value="{Tools::ps_round($product['unit_price_tax_excl'], 2)}" size="5" /> {if !($currency->sign % 2)}{$currency->sign}{/if} {l s='tax excl.'}<br />
{if $currency->sign % 2}{$currency->sign}{/if}<input type="text" name="product_price_tax_incl" class="edit_product_price_tax_incl edit_product_price" value="{Tools::ps_round($product['unit_price_tax_incl'], 2)}" size="5" /> {if !($currency->sign % 2)}{$currency->sign}{/if} {l s='tax incl.'}
</span>
{/if}
</td>
<td align="center" class="productQuantity">{$product['customizationQuantityTotal']}</td>
{if ($order->hasBeenPaid())}<td align="center" class="productQuantity">{$product['customizationQuantityRefunded']}</td>{/if}
{if ($order->hasBeenDelivered())}<td align="center" class="productQuantity">{$product['customizationQuantityReturned']}</td>{/if}
<td align="center" class="productQuantity"> - </td>
<td align="center">
<td align="center" class=""> - </td>
<td align="center" class="total_product">
{if ($order->getTaxCalculationMethod() == $smarty.const.PS_TAX_EXC)}
{displayPrice price=Tools::ps_round($product['product_price'] * $product['customizationQuantityTotal'], 2) currency=$currency->id}
{else}
{displayPrice price=Tools::ps_round($product['product_price_wt'] * $product['customizationQuantityTotal'], 2) currency=$currency->id}
{/if}
</td>
<td align="center" class="cancelCheck">--</td>
<td align="center" class="cancelQuantity">--</td>
<td class="edit_product_fields" colspan="2" style="display:none">&nbsp;</td>
<td class="partial_refund_fields current-edit" style="text-align:left;display:none"></td>
<td class="product_action" style="text-align:right">
<a href="#" class="edit_product_change_link"><img src="../img/admin/edit.gif" alt="{l s='Edit'}" /></a>
<input type="submit" class="button" name="submitProductChange" value="{l s='Update'}" style="display: none;" />
<a href="#" class="cancel_product_change_link" style="display: none;"><img src="../img/admin/disabled.gif" alt="{l s='Cancel'}" /></a>
<a href="#" class="delete_product_line"><img src="../img/admin/delete.gif" alt="{l s='Delete'}" /></a>
</td>
</tr>
{foreach from=$product.customizedDatas key=customizationId item=customization}
<tr>
<td colspan="2">
{foreach from=$customization.datas key=type item=datas}
{if ($type == Product::CUSTOMIZE_FILE)}
<ul style="margin: 4px 0px 4px 0px; padding: 0px; list-style-type: none;">
{foreach from=$datas item=data}
<li style="display: inline; margin: 2px;">
<a href="displayImage.php?img={$data['value']}&name={$order->id}-file{$data@iteration}" target="_blank"><img src="'{$smarty.const._THEME_PROD_PIC_DIR_}{$data['value']}_small" alt="" /></a>
</li>
{/foreach}
</ul>
{elseif ($type == Product::CUSTOMIZE_TEXTFIELD)}
<ul style="margin: 0px 0px 4px 0px; padding: 0px 0px 0px 6px; list-style-type: none;">
{foreach from=$datas item=data}
<li>{if $data['name']}{$data['name']}{else}{l s='Text #'}{$data@iteration}{/if}{l s=':'} {$data['value']}</li>
{/foreach}
</ul>
{/if}
{foreach $product.customizedDatas as $customizationPerAddress}
{foreach $customizationPerAddress as $customizationId => $customization}
<tr class="customized customized-{$product.id_order_detail}">
<input type="hidden" class="edit_product_id_order_detail" value="{$product.id_order_detail}" />
<td colspan="2">
{foreach $customization.datas as $type => $datas}
{if ($type == Product::CUSTOMIZE_FILE)}
<ul style="margin: 4px 0px 4px 0px; padding: 0px; list-style-type: none;">
{foreach from=$datas item=data}
<li style="display: inline; margin: 2px;">
<a href="displayImage.php?img={$data['value']}&name={$order->id}-file{$data@iteration}" target="_blank"><img src="'{$smarty.const._THEME_PROD_PIC_DIR_}{$data['value']}_small" alt="" /></a>
</li>
{/foreach}
</ul>
{elseif ($type == Product::CUSTOMIZE_TEXTFIELD)}
<ul style="margin: 0px 0px 4px 0px; padding: 0px 0px 0px 6px; list-style-type: none;">
{foreach from=$datas item=data}
<li>{if $data['name']}{$data['name']}{else}{l s='Text #'}{$data@iteration}{/if}{l s=':'} {$data['value']}</li>
{/foreach}
</ul>
{/if}
{/foreach}
</td>
<td align="center">-
</td>
<td align="center" class="productQuantity">
<span class="product_quantity_show">{$customization['quantity']}</span>
{if $can_edit}
<span class="product_quantity_edit" style="display:none;">
<input type="text" name="product_quantity[{$customizationId}]" class="edit_product_quantity" value="{$customization['quantity']|htmlentities}" size="2" />
</span>
{/if}
</td>
{if ($order->hasBeenPaid())}<td align="center">{$customization['quantity_refunded']}</td>{/if}
{if ($order->hasBeenDelivered())}<td align="center">{$customization['quantity_returned']}</td>{/if}
<td align="center">
-
</td>
<td align="center" class="total_product">
{if ($order->getTaxCalculationMethod() == $smarty.const.PS_TAX_EXC)}
{displayPrice price=Tools::ps_round($product['product_price'] * $customization['quantity'], 2) currency=$currency->id}
{else}
{displayPrice price=Tools::ps_round($product['product_price_wt'] * $customization['quantity'], 2) currency=$currency->id}
{/if}
</td>
<td class="partial_refund_fields current-edit" style="text-align:left;display:none">
<div style="width:40%;margin-top:5px;float:left">{l s='Quantity:'}</div> <div style="width:60%;margin-top:2px;float:left"><input type="text" size="3" name="partialRefundProductQuantity[{$k}]" value="0" /> 0/{$customization['quantity']-$product['product_quantity_refunded']}</div>
<div style="width:40%;margin-top:5px;float:left">{l s='Amount:'}</div> <div style="width:60%;margin-top:2px;float:left"><input type="text" size="3" name="partialRefundProduct[{$k}]" /> &euro;</div>
</td>
<td class="edit_product_fields" colspan="2" style="display:none"></td>
<td class="product_action" style="text-align:right">
</td>
</tr>
{/foreach}
</td>
<td align="center">-</td>
<td align="center" class="productQuantity">{$customization['quantity']}</td>
{if ($order->hasBeenPaid())}<td align="center">{$customization['quantity_refunded']}</td>{/if}
{if ($order->hasBeenDelivered())}<td align="center">{$customization['quantity_returned']}</td>{/if}
<td align="center">-</td>
<td align="center">
{if ($order->getTaxCalculationMethod() == $smarty.const.PS_TAX_EXC)}
{displayPrice price=Tools::ps_round($product['product_price'] * $customization['quantity'], 2) currency=$currency->id}
{else}
{displayPrice price=Tools::ps_round($product['product_price_wt'] * $customization['quantity'], 2) currency=$currency->id}
{/if}
</td>
<td align="center" class="cancelCheck">
<input type="hidden" name="totalQtyReturn" id="totalQtyReturn" value="{$customization['quantity_returned']}" />
<input type="hidden" name="totalQty" id="totalQty" value="{$customization['quantity']}" />
<input type="hidden" name="productName" id="productName" value="{$product['product_name']}" />
{if ((!$order->hasBeenDelivered() OR Configuration::get('PS_ORDER_RETURN')) && (int)(($customization['quantity_returned']) < (int)($customization['quantity'])))}
<input type="checkbox" name="id_customization[{$customizationId}]" id="id_customization[{$customizationId}]" value="{$product['id_order_detail']}" onchange="setCancelQuantity(this, '{$customizationId}', '{$customization['quantity'] - $customization['quantity_refunded']}')" '.{if (($customization['quantity_returned'] + $customization['quantity_refunded']) >= $customization['quantity'])}disabled="disabled"{/if} />
{else}
--
{/if}
</td>
<td class="cancelQuantity">
{if (($customization['quantity_returned'] + $customization['quantity_refunded']) >= $customization['quantity'])}
<input type="hidden" name="cancelCustomizationQuantity[{$customizationId}]" value="0" />
{elseif (!$order->hasBeenDelivered() || Configuration::get('PS_ORDER_RETURN'))}
<input type="text" id="cancelQuantity_{$customizationId}" name="cancelCustomizationQuantity[{$customizationId}]" size="2" onclick="selectCheckbox(this);" value="" />
{/if}
{if ($order->hasBeenDelivered())}
{$customization['quantity_returned']}/{$customization['quantity']-$customization['quantity_refunded']}
{elseif ($order->hasBeenPaid())}
{$customization['quantity_returned']}/{$customization['quantity']}
{/if}
</td>
</tr>
{/foreach}
{/if}
+3
View File
@@ -549,6 +549,9 @@ class OrderCore extends ObjectModel
// Get the display filename
$row['display_filename'] = ProductDownload::getFilenameFromFilename($row['filename']);
}
$row['id_address_delivery'] = $this->id_address_delivery;
/* Stock product */
$resultArray[(int)$row['id_order_detail']] = $row;
}
+34 -6
View File
@@ -1573,12 +1573,26 @@ class AdminOrdersControllerCore extends AdminController
if (Tools::isSubmit('product_invoice'))
$order_invoice = new OrderInvoice(Tools::getValue('product_invoice'));
// Check fields validity
$this->doEditProductValidation($order_detail, $order, isset($order_invoice) ? $order_invoice : null);
// If multiple product_quantity, the order details concern a product customized
$product_quantity = 0;
if (is_array(Tools::getValue('product_quantity')))
foreach (Tools::getValue('product_quantity') as $id_customization => $qty)
{
// Update quantity of each customization
Db::getInstance()->update('customization', array('quantity' => $qty), 'id_customization = '.(int)$id_customization);
// Calculate the real quantity of the product
$product_quantity += $qty;
}
else
$product_quantity = Tools::getValue('product_quantity');
$product_price_tax_incl = Tools::ps_round(Tools::getValue('product_price_tax_incl'), 2);
$product_price_tax_excl = Tools::ps_round(Tools::getValue('product_price_tax_excl'), 2);
$total_products_tax_incl = $product_price_tax_incl * Tools::getValue('product_quantity');
$total_products_tax_excl = $product_price_tax_excl * Tools::getValue('product_quantity');
$total_products_tax_incl = $product_price_tax_incl * $product_quantity;
$total_products_tax_excl = $product_price_tax_excl * $product_quantity;
// Calculate differences of price (Before / After)
$diff_price_tax_incl = $total_products_tax_incl - $order_detail->total_price_tax_incl;
@@ -1639,7 +1653,7 @@ class AdminOrdersControllerCore extends AdminController
$res &= $order->update();
}
$order_detail->product_quantity = Tools::getValue('product_quantity');
$order_detail->product_quantity = $product_quantity;
// Save order detail
$res &= $order_detail->update();
// Save order invoice
@@ -1677,16 +1691,23 @@ class AdminOrdersControllerCore extends AdminController
'result' => $res,
'error' => Tools::displayError('Error occurred while editing this product line')
)));
if (is_array(Tools::getValue('product_quantity')))
$view = $this->createTemplate('_customized_data.tpl')->fetch();
else
$view = $this->createTemplate('_product_line.tpl')->fetch();
die(Tools::jsonEncode(array(
'result' => $res,
'view' => $this->createTemplate('_product_line.tpl')->fetch(),
'view' => $view,
'can_edit' => $this->tabAccess['add'],
'invoices_collection' => $invoice_collection,
'order' => $order,
'invoices' => $invoice_array,
'documents_html' => $this->createTemplate('_documents.tpl')->fetch(),
'shipping_html' => $this->createTemplate('_shipping.tpl')->fetch()
'shipping_html' => $this->createTemplate('_shipping.tpl')->fetch(),
'customized_product' => is_array(Tools::getValue('product_quantity'))
)));
}
@@ -1806,11 +1827,18 @@ class AdminOrdersControllerCore extends AdminController
'error' => Tools::displayError('Invalid price')
)));
if (!Validate::isUnsignedInt(Tools::getValue('product_quantity')))
if (!is_array(Tools::getValue('product_quantity')) && !Validate::isUnsignedInt(Tools::getValue('product_quantity')))
die(Tools::jsonEncode(array(
'result' => false,
'error' => Tools::displayError('Invalid quantity')
)));
elseif (is_array(Tools::getValue('product_quantity')))
foreach (Tools::getValue('product_quantity') as $qty)
if (!Validate::isUnsignedInt($qty))
die(Tools::jsonEncode(array(
'result' => false,
'error' => Tools::displayError('Invalid quantity')
)));
}
protected function doDeleteProductLinveValidation(OrderDetail $order_detail, Order $order)
+78 -30
View File
@@ -145,6 +145,14 @@ function addProductRefreshTotal()
function editProductRefreshTotal(element)
{
element = element.parent().parent().parent();
var element_list = [];
// Customized product
if(element.hasClass('customized'))
{
var element_list = $('.customized-' + element.find('.edit_product_id_order_detail').val());
element = $(element_list[0]);
}
var quantity = parseInt(element.find('td .edit_product_quantity').val());
if (quantity < 1 || isNaN(quantity))
@@ -156,9 +164,33 @@ function editProductRefreshTotal(element)
if (price < 0 || isNaN(price))
price = 0;
// Customized product
if (element_list.length)
{
console.log(element_list);
var qty = 0;
$.each(element_list, function(i, elm) {
if($(elm).find('.edit_product_quantity').length)
{
qty += parseInt($(elm).find('.edit_product_quantity').val());
subtotal = makeTotalProductCaculation($(elm).find('.edit_product_quantity').val(), price);
$(elm).find('.total_product').html(formatCurrency(subtotal, currency_format, currency_sign, currency_blank));
console.log('res');
console.log($(elm).find('.total_product'));
}
});
var total = makeTotalProductCaculation(qty, price);
element.find('td.total_product').html(formatCurrency(total, currency_format, currency_sign, currency_blank));
element.find('td.productQuantity').html(qty);
}
else
{
var total = makeTotalProductCaculation(quantity, price);
element.find('td.total_product').html(formatCurrency(total, currency_format, currency_sign, currency_blank));
}
var total = makeTotalProductCaculation(quantity, price);
element.find('td.total_product').html(formatCurrency(total, currency_format, currency_sign, currency_blank));
}
function makeTotalProductCaculation(quantity, price)
@@ -187,10 +219,15 @@ function refreshProductLineView(element, view)
{
var new_product_line = $(view);
new_product_line.find('td').hide();
var element_list = [];
if (element.parent().parent().find('.edit_product_id_order_detail').length)
var element_list = $('.customized-' + element.parent().parent().find('.edit_product_id_order_detail').val());
var current_product_line = element.parent().parent();
current_product_line.before(new_product_line);
current_product_line.remove();
element_list.remove();
new_product_line.find('td').each(function() {
if (!$(this).is('.product_invoice'))
@@ -509,32 +546,39 @@ function init()
$('.edit_product_fields').show();
$('.cancel_product_change_link:visible').trigger('click');
closeAddProduct();
query = 'ajax=1&token='+token+'&action=loadProductInformation&id_order_detail='+
$(this).parent().parent().find('input.edit_product_id_order_detail').val()+'&id_address='+id_address+'&id_order='+id_order;
var element = $(this);
$.ajax({
type: 'POST',
url: admin_order_tab_link,
cache: false,
dataType: 'json',
data : query,
data : {
ajax: 1,
token: token,
action: 'loadProductInformation',
id_order_detail: $(this).parent().parent().find('input.edit_product_id_order_detail').val(),
id_address: id_address,
id_order: id_order
},
success : function(data)
{
if (data.result)
{
current_product = data;
element.parent().parent().css('background-color', '#E8EDC2');
var element_list = $('.customized-' + element.parent().parent().find('.edit_product_id_order_detail').val());
element.parent().parent().find('td .product_price_show').hide();
element.parent().parent().find('td .product_quantity_show').hide();
element.parent().parent().find('td .product_price_edit').parent().attr('align', 'left');
element.parent().parent().find('td .product_price_edit').show();
element.parent().parent().find('td .product_quantity_edit').show();
element_list.css('background-color', '#E8EDC2');
element.parent().parent().find('td.cancelCheck').hide();
element.parent().parent().find('td.cancelQuantity').hide();
element.parent().parent().find('td.product_invoice').show();
element_list.find('td .product_price_show').hide();
element_list.find('td .product_quantity_show').hide();
element_list.find('td .product_price_edit').parent().attr('align', 'left');
element_list.find('td .product_price_edit').show();
element_list.find('td .product_quantity_edit').show();
element_list.find('td.cancelCheck').hide();
element_list.find('td.cancelQuantity').hide();
element_list.find('td.product_invoice').show();
element.parent().children('.delete_product_line').hide();
element.parent().children('.edit_product_change_link').hide();
@@ -554,23 +598,25 @@ function init()
$('.cancel_product_change_link').click(function() {
current_product = null;
$('.edit_product_fields').show();
$(this).parent().parent().css('background-color', '#FFF');
$('.edit_product_fields').hide();
var element_list = $('.customized-' + $(this).parent().parent().find('.edit_product_id_order_detail').val());
$(this).parent().parent().find('td .product_price_show').show();
$(this).parent().parent().find('td .product_quantity_show').show();
$(this).parent().parent().find('td .product_price_edit').parent().attr('align', 'center');
$(this).parent().parent().find('td .product_price_edit').hide();
$(this).parent().parent().find('td .product_quantity_edit').hide();
element_list.css('background-color', '#FFF');
$(this).parent().parent().find('td.product_invoice').hide();
$(this).parent().parent().find('td.cancelCheck').show();
$(this).parent().parent().find('td.cancelQuantity').show();
element_list.find('td .product_price_show').show();
element_list.find('td .product_quantity_show').show();
element_list.find('td .product_price_edit').parent().attr('align', 'center');
element_list.find('td .product_price_edit').hide();
element_list.find('td .product_quantity_edit').hide();
$(this).parent().children('.delete_product_line').show();
$(this).parent().children('.edit_product_change_link').show();
$(this).parent().children('input[name=submitProductChange]').hide();
$(this).parent().children('.cancel_product_change_link').hide();
element_list.find('td.product_invoice').hide();
element_list.find('td.cancelCheck').show();
element_list.find('td.cancelQuantity').show();
element_list.find('.delete_product_line').show();
element_list.find('.edit_product_change_link').show();
element_list.find('input[name=submitProductChange]').hide();
element_list.find('.cancel_product_change_link').hide();
$('.standard_refund_fields').hide();
return false;
});
@@ -591,9 +637,11 @@ function init()
if (confirm(txt_confirm))
{
var element = $(this);
var element_list = $('.customized-' + $(this).parent().parent().find('.edit_product_id_order_detail').val());
query = 'ajax=1&token='+token+'&action=editProductOnOrder&id_order='+id_order+'&'+
element.parent().parent().find('input:visible, select:visible, input.edit_product_id_order_detail').serialize();
element_list.parent().parent().find('input:visible, select:visible, input.edit_product_id_order_detail').serialize();
$.ajax({
type: 'POST',
+27 -25
View File
@@ -211,32 +211,34 @@
</label>
</td>
</tr>
{foreach from=$product.customizedDatas item='customization' key='customizationId'}
<tr class="alternate_item">
{if $return_allowed}<td class="order_cb"><input type="checkbox" id="cb_{$product.id_order_detail|intval}" name="customization_ids[{$product.id_order_detail|intval}][]" value="{$customizationId|intval}" /></td>{/if}
<td colspan="2">
{foreach from=$customization.datas key='type' item='datas'}
{if $type == $CUSTOMIZE_FILE}
<ul class="customizationUploaded">
{foreach from=$datas item='data'}
<li><img src="{$pic_dir}{$data.value}_small" alt="" class="customizationUploaded" /></li>
{/foreach}
</ul>
{elseif $type == $CUSTOMIZE_TEXTFIELD}
<ul class="typedText">{counter start=0 print=false}
{foreach from=$datas item='data'}
{assign var='customizationFieldName' value="Text #"|cat:$data.id_customization_field}
<li>{$data.name|default:$customizationFieldName}{l s=':'} {$data.value}</li>
{/foreach}
</ul>
{/if}
{foreach $product.customizedDatas as $customizationPerAddress}
{foreach $customizationPerAddress as $customizationId => $customization}
<tr class="alternate_item">
{if $return_allowed}<td class="order_cb"><input type="checkbox" id="cb_{$product.id_order_detail|intval}" name="customization_ids[{$product.id_order_detail|intval}][]" value="{$customizationId|intval}" /></td>{/if}
<td colspan="2">
{foreach from=$customization.datas key='type' item='datas'}
{if $type == $CUSTOMIZE_FILE}
<ul class="customizationUploaded">
{foreach from=$datas item='data'}
<li><img src="{$pic_dir}{$data.value}_small" alt="" class="customizationUploaded" /></li>
{/foreach}
</ul>
{elseif $type == $CUSTOMIZE_TEXTFIELD}
<ul class="typedText">{counter start=0 print=false}
{foreach from=$datas item='data'}
{assign var='customizationFieldName' value="Text #"|cat:$data.id_customization_field}
<li>{$data.name|default:$customizationFieldName}{l s=':'} {$data.value}</li>
{/foreach}
</ul>
{/if}
{/foreach}
</td>
<td>
<input class="order_qte_input" name="customization_qty_input[{$customizationId|intval}]" type="text" size="2" value="{$customization.quantity|intval}" /><label for="cb_{$product.id_order_detail|intval}"><span class="order_qte_span editable">{$customization.quantity|intval}</span></label>
</td>
<td colspan="2"></td>
</tr>
{/foreach}
</td>
<td>
<input class="order_qte_input" name="customization_qty_input[{$customizationId|intval}]" type="text" size="2" value="{$customization.quantity|intval}" /><label for="cb_{$product.id_order_detail|intval}"><span class="order_qte_span editable">{$customization.quantity|intval}</span></label>
</td>
<td colspan="2"></td>
</tr>
{/foreach}
{/if}
<!-- Classic products -->