Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop

This commit is contained in:
Laurent Destailleur
2025-12-05 02:13:27 +01:00
3 changed files with 71 additions and 27 deletions

View File

@@ -1070,4 +1070,38 @@ class FactureLigne extends CommonInvoiceLine
return $cumulated_percent; return $cumulated_percent;
} }
} }
/**
* Determines if we are using situation invoices.
* If so, determines if we are using the new mode (2) or legacy mode (1).
*
* Legacy mode means invoice line fields store the state of the cycle at the current
* situation (a cumulative value) rather than the delta between the previous situation
* and the current one. In that case, we need a ratio to convert those values.
*
* New mode = the values on the line already represent the delta between the previous
* state and the current state, so we don't need a conversion (we return 1).
*
* @return float
*/
public function getSituationRatio()
{
if (getDolGlobalInt('INVOICE_USE_SITUATION') === 1) {
// in legacy mode, the situation invoice line stores the (cumulative) state of the
// cycle at the current situation. To get the delta, we need to subtract the
// state at the previous situation (if applicable).
$prevProgress = $this->get_prev_progress($this->fk_facture);
if ($this->situation_percent == 0) {
// should not happen
return 0;
}
return ($this->situation_percent - $prevProgress) / $this->situation_percent;
}
// new mode (INVOICE_USE_SITUATION == 2):
// no ratio needed (data stored on line is already a delta)
// or not a situation invoice: no ratio needed either
return 1;
}
} }

View File

@@ -203,12 +203,22 @@ if ($result) {
$line->fetch($obj->id); // id of line $line->fetch($obj->id); // id of line
$prev_progress = 0; $prev_progress = 0;
if ($obj->situation_cycle_ref > 0) { // It is a situation invoice if ($obj->situation_cycle_ref > 0) { // It is a situation invoice
$prev_progress = $line->get_prev_progress($obj->rowid); // id on invoice
if (getDolGlobalInt('INVOICE_USE_SITUATION') === 1) {
// backward compat: old behavior => line's situation_percent was cumulative
// (it reflected the line's progress state, not the line progress delta)
$progressDelta = $obj->situation_percent - $prev_progress;
$progressState = $obj->situation_percent;
} else {
$progressDelta = $obj->situation_percent;
$progressState = $prev_progress + $progressDelta;
}
// Avoid divide by 0 // Avoid divide by 0
if ($obj->situation_percent == 0) { if ($progressState == 0) {
$situation_ratio = 0; $situation_ratio = 0;
} else { } else {
$prev_progress = $line->get_prev_progress($obj->rowid); // id on invoice $situation_ratio = $progressDelta / $progressState;
$situation_ratio = ($obj->situation_percent - $prev_progress) / $obj->situation_percent;
} }
} else { } else {
$situation_ratio = 1; $situation_ratio = 1;

View File

@@ -2456,15 +2456,31 @@ function pdf_getlineprogress($object, $i, $outputlangs, $hidedetails = 0, $hookm
return ''; return '';
} }
if (empty($hidedetails) || $hidedetails > 1) { if (empty($hidedetails) || $hidedetails > 1) {
if (getDolGlobalString('SITUATION_DISPLAY_DIFF_ON_PDF')) { // 2 = situation_percent is non-cumulative (delta of current situation)
// 1 = (old mode): situation_percent is cumulative (state at situation)
$isCumulative = getDolGlobalInt('INVOICE_USE_SITUATION') === 1;
$showDelta = (bool) getDolGlobalInt('SITUATION_DISPLAY_DIFF_ON_PDF');
if ($isCumulative xor $showDelta) {
// Either:
// - old mode and we want to show a total or
// - new mode and we want to show a delta
$result = $object->lines[$i]->situation_percent;
} else {
// Either:
// - old mode but we want to show a delta or
// - new mode but we want to show a total
$prev_progress = 0; $prev_progress = 0;
if (method_exists($object->lines[$i], 'get_prev_progress')) { if (method_exists($object->lines[$i], 'get_prev_progress')) {
$prev_progress = $object->lines[$i]->get_prev_progress($object->id); $prev_progress = $object->lines[$i]->get_prev_progress($object->id);
} }
$result = round($object->lines[$i]->situation_percent - $prev_progress, 1).'%'; $result = $isCumulative ?
} else { // old mode: we need to compute the delta (total - sum of previous)
$result = round($object->lines[$i]->situation_percent, 1).'%'; $object->lines[$i]->situation_percent - $prev_progress :
// new mode: we need to compute the total (sum of previous + delta)
$prev_progress + $object->lines[$i]->situation_percent;
} }
$result = round($result, 1).'%';
} }
} }
return $result; return $result;
@@ -2510,17 +2526,9 @@ function pdf_getlinetotalexcltax($object, $i, $outputlangs, $hidedetails = 0)
} elseif (empty($hidedetails) || $hidedetails > 1) { } elseif (empty($hidedetails) || $hidedetails > 1) {
$total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht); $total_ht = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ht : $object->lines[$i]->total_ht);
if (!empty($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) { if (!empty($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
// TODO Remove this. The total should be saved correctly in database instead of being modified here. $total_ht *= $object->lines[$i]->getSituationRatio();
$prev_progress = 0;
$progress = 1;
if (method_exists($object->lines[$i], 'get_prev_progress')) {
$prev_progress = $object->lines[$i]->get_prev_progress($object->id);
$progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
}
$result .= price($sign * ($total_ht / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
} else {
$result .= price($sign * $total_ht, 0, $outputlangs);
} }
$result .= price($sign * $total_ht, 0, $outputlangs);
} }
} }
return $result; return $result;
@@ -2566,17 +2574,9 @@ function pdf_getlinetotalwithtax($object, $i, $outputlangs, $hidedetails = 0)
} elseif (empty($hidedetails) || $hidedetails > 1) { } elseif (empty($hidedetails) || $hidedetails > 1) {
$total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ttc : $object->lines[$i]->total_ttc); $total_ttc = (isModEnabled("multicurrency") && $object->multicurrency_tx != 1 ? $object->lines[$i]->multicurrency_total_ttc : $object->lines[$i]->total_ttc);
if (isset($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) { if (isset($object->lines[$i]->situation_percent) && $object->lines[$i]->situation_percent > 0) {
// TODO Remove this. The total should be saved correctly in database instead of being modified here. $total_ttc *= $object->lines[$i]->getSituationRatio();
$prev_progress = 0;
$progress = 1;
if (method_exists($object->lines[$i], 'get_prev_progress')) {
$prev_progress = $object->lines[$i]->get_prev_progress($object->id);
$progress = ($object->lines[$i]->situation_percent - $prev_progress) / 100;
}
$result .= price($sign * ($total_ttc / ($object->lines[$i]->situation_percent / 100)) * $progress, 0, $outputlangs);
} else {
$result .= price($sign * $total_ttc, 0, $outputlangs);
} }
$result .= price($sign * $total_ttc, 0, $outputlangs);
} }
} }
return $result; return $result;