mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2026-01-06 00:53:00 +01:00
Merge remote-tracking branch 'upstream/develop' into membertooltip
This commit is contained in:
@@ -4,7 +4,7 @@ LOG INALTERABLE
|
||||
## Fonctionnalité
|
||||
|
||||
Ce module trace, en temps réel, certains évènements métiers dans une log inaltérable (que vous ne pouvez pas modifier une fois enregistrés) de type blockchain.
|
||||
Ce module est requis pour la compatibilité avec les exigences légales de certains pays (comme la France avec la loi Fincance 2016 - Norme NF535).
|
||||
Ce module est requis pour la compatibilité avec les exigences légales de certains pays (comme la France avec la loi Finance 2016 - Norme NF525).
|
||||
|
||||
|
||||
**Les évènements tracés de manière inaltérables sont:**
|
||||
|
||||
@@ -4,7 +4,7 @@ BLOCKED LOG
|
||||
## Feature
|
||||
|
||||
This module tracks, in real time, some events into a non reversible log (that you can't modify once recorded) into a block chain.
|
||||
This module provides compatibility with requirements of laws of some countries (like France with the law Fincance 2016 - Norme NF535).
|
||||
This module provides compatibility with requirements of laws of some countries (like France with the law Finance 2016 - Norme NF525).
|
||||
|
||||
|
||||
**The tracked events are:**
|
||||
|
||||
@@ -80,8 +80,6 @@ if (isModEnabled('margin')) {
|
||||
}
|
||||
|
||||
// General $Variables
|
||||
$projectid = (GETPOST('projectid', 'int') ? GETPOST('projectid', 'int') : 0);
|
||||
|
||||
$id = (GETPOST('id', 'int') ? GETPOST('id', 'int') : GETPOST('facid', 'int')); // For backward compatibility
|
||||
$ref = GETPOST('ref', 'alpha');
|
||||
$socid = GETPOST('socid', 'int');
|
||||
@@ -100,6 +98,7 @@ $fac_rec = GETPOST('fac_rec', 'int');
|
||||
$facid = GETPOST('facid', 'int');
|
||||
$ref_client = GETPOST('ref_client', 'int');
|
||||
$rank = (GETPOST('rank', 'int') > 0) ? GETPOST('rank', 'int') : -1;
|
||||
$projectid = (GETPOST('projectid', 'int') ? GETPOST('projectid', 'int') : 0);
|
||||
|
||||
// PDF
|
||||
$hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
|
||||
@@ -3149,7 +3148,7 @@ if ($action == 'create') {
|
||||
|
||||
print '<form name="add" action="'.$_SERVER["PHP_SELF"].'" method="POST" id="formtocreate" name="formtocreate">';
|
||||
print '<input type="hidden" name="token" value="'.newToken().'">';
|
||||
print '<input type="hidden" name="action" value="add">';
|
||||
print '<input type="hidden" name="action" id="formtocreateaction" value="add">';
|
||||
if ($soc->id > 0) {
|
||||
print '<input type="hidden" name="socid" value="'.$soc->id.'">'."\n";
|
||||
}
|
||||
@@ -3215,11 +3214,10 @@ if ($action == 'create') {
|
||||
$(\'input[name="force_fk_account"]\').val(\'1\');
|
||||
$("#formtocreate").submit(); */
|
||||
|
||||
// For company change, we must reuse data of comany, not input already done, so we call a GET with action=create, not a POST submit.
|
||||
console.log("We have changed the company - Reload page");
|
||||
var socid = $(this).val();
|
||||
var fac_rec = $(\'#fac_rec\').val();
|
||||
window.location.href = "'.$_SERVER["PHP_SELF"].'?action=create&socid="+socid+"&fac_rec="+fac_rec;
|
||||
// For company change, we must submit page with action=create instead of action=add
|
||||
console.log("We have changed the company - Resubmit page");
|
||||
jQuery("#formtocreateaction").val("create");
|
||||
jQuery("#formtocreate").submit();
|
||||
});
|
||||
});
|
||||
</script>';
|
||||
|
||||
@@ -1793,11 +1793,11 @@ if ($resql) {
|
||||
|
||||
$with_margin_info = false;
|
||||
if (isModEnabled('margin') && (
|
||||
!empty($arrayfields['total_pa']['checked'])
|
||||
|| !empty($arrayfields['total_margin']['checked'])
|
||||
|| !empty($arrayfields['total_margin_rate']['checked'])
|
||||
|| !empty($arrayfields['total_mark_rate']['checked'])
|
||||
)
|
||||
!empty($arrayfields['total_pa']['checked'])
|
||||
|| !empty($arrayfields['total_margin']['checked'])
|
||||
|| !empty($arrayfields['total_margin_rate']['checked'])
|
||||
|| !empty($arrayfields['total_mark_rate']['checked'])
|
||||
)
|
||||
) {
|
||||
$with_margin_info = true;
|
||||
}
|
||||
|
||||
@@ -903,9 +903,8 @@ if ($ok && GETPOST('clean_product_stock_batch', 'alpha')) {
|
||||
$sql = "SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."product as p, ".MAIN_DB_PREFIX."product_stock as ps LEFT JOIN ".MAIN_DB_PREFIX."product_batch as pb ON ps.rowid = pb.fk_product_stock";
|
||||
$sql .= " WHERE p.rowid = ps.fk_product";
|
||||
$sql .= " AND p.tobatch > 0";
|
||||
$sql .= " GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel";
|
||||
$sql .= " HAVING reel != SUM(pb.qty) or SUM(pb.qty) IS NULL";
|
||||
$sql .= " HAVING (SUM(pb.qty) IS NOT NULL AND reel != SUM(pb.qty)) OR (SUM(pb.qty) IS NULL AND p.tobatch > 0)";
|
||||
print $sql;
|
||||
$resql = $db->query($sql);
|
||||
if ($resql) {
|
||||
@@ -915,53 +914,73 @@ if ($ok && GETPOST('clean_product_stock_batch', 'alpha')) {
|
||||
$i = 0;
|
||||
while ($i < $num) {
|
||||
$obj = $db->fetch_object($resql);
|
||||
print '<tr><td>Product '.$obj->rowid.'-'.$obj->ref.' in warehouse '.$obj->fk_entrepot.' (product_stock id '.$obj->psrowid.'): '.$obj->reel.' (Stock product_stock.reel) != '.($obj->reelbatch ? $obj->reelbatch : '0').' (Stock batch sum product_batch)';
|
||||
print '<tr><td>Product '.$obj->rowid.'-'.$obj->ref.' in warehouse id='.$obj->fk_entrepot.' (product_stock.id='.$obj->psrowid.'): '.$obj->reel.' (Stock product_stock.reel) != '.($obj->reelbatch ? $obj->reelbatch : '0').' (Stock batch sum product_batch)';
|
||||
|
||||
// Fix
|
||||
// Fix is required
|
||||
if ($obj->reel != $obj->reelbatch) {
|
||||
if ($methodtofix == 'updatebatch') {
|
||||
// Method 1
|
||||
print ' -> Insert qty '.($obj->reel - $obj->reelbatch).' with lot 000000 linked to fk_product_stock='.$obj->psrowid;
|
||||
if (empty($obj->tobatch)) {
|
||||
// If product is not a product that support batches, we can clean stock by deleting the product batch lines
|
||||
print ' -> Delete qty '.$obj->reelbatch.' for any lot linked to fk_product_stock='.$obj->psrowid;
|
||||
$sql2 = "DELETE FROM ".MAIN_DB_PREFIX."product_batch";
|
||||
$sql2 .= " WHERE fk_product_stock = ".((int) $obj->psrowid);
|
||||
print '<br>'.$sql2;
|
||||
|
||||
if (GETPOST('clean_product_stock_batch') == 'confirmed') {
|
||||
$sql2 = "INSERT INTO ".MAIN_DB_PREFIX."product_batch(fk_product_stock, batch, qty)";
|
||||
$sql2 .= "VALUES(".$obj->psrowid.", '000000', ".($obj->reel - $obj->reelbatch).")";
|
||||
$resql2 = $db->query($sql2);
|
||||
if (!$resql2) {
|
||||
// TODO If it fails, we must make update
|
||||
//$sql2 ="UPDATE ".MAIN_DB_PREFIX."product_batch";
|
||||
//$sql2.=" SET ".$obj->psrowid.", '000000', ".($obj->reel - $obj->reelbatch).")";
|
||||
//$sql2.=" WHERE fk_product_stock = ".((int) $obj->psrowid)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($methodtofix == 'updatestock') {
|
||||
// Method 2
|
||||
print ' -> Update qty of product_stock with qty = '.($obj->reelbatch ? ((float) $obj->reelbatch) : '0').' for ps.rowid = '.((int) $obj->psrowid);
|
||||
if (GETPOST('clean_product_stock_batch') == 'confirmed') {
|
||||
$error = 0;
|
||||
|
||||
$db->begin();
|
||||
|
||||
$sql2 = "UPDATE ".MAIN_DB_PREFIX."product_stock";
|
||||
$sql2 .= " SET reel = ".($obj->reelbatch ? ((float) $obj->reelbatch) : '0')." WHERE rowid = ".((int) $obj->psrowid);
|
||||
$resql2 = $db->query($sql2);
|
||||
if ($resql2) {
|
||||
// We update product_stock, so we must fill p.stock into product too.
|
||||
$sql3 = 'UPDATE '.MAIN_DB_PREFIX.'product p SET p.stock= (SELECT SUM(ps.reel) FROM '.MAIN_DB_PREFIX.'product_stock ps WHERE ps.fk_product = p.rowid)';
|
||||
$resql3 = $db->query($sql3);
|
||||
if (!$resql3) {
|
||||
$error++;
|
||||
dol_print_error($db);
|
||||
}
|
||||
} else {
|
||||
$error++;
|
||||
dol_print_error($db);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($methodtofix == 'updatebatch') {
|
||||
// Method 1
|
||||
print ' -> Insert qty '.($obj->reel - $obj->reelbatch).' with lot 000000 linked to fk_product_stock='.$obj->psrowid;
|
||||
$sql2 = "INSERT INTO ".MAIN_DB_PREFIX."product_batch(fk_product_stock, batch, qty)";
|
||||
$sql2 .= "VALUES(".((int) $obj->psrowid).", '000000', ".((float) ($obj->reel - $obj->reelbatch)).")";
|
||||
print '<br>'.$sql2;
|
||||
|
||||
if (!$error) {
|
||||
$db->commit();
|
||||
} else {
|
||||
$db->rollback();
|
||||
if (GETPOST('clean_product_stock_batch') == 'confirmed') {
|
||||
$resql2 = $db->query($sql2);
|
||||
if (!$resql2) {
|
||||
// TODO If it fails, we must make update
|
||||
//$sql2 ="UPDATE ".MAIN_DB_PREFIX."product_batch";
|
||||
//$sql2.=" SET ".$obj->psrowid.", '000000', ".($obj->reel - $obj->reelbatch).")";
|
||||
//$sql2.=" WHERE fk_product_stock = ".((int) $obj->psrowid)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($methodtofix == 'updatestock') {
|
||||
// Method 2
|
||||
print ' -> Update qty of product_stock with qty = '.($obj->reelbatch ? ((float) $obj->reelbatch) : '0').' for ps.rowid = '.((int) $obj->psrowid);
|
||||
$sql2 = "UPDATE ".MAIN_DB_PREFIX."product_stock";
|
||||
$sql2 .= " SET reel = ".($obj->reelbatch ? ((float) $obj->reelbatch) : '0')." WHERE rowid = ".((int) $obj->psrowid);
|
||||
print '<br>'.$sql2;
|
||||
|
||||
if (GETPOST('clean_product_stock_batch') == 'confirmed') {
|
||||
$error = 0;
|
||||
|
||||
$db->begin();
|
||||
|
||||
$resql2 = $db->query($sql2);
|
||||
if ($resql2) {
|
||||
// We update product_stock, so we must fill p.stock into product too.
|
||||
$sql3 = 'UPDATE '.MAIN_DB_PREFIX.'product p SET p.stock= (SELECT SUM(ps.reel) FROM '.MAIN_DB_PREFIX.'product_stock ps WHERE ps.fk_product = p.rowid)';
|
||||
$resql3 = $db->query($sql3);
|
||||
if (!$resql3) {
|
||||
$error++;
|
||||
dol_print_error($db);
|
||||
}
|
||||
} else {
|
||||
$error++;
|
||||
dol_print_error($db);
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
$db->commit();
|
||||
} else {
|
||||
$db->rollback();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ ErrorExistingPermission = Permission <b>%s</b> for object <b>%s</b> already exis
|
||||
ErrorFieldExist=The value for <b>%s</b> already exist
|
||||
ErrorEqualModule=Module invalid in <b>%s</b>
|
||||
ErrorFieldValue=Value for <b>%s</b> is incorrect
|
||||
ErrorCoherenceMenu=<b>%s</b> is required when <b>%</b> equal LEFT
|
||||
ErrorCoherenceMenu=<b>%s</b> is required when <b>%s</b> is 'left'
|
||||
|
||||
# Warnings
|
||||
WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup.
|
||||
|
||||
@@ -50,7 +50,7 @@ UseDateWithoutHourOnFichinter=Hides hours and minutes off the date field for int
|
||||
InterventionStatistics=Statistics of interventions
|
||||
NbOfinterventions=No. of intervention cards
|
||||
NumberOfInterventionsByMonth=No. of intervention cards by month (date of validation)
|
||||
AmountOfInteventionNotIncludedByDefault=Amount of intervention is not included by default into profit (in most cases, timesheets are used to count time spent). Add option PROJECT_INCLUDE_INTERVENTION_AMOUNT_IN_PROFIT to 1 into home-setup-other to include them.
|
||||
AmountOfInteventionNotIncludedByDefault=Amount of intervention is not included by default into profit (in most cases, timesheets are used to count time spent). You can use PROJECT_ELEMENTS_FOR_ADD_MARGIN and PROJECT_ELEMENTS_FOR_MINUS_MARGIN option into home-setup-other to complete list of element included into profit.
|
||||
InterId=Intervention id
|
||||
InterRef=Intervention ref.
|
||||
InterDateCreation=Date creation intervention
|
||||
|
||||
@@ -1277,7 +1277,7 @@ if (!empty($arrayfields['p.stock']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['p.stock']['label'], $_SERVER["PHP_SELF"], "p.stock", "", $param, '', $sortfield, $sortorder, 'right ');
|
||||
}
|
||||
if (!empty($arrayfields['stock_virtual']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['stock_virtual']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
|
||||
print_liste_field_titre($arrayfields['stock_virtual']['label'], $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ', 'VirtualStockDesc');
|
||||
}
|
||||
if (!empty($arrayfields['p.tobatch']['checked'])) {
|
||||
print_liste_field_titre($arrayfields['p.tobatch']['label'], $_SERVER["PHP_SELF"], "p.tobatch", "", $param, '', $sortfield, $sortorder, 'center ');
|
||||
@@ -1854,7 +1854,7 @@ while ($i < $imaxinloop) {
|
||||
}
|
||||
if ($usercancreadprice) {
|
||||
if ($product_static->stock_reel < 0) { print '<span class="warning">'; }
|
||||
print price(price2num($product_static->stock_reel, 'MS'));
|
||||
print price(price2num($product_static->stock_reel, 'MS'), 0, $langs, 1, 0);
|
||||
if ($product_static->stock_reel < 0) { print '</span>'; }
|
||||
}
|
||||
}
|
||||
@@ -1872,7 +1872,7 @@ while ($i < $imaxinloop) {
|
||||
}
|
||||
if ($usercancreadprice) {
|
||||
if ($product_static->stock_theorique < 0) { print '<span class="warning">'; }
|
||||
print price(price2num($product_static->stock_theorique, 'MS'));
|
||||
print price(price2num($product_static->stock_theorique, 'MS'), 0, $langs, 1, 0);
|
||||
if ($product_static->stock_theorique < 0) { print '</span>'; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,7 +493,7 @@ if ($resql) {
|
||||
print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' ';
|
||||
}
|
||||
if ($objp->stock_physique < 0) { print '<span class="warning">'; }
|
||||
print price2num($objp->stock_physique, 'MS');
|
||||
print price(price2num($objp->stock_physique, 'MS'), 0, $langs, 1, 0);
|
||||
if ($objp->stock_physique < 0) { print '</span>'; }
|
||||
print '</td>';
|
||||
|
||||
@@ -502,7 +502,7 @@ if ($resql) {
|
||||
if ($nb_warehouse > 1) {
|
||||
foreach ($warehouses_list as &$wh) {
|
||||
print '<td class="right">';
|
||||
print empty($product->stock_warehouse[$wh['id']]->real) ? '0' : $product->stock_warehouse[$wh['id']]->real;
|
||||
print price(empty($product->stock_warehouse[$wh['id']]->real) ? 0 : $product->stock_warehouse[$wh['id']]->real, 0, $langs, 1, 0);
|
||||
print '</td>';
|
||||
}
|
||||
}
|
||||
@@ -511,11 +511,11 @@ if ($resql) {
|
||||
// Virtual stock
|
||||
if ($virtualdiffersfromphysical) {
|
||||
print '<td class="right">';
|
||||
if ($objp->seuil_stock_alerte != '' && ($product->stock_theorique < $objp->seuil_stock_alerte)) {
|
||||
if ($objp->seuil_stock_alerte != '' && ($product->stock_theorique < (float) $objp->seuil_stock_alerte)) {
|
||||
print img_warning($langs->trans("StockLowerThanLimit", $objp->seuil_stock_alerte)).' ';
|
||||
}
|
||||
if ($objp->stock_physique < 0) { print '<span class="warning">'; }
|
||||
print price2num($product->stock_theorique, 'MS');
|
||||
print price2num($product->stock_theorique, 'MS', 0, $langs, 1, 0);
|
||||
if ($objp->stock_physique < 0) { print '</span>'; }
|
||||
print '</td>';
|
||||
}
|
||||
|
||||
@@ -475,7 +475,7 @@ $listofreferent = array(
|
||||
'table'=>'fichinter',
|
||||
'datefieldname'=>'date_valid',
|
||||
'disableamount'=>0,
|
||||
'margin'=>'minus',
|
||||
'margin'=>'',
|
||||
'urlnew'=>DOL_URL_ROOT.'/fichinter/card.php?action=create&origin=project&originid='.$id.'&socid='.$socid.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
|
||||
'lang'=>'interventions',
|
||||
'buttonnew'=>'AddIntervention',
|
||||
@@ -585,9 +585,9 @@ $listofreferent = array(
|
||||
'name'=>"MouvementStockAssociated",
|
||||
'title'=>"ListMouvementStockProject",
|
||||
'class'=>'MouvementStock',
|
||||
'margin'=>'minus',
|
||||
'table'=>'stock_mouvement',
|
||||
'datefieldname'=>'datem',
|
||||
'margin'=>'minus',
|
||||
'disableamount'=>0,
|
||||
'test'=>!empty($conf->stock->enabled) && $user->hasRight('stock', 'mouvement', 'lire') && !empty($conf->global->STOCK_MOVEMENT_INTO_PROJECT_OVERVIEW)),
|
||||
'salaries'=>array(
|
||||
@@ -752,6 +752,7 @@ $total_revenue_ht = 0;
|
||||
$balance_ht = 0;
|
||||
$balance_ttc = 0;
|
||||
|
||||
// Loop on each element type (proposal, sale order, invoices, ...)
|
||||
foreach ($listofreferent as $key => $value) {
|
||||
$parameters = array(
|
||||
'total_revenue_ht' =>& $total_revenue_ht,
|
||||
@@ -787,6 +788,7 @@ foreach ($listofreferent as $key => $value) {
|
||||
$total_ht = 0;
|
||||
$total_ttc = 0;
|
||||
|
||||
// Loop on each object for the current element type
|
||||
$num = count($elementarray);
|
||||
for ($i = 0; $i < $num; $i++) {
|
||||
$tmp = explode('_', $elementarray[$i]);
|
||||
@@ -871,7 +873,7 @@ foreach ($listofreferent as $key => $value) {
|
||||
$defaultvat = get_default_tva($mysoc, $mysoc);
|
||||
$total_ttc_by_line = price2num($total_ht_by_line * (1 + ($defaultvat / 100)), 'MT');
|
||||
} elseif ($key == 'loan') {
|
||||
$total_ttc_by_line = $total_ht_by_line; // For loan there is actually no taxe managed in Dolibarr
|
||||
$total_ttc_by_line = $total_ht_by_line; // For loan there is actually no taxe managed in Dolibarr
|
||||
} else {
|
||||
$total_ttc_by_line = $element->total_ttc;
|
||||
}
|
||||
@@ -892,19 +894,14 @@ foreach ($listofreferent as $key => $value) {
|
||||
}
|
||||
|
||||
// Each element with at least one line is output
|
||||
$qualifiedforfinalprofit = true;
|
||||
if ($key == 'intervention' && empty($conf->global->PROJECT_INCLUDE_INTERVENTION_AMOUNT_IN_PROFIT)) {
|
||||
$qualifiedforfinalprofit = false;
|
||||
}
|
||||
//var_dump($key.' '.$qualifiedforfinalprofit);
|
||||
|
||||
// Calculate margin
|
||||
if ($qualifiedforfinalprofit) {
|
||||
if ($margin == 'add') {
|
||||
if ($margin) {
|
||||
if ($margin === 'add') {
|
||||
$total_revenue_ht += $total_ht;
|
||||
}
|
||||
|
||||
if ($margin != "add") { // Revert sign
|
||||
if ($margin === "minus") { // Revert sign
|
||||
$total_ht = -$total_ht;
|
||||
$total_ttc = -$total_ttc;
|
||||
}
|
||||
@@ -920,24 +917,24 @@ foreach ($listofreferent as $key => $value) {
|
||||
print '<td class="right">'.$i.'</td>';
|
||||
// Amount HT
|
||||
print '<td class="right">';
|
||||
if ($key == 'intervention' && !$qualifiedforfinalprofit) {
|
||||
if ($key == 'intervention' && !$margin) {
|
||||
print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NA"), $langs->trans("AmountOfInteventionNotIncludedByDefault")).'</span>';
|
||||
} else {
|
||||
print price($total_ht);
|
||||
if ($key == 'propal') {
|
||||
print '<span class="opacitymedium">'.$form->textwithpicto('', $langs->trans("SignedOnly")).'</span>';
|
||||
}
|
||||
print price($total_ht);
|
||||
}
|
||||
print '</td>';
|
||||
// Amount TTC
|
||||
print '<td class="right">';
|
||||
if ($key == 'intervention' && !$qualifiedforfinalprofit) {
|
||||
if ($key == 'intervention' && !$margin) {
|
||||
print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NA"), $langs->trans("AmountOfInteventionNotIncludedByDefault")).'</span>';
|
||||
} else {
|
||||
print price($total_ttc);
|
||||
if ($key == 'propal') {
|
||||
print '<span class="opacitymedium">'.$form->textwithpicto('', $langs->trans("SignedOnly")).'</span>';
|
||||
}
|
||||
print price($total_ttc);
|
||||
}
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
Reference in New Issue
Block a user