Merge remote-tracking branch 'upstream/develop' into membertooltip

This commit is contained in:
Frédéric FRANCE
2023-02-15 21:10:35 +01:00
10 changed files with 93 additions and 79 deletions

View File

@@ -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:**

View File

@@ -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:**

View File

@@ -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>';

View File

@@ -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;
}

View File

@@ -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();
}
}
}
}

View File

@@ -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.

View File

@@ -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

View File

@@ -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>'; }
}
}

View File

@@ -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>';
}

View File

@@ -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>';