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

This commit is contained in:
ldestailleur
2025-02-21 15:46:33 +01:00
14 changed files with 131 additions and 150 deletions

View File

@@ -1,19 +1,19 @@
<?php <?php
/* /*
* Copyright (C) 2007-2012 Laurent Destailleur <eldy@users.sourceforge.net> * Copyright (C) 2007-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es> * Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2015 Florian Henry <florian.henry@open-concept.pro> * Copyright (C) 2015 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr> * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
* Copyright (C) 2016 Pierre-Henry Favre <phf@atm-consulting.fr> * Copyright (C) 2016 Pierre-Henry Favre <phf@atm-consulting.fr>
* Copyright (C) 2016-2024 Alexandre Spangaro <aspangaro@open-dsi.fr> * Copyright (C) 2016-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2022 Lionel Vessiller <lvessiller@open-dsi.fr> * Copyright (C) 2022 Lionel Vessiller <lvessiller@open-dsi.fr>
* Copyright (C) 2013-2017 Olivier Geffroy <jeff@jeffinfo.com> * Copyright (C) 2013-2017 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2017 Elarifr. Ari Elbaz <github@accedinfo.com> * Copyright (C) 2017 Elarifr. Ari Elbaz <github@accedinfo.com>
* Copyright (C) 2017-2024 Frédéric France <frederic.france@free.fr> * Copyright (C) 2017-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2017 André Schild <a.schild@aarboard.ch> * Copyright (C) 2017 André Schild <a.schild@aarboard.ch>
* Copyright (C) 2020 Guillaume Alexandre <guillaume@tag-info.fr> * Copyright (C) 2020 Guillaume Alexandre <guillaume@tag-info.fr>
* Copyright (C) 2022 Joachim Kueter <jkueter@gmx.de> * Copyright (C) 2022 Joachim Kueter <jkueter@gmx.de>
* Copyright (C) 2022 Progiseize <a.bisotti@progiseize.fr> * Copyright (C) 2022 Progiseize <a.bisotti@progiseize.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com> * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@@ -1501,14 +1501,20 @@ class AccountancyExport
$objectDirPath = ''; $objectDirPath = '';
$objectFileName = dol_sanitizeFileName($line->doc_ref); $objectFileName = dol_sanitizeFileName($line->doc_ref);
if ($line->doc_type == 'customer_invoice') { if ($line->doc_type == 'customer_invoice') {
$objectDirPath = !empty($conf->invoice->multidir_output[$conf->entity]) ? $conf->invoice->multidir_output[$conf->entity] : $conf->invoice->dir_output; if (getDolGlobalInt('ACCOUNTING_EXPORT_REMOVE_INVOICE_SOURCE_FILE')) {
$objectDirPath = !empty($conf->invoice->multidir_output[$conf->entity]) ? $conf->invoice->multidir_output[$conf->entity] : $conf->invoice->dir_output;
}
} elseif ($line->doc_type == 'expense_report') { } elseif ($line->doc_type == 'expense_report') {
$objectDirPath = !empty($conf->expensereport->multidir_output[$conf->entity]) ? $conf->expensereport->multidir_output[$conf->entity] : $conf->expensereport->dir_output; if (getDolGlobalInt('ACCOUNTING_EXPORT_REMOVE_EXPENSEREPORT_SOURCE_FILE')) {
$objectDirPath = !empty($conf->expensereport->multidir_output[$conf->entity]) ? $conf->expensereport->multidir_output[$conf->entity] : $conf->expensereport->dir_output;
}
} elseif ($line->doc_type == 'supplier_invoice') { } elseif ($line->doc_type == 'supplier_invoice') {
'@phan-var-force FactureFournisseur $invoice'; if (getDolGlobalInt('ACCOUNTING_EXPORT_REMOVE_SUPPLIERINVOICE_SOURCE_FILE')) {
/** @var FactureFournisseur $invoice */ '@phan-var-force FactureFournisseur $invoice';
$objectDirPath = !empty($conf->fournisseur->facture->multidir_output[$conf->entity]) ? $conf->fournisseur->facture->multidir_output[$conf->entity] : $conf->fournisseur->facture->dir_output; /** @var FactureFournisseur $invoice */
$objectDirPath .= '/'.rtrim(get_exdir($invoice->id, 2, 0, 0, $invoice, 'invoice_supplier'), '/'); $objectDirPath = !empty($conf->fournisseur->facture->multidir_output[$conf->entity]) ? $conf->fournisseur->facture->multidir_output[$conf->entity] : $conf->fournisseur->facture->dir_output;
$objectDirPath .= '/' . rtrim(get_exdir($invoice->id, 2, 0, 0, $invoice, 'invoice_supplier'), '/');
}
} }
$arrayofinclusion = array(); $arrayofinclusion = array();
// If it is a supplier invoice, we want to use last uploaded file // If it is a supplier invoice, we want to use last uploaded file
@@ -1715,14 +1721,20 @@ class AccountancyExport
$objectDirPath = ''; $objectDirPath = '';
$objectFileName = dol_sanitizeFileName($line->doc_ref); $objectFileName = dol_sanitizeFileName($line->doc_ref);
if ($line->doc_type == 'customer_invoice') { if ($line->doc_type == 'customer_invoice') {
$objectDirPath = !empty($conf->invoice->multidir_output[$conf->entity]) ? $conf->invoice->multidir_output[$conf->entity] : $conf->invoice->dir_output; if (getDolGlobalInt('ACCOUNTING_EXPORT_REMOVE_INVOICE_SOURCE_FILE')) {
$objectDirPath = !empty($conf->invoice->multidir_output[$conf->entity]) ? $conf->invoice->multidir_output[$conf->entity] : $conf->invoice->dir_output;
}
} elseif ($line->doc_type == 'expense_report') { } elseif ($line->doc_type == 'expense_report') {
$objectDirPath = !empty($conf->expensereport->multidir_output[$conf->entity]) ? $conf->expensereport->multidir_output[$conf->entity] : $conf->expensereport->dir_output; if (getDolGlobalInt('ACCOUNTING_EXPORT_REMOVE_EXPENSEREPORT_SOURCE_FILE')) {
$objectDirPath = !empty($conf->expensereport->multidir_output[$conf->entity]) ? $conf->expensereport->multidir_output[$conf->entity] : $conf->expensereport->dir_output;
}
} elseif ($line->doc_type == 'supplier_invoice') { } elseif ($line->doc_type == 'supplier_invoice') {
'@phan-var-force FactureFournisseur $invoice'; if (getDolGlobalInt('ACCOUNTING_EXPORT_REMOVE_SUPPLIERINVOICE_SOURCE_FILE')) {
/** @var FactureFournisseur $invoice */ '@phan-var-force FactureFournisseur $invoice';
$objectDirPath = !empty($conf->fournisseur->facture->multidir_output[$conf->entity]) ? $conf->fournisseur->facture->multidir_output[$conf->entity] : $conf->fournisseur->facture->dir_output; /** @var FactureFournisseur $invoice */
$objectDirPath .= '/'.rtrim(get_exdir($invoice->id, 2, 0, 0, $invoice, 'invoice_supplier'), '/'); $objectDirPath = !empty($conf->fournisseur->facture->multidir_output[$conf->entity]) ? $conf->fournisseur->facture->multidir_output[$conf->entity] : $conf->fournisseur->facture->dir_output;
$objectDirPath .= '/' . rtrim(get_exdir($invoice->id, 2, 0, 0, $invoice, 'invoice_supplier'), '/');
}
} }
$arrayofinclusion = array(); $arrayofinclusion = array();
// If it is a supplier invoice, we want to use last uploaded file // If it is a supplier invoice, we want to use last uploaded file

View File

@@ -1195,7 +1195,7 @@ if (empty($reshook)) {
$facture_source = new Facture($db); // fetch origin object $facture_source = new Facture($db); // fetch origin object
if ($facture_source->fetch($object->fk_facture_source) > 0) { if ($facture_source->fetch($object->fk_facture_source) > 0) {
if ($facture_source->type == Facture::TYPE_SITUATION) { if ($facture_source->isSituationInvoice()) {
$object->situation_counter = $facture_source->situation_counter; $object->situation_counter = $facture_source->situation_counter;
$object->situation_cycle_ref = $facture_source->situation_cycle_ref; $object->situation_cycle_ref = $facture_source->situation_cycle_ref;
$facture_source->fetchPreviousNextSituationInvoice(); $facture_source->fetchPreviousNextSituationInvoice();
@@ -1240,7 +1240,7 @@ if (empty($reshook)) {
} }
if ($facture_source->type == Facture::TYPE_SITUATION) { if ($facture_source->isSituationInvoice()) {
$source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id $source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id
$line->fk_prev_id = $line->id; // The new line of the new credit note we are creating must be linked to the situation invoice line it is created from $line->fk_prev_id = $line->id; // The new line of the new credit note we are creating must be linked to the situation invoice line it is created from
@@ -2943,7 +2943,7 @@ if (empty($reshook)) {
$object->fetch($id, '', '', 0, true); $object->fetch($id, '', '', 0, true);
if (in_array($object->status, array(Facture::STATUS_CLOSED, Facture::STATUS_VALIDATED)) if (in_array($object->status, array(Facture::STATUS_CLOSED, Facture::STATUS_VALIDATED))
&& $object->type == Facture::TYPE_SITUATION && $object->isSituationInvoice()
&& $usercancreate && $usercancreate
&& !$objectidnext && !$objectidnext
&& $object->is_last_in_cycle() && $object->is_last_in_cycle()
@@ -2999,7 +2999,7 @@ if (empty($reshook)) {
$lineIndex = count($object->tab_previous_situation_invoice) - 1; $lineIndex = count($object->tab_previous_situation_invoice) - 1;
$searchPreviousInvoice = true; $searchPreviousInvoice = true;
while ($searchPreviousInvoice) { while ($searchPreviousInvoice) {
if ($object->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_SITUATION || $lineIndex < 1) { if ($object->tab_previous_situation_invoice[$lineIndex]->isSituationInvoice() || $lineIndex < 1) {
$searchPreviousInvoice = false; // find, exit; $searchPreviousInvoice = false; // find, exit;
break; break;
} else { } else {
@@ -3098,7 +3098,7 @@ if (empty($reshook)) {
$pa_ht = $originLine->pa_ht; $pa_ht = $originLine->pa_ht;
$label = $originLine->label; $label = $originLine->label;
$array_options = $originLine->array_options; $array_options = $originLine->array_options;
if ($object->type == Facture::TYPE_SITUATION) { if ($object->isSituationInvoice()) {
$situation_percent = 0; $situation_percent = 0;
} else { } else {
$situation_percent = 100; $situation_percent = 100;
@@ -3727,12 +3727,12 @@ if ($action == 'create') {
$opt = $form->selectSituationInvoices(GETPOSTINT('originid'), $socid); $opt = $form->selectSituationInvoices(GETPOSTINT('originid'), $socid);
print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">'; print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
$tmp = '<input type="radio" name="type" value="5"'.(GETPOST('type') == 5 && GETPOSTINT('originid') ? ' checked' : ''); $tmp = '<input id="radio_situation_bis" type="radio" name="type" value="5"'.(GETPOST('type') == 5 && GETPOSTINT('originid') ? ' checked' : '');
if ($opt == ('<option value ="0" selected>'.$langs->trans('NoSituations').'</option>') || (GETPOST('origin') && GETPOST('origin') != 'facture' && GETPOST('origin') != 'commande')) { if ($opt == ('<option value ="0" selected>'.$langs->trans('NoSituations').'</option>') || (GETPOST('origin') && GETPOST('origin') != 'facture' && GETPOST('origin') != 'commande')) {
$tmp .= ' disabled'; $tmp .= ' disabled';
} }
$tmp .= '> '; $tmp .= '> ';
$text = $tmp.'<label>'.$langs->trans("InvoiceSituationAsk").'</label> '; $text = $tmp.'<label for="radio_situation_bis">'.$langs->trans("InvoiceSituationAsk").'</label> ';
$text .= '<select class="flat" id="situations" name="situations"'; $text .= '<select class="flat" id="situations" name="situations"';
if ($opt == ('<option value ="0" selected>'.$langs->trans('NoSituations').'</option>') || (GETPOST('origin') && GETPOST('origin') != 'facture' && GETPOST('origin') != 'commande')) { if ($opt == ('<option value ="0" selected>'.$langs->trans('NoSituations').'</option>') || (GETPOST('origin') && GETPOST('origin') != 'facture' && GETPOST('origin') != 'commande')) {
$text .= ' disabled'; $text .= ' disabled';
@@ -5625,7 +5625,7 @@ if ($action == 'create') {
// Retained warranty : usually use on construction industry // Retained warranty : usually use on construction industry
if (!empty($object->situation_final) && !empty($object->retained_warranty) && $displayWarranty) { if (!empty($object->situation_final) && !empty($object->retained_warranty) && $displayWarranty) {
// Billed - retained warranty // Billed - retained warranty
if ($object->type == Facture::TYPE_SITUATION) { if ($object->isSituationInvoice()) {
$retainedWarranty = $total_global_ttc * $object->retained_warranty / 100; $retainedWarranty = $total_global_ttc * $object->retained_warranty / 100;
} else { } else {
// Because one day retained warranty could be used on standard invoices // Because one day retained warranty could be used on standard invoices
@@ -6026,7 +6026,7 @@ if ($action == 'create') {
// For situation invoice with excess received // For situation invoice with excess received
if ($object->status > Facture::STATUS_DRAFT if ($object->status > Facture::STATUS_DRAFT
&& $object->type == Facture::TYPE_SITUATION && $object->isSituationInvoice()
&& ($object->total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits) > 0 && ($object->total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits) > 0
&& $usercancreate && $usercancreate
&& !$objectidnext && !$objectidnext
@@ -6056,7 +6056,7 @@ if ($action == 'create') {
// Remove situation from cycle // Remove situation from cycle
if (in_array($object->status, array(Facture::STATUS_CLOSED, Facture::STATUS_VALIDATED)) if (in_array($object->status, array(Facture::STATUS_CLOSED, Facture::STATUS_VALIDATED))
&& $object->type == Facture::TYPE_SITUATION && $object->isSituationInvoice()
&& $usercancreate && $usercancreate
&& !$objectidnext && !$objectidnext
&& $object->situation_counter > 1 && $object->situation_counter > 1

View File

@@ -5615,14 +5615,22 @@ class Facture extends CommonInvoice
return $hasDelay; return $hasDelay;
} }
/**
* Check if an invoice is a situation invoice
*
* @return int Return a value if invoice is a situation invoice
*/
public function isSituationInvoice()
{
return $this->situation_cycle_ref;
}
/** /**
* Currently used for documents generation : to know if retained warranty need to be displayed * Currently used for documents generation : to know if retained warranty need to be displayed
* @return bool * @return bool
*/ */
public function displayRetainedWarranty() public function displayRetainedWarranty()
{ {
global $conf;
// TODO : add a flag on invoices to store this conf : INVOICE_RETAINED_WARRANTY_LIMITED_TO_FINAL_SITUATION // TODO : add a flag on invoices to store this conf : INVOICE_RETAINED_WARRANTY_LIMITED_TO_FINAL_SITUATION
// note : we don't need to test INVOICE_USE_RETAINED_WARRANTY because if $this->retained_warranty is not empty it's because it was set when this conf was active // note : we don't need to test INVOICE_USE_RETAINED_WARRANTY because if $this->retained_warranty is not empty it's because it was set when this conf was active
@@ -5631,7 +5639,7 @@ class Facture extends CommonInvoice
if (!empty($this->retained_warranty)) { if (!empty($this->retained_warranty)) {
$displayWarranty = true; $displayWarranty = true;
if ($this->type == Facture::TYPE_SITUATION && getDolGlobalString('INVOICE_RETAINED_WARRANTY_LIMITED_TO_FINAL_SITUATION')) { if ($this->isSituationInvoice() && getDolGlobalString('INVOICE_RETAINED_WARRANTY_LIMITED_TO_FINAL_SITUATION')) {
// Check if this situation invoice is 100% for real // Check if this situation invoice is 100% for real
$displayWarranty = false; $displayWarranty = false;
if (!empty($this->situation_final)) { if (!empty($this->situation_final)) {
@@ -5659,7 +5667,6 @@ class Facture extends CommonInvoice
*/ */
public function getRetainedWarrantyAmount($rounding = -1) public function getRetainedWarrantyAmount($rounding = -1)
{ {
global $conf;
if (empty($this->retained_warranty)) { if (empty($this->retained_warranty)) {
return -1; return -1;
} }
@@ -5667,7 +5674,7 @@ class Facture extends CommonInvoice
$retainedWarrantyAmount = 0; $retainedWarrantyAmount = 0;
// Billed - retained warranty // Billed - retained warranty
if ($this->type == Facture::TYPE_SITUATION && getDolGlobalString('INVOICE_RETAINED_WARRANTY_LIMITED_TO_FINAL_SITUATION')) { if ($this->isSituationInvoice() && getDolGlobalString('INVOICE_RETAINED_WARRANTY_LIMITED_TO_FINAL_SITUATION')) {
$displayWarranty = true; $displayWarranty = true;
// Check if this situation invoice is 100% for real // Check if this situation invoice is 100% for real
if (!empty($this->lines)) { if (!empty($this->lines)) {

View File

@@ -124,7 +124,7 @@ report_header($name, '', $period, $periodlink, $description, $builddate, $export
$p = explode(":", getDolGlobalString('MAIN_INFO_SOCIETE_COUNTRY')); $p = explode(":", getDolGlobalString('MAIN_INFO_SOCIETE_COUNTRY'));
$idpays = $p[0]; $idpays = $p[0];
$sql = "SELECT f.rowid, f.ref, f.type, f.datef, f.ref_client,"; $sql = "SELECT f.rowid, f.ref, f.type, f.datef, f.ref_client, f.situation_cycle_ref,";
$sql .= " fd.product_type, fd.total_ht, fd.total_tva, fd.tva_tx, fd.total_ttc, fd.localtax1_tx, fd.localtax2_tx, fd.total_localtax1, fd.total_localtax2, fd.rowid as id, fd.situation_percent,"; $sql .= " fd.product_type, fd.total_ht, fd.total_tva, fd.tva_tx, fd.total_ttc, fd.localtax1_tx, fd.localtax2_tx, fd.total_localtax1, fd.total_localtax2, fd.rowid as id, fd.situation_percent,";
$sql .= " s.rowid as socid, s.nom as name, s.code_compta as code_compta_client, s.client,"; $sql .= " s.rowid as socid, s.nom as name, s.code_compta as code_compta_client, s.client,";
$sql .= " p.rowid as pid, p.ref as pref,"; $sql .= " p.rowid as pid, p.ref as pref,";
@@ -202,7 +202,7 @@ if ($result) {
$line = new FactureLigne($db); $line = new FactureLigne($db);
$line->fetch($obj->id); // id of line $line->fetch($obj->id); // id of line
$prev_progress = 0; $prev_progress = 0;
if ($obj->type == Facture::TYPE_SITUATION) { if ($obj->situation_cycle_ref > 0) { // It is a situation invoice
// Avoid divide by 0 // Avoid divide by 0
if ($obj->situation_percent == 0) { if ($obj->situation_percent == 0) {
$situation_ratio = 0; $situation_ratio = 0;

View File

@@ -4489,6 +4489,14 @@ function dol_print_phone($phone, $countrycode = '', $cid = 0, $socid = 0, $addli
$newphonewa = $newphone; $newphonewa = $newphone;
$newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 3).$separ.substr($newphone, 6, 3).$separ.substr($newphone, 10, 3).$separ.substr($newphone, 14, 3); $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 3).$separ.substr($newphone, 6, 3).$separ.substr($newphone, 10, 3).$separ.substr($newphone, 14, 3);
} }
} elseif (strtoupper($countrycode) == "IN") {//India
if (dol_strlen($phone) == 13) {
if ($withpicto == 'phone') {//ex: +91_AB_CDEF_GHIJ
$newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 2).$separ.substr($newphone, 5, 4).$separ.substr($newphone, 9, 4);
} else {//ex: +91_ABCDE_FGHIJ
$newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 5).$separ.substr($newphone, 8, 5);
}
}
} }
$newphoneastart = $newphoneaend = ''; $newphoneastart = $newphoneaend = '';

View File

@@ -786,7 +786,7 @@ class pdf_eratosthene extends ModelePDFCommandes
// Add last page for document footer if there are not enough size left // Add last page for document footer if there are not enough size left
$afterPosData = $this->getMaxAfterColsLinePositionsData(); $afterPosData = $this->getMaxAfterColsLinePositionsData();
if ($afterPosData['y'] > $this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot)) { if (isset($afterPosData['y']) && $afterPosData['y'] > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforinfotot))) {
$pdf->AddPage(); $pdf->AddPage();
if (!empty($tplidx)) { if (!empty($tplidx)) {
$pdf->useTemplate($tplidx); $pdf->useTemplate($tplidx);

View File

@@ -3248,7 +3248,7 @@ class pdf_octopus extends ModelePDFFactures
if (!empty($object->retained_warranty)) { if (!empty($object->retained_warranty)) {
$displayWarranty = true; $displayWarranty = true;
if ($object->type == Facture::TYPE_SITUATION && getDolGlobalString('USE_RETAINED_WARRANTY_ONLY_FOR_SITUATION_FINAL')) { if ($object->isSituationInvoice() && getDolGlobalString('USE_RETAINED_WARRANTY_ONLY_FOR_SITUATION_FINAL')) {
// Check if this situation invoice is 100% for real // Check if this situation invoice is 100% for real
$displayWarranty = false; $displayWarranty = false;
if (!empty($object->situation_final)) { if (!empty($object->situation_final)) {

View File

@@ -970,7 +970,7 @@ class pdf_sponge extends ModelePDFFactures
$afterPosData = $this->getMaxAfterColsLinePositionsData(); $afterPosData = $this->getMaxAfterColsLinePositionsData();
$page_bottom_margin = $this->heightforfooter + $this->heightforfreetext + $this->heightforinfotot + $this->getHeightForQRInvoice($pdf->getPage(), $object, $langs); $page_bottom_margin = $this->heightforfooter + $this->heightforfreetext + $this->heightforinfotot + $this->getHeightForQRInvoice($pdf->getPage(), $object, $langs);
if ($afterPosData['y'] > $this->page_hauteur - $page_bottom_margin) { if (isset($afterPosData['y']) && $afterPosData['y'] > $this->page_hauteur - $page_bottom_margin) {
$pdf->AddPage(); $pdf->AddPage();
if (!empty($tplidx)) { if (!empty($tplidx)) {
$pdf->useTemplate($tplidx); $pdf->useTemplate($tplidx);

View File

@@ -805,7 +805,7 @@ class pdf_cyan extends ModelePDFPropales
// Add last page for document footer if there are not enough size left // Add last page for document footer if there are not enough size left
$afterPosData = $this->getMaxAfterColsLinePositionsData(); $afterPosData = $this->getMaxAfterColsLinePositionsData();
if ($afterPosData['y'] > $this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforsignature + $heightforinfotot)) { if (isset($afterPosData['y']) && $afterPosData['y'] > ($this->page_hauteur - ($heightforfooter + $heightforfreetext + $heightforsignature + $heightforinfotot))) {
$pdf->AddPage(); $pdf->AddPage();
if (!empty($tplidx)) { if (!empty($tplidx)) {
$pdf->useTemplate($tplidx); $pdf->useTemplate($tplidx);

View File

@@ -159,7 +159,7 @@ print '</th>';
// Fields for situation invoice // Fields for situation invoice
if (isset($this->situation_cycle_ref) && $this->situation_cycle_ref) { if (isset($this->situation_cycle_ref) && $this->situation_cycle_ref) {
print '<th class="linecolcycleref right">'.$langs->trans('Progress').'</th>'; print '<th class="linecolcycleref right">'.$langs->trans('CumulativeProgression').'</th>';
if (getDolGlobalInt('INVOICE_USE_SITUATION') == 2) { if (getDolGlobalInt('INVOICE_USE_SITUATION') == 2) {
print '<th class="linecolcycleref2 right">' . $langs->trans('SituationInvoiceProgressCurrent') . '</th>'; print '<th class="linecolcycleref2 right">' . $langs->trans('SituationInvoiceProgressCurrent') . '</th>';
} }

View File

@@ -668,7 +668,7 @@ if ($num > 0) {
$datefromto = (empty($datelastrun) ? '' : dol_print_date($datelastrun, 'dayhoursec', 'tzserver')).' - '.(empty($datelastresult) ? '' : dol_print_date($datelastresult, 'dayhoursec', 'tzserver')); $datefromto = (empty($datelastrun) ? '' : dol_print_date($datelastrun, 'dayhoursec', 'tzserver')).' - '.(empty($datelastresult) ? '' : dol_print_date($datelastresult, 'dayhoursec', 'tzserver'));
// Date start last run // Date start last run
print '<td class="center" title="'.dol_escape_htmltag($datefromto).'">'; print '<td class="center lineheightsmall" title="'.dol_escape_htmltag($datefromto).'">';
if (!empty($datelastrun)) { if (!empty($datelastrun)) {
print dol_print_date($datelastrun, 'dayhoursec', 'tzserver'); print dol_print_date($datelastrun, 'dayhoursec', 'tzserver');
} }
@@ -696,14 +696,14 @@ if ($num > 0) {
// Output of last run // Output of last run
print '<td class="small minwidth150">'; print '<td class="small minwidth150">';
if (!empty($obj->lastoutput)) { if (!empty($obj->lastoutput)) {
print '<div class="twolinesmax classfortooltip" title="'.dol_escape_htmltag($obj->lastoutput, 1, 1).'">'; print '<div class="twolinesmax lineheightsmall classfortooltip" title="'.dol_escape_htmltag($obj->lastoutput, 1, 1).'">';
print dol_trunc(dolGetFirstLineOfText($obj->lastoutput, 2), 100); print dol_trunc(dolGetFirstLineOfText($obj->lastoutput, 2), 100);
print '</div>'; print '</div>';
} }
print '</td>'; print '</td>';
// Next run date // Next run date
print '<td class="center">'; print '<td class="center lineheightsmall">';
if (!empty($obj->datenextrun)) { if (!empty($obj->datenextrun)) {
$datenextrun = $db->jdate($obj->datenextrun); $datenextrun = $db->jdate($obj->datenextrun);
if (empty($obj->status)) { if (empty($obj->status)) {

View File

@@ -678,4 +678,5 @@ SearchValidatedSupplierInvoicesWithDate=Search unpaid supplier invoices with a v
SendEmailsRemindersOnSupplierInvoiceDueDate=Send reminder by email for validated and unpaid supplier invoices SendEmailsRemindersOnSupplierInvoiceDueDate=Send reminder by email for validated and unpaid supplier invoices
PaymentMadeForSeveralInvoices=Payment made for several invoices PaymentMadeForSeveralInvoices=Payment made for several invoices
SituationInvoiceProgressCurrent=Invoice progress SituationInvoiceProgressCurrent=Invoice progress
CumulativeProgression=Cumulative progress
INVOICE_ADD_EPC_QR_CODEPay=Scan this QR code to pay with a smartphone supporting payment with EPC QR code. INVOICE_ADD_EPC_QR_CODEPay=Scan this QR code to pay with a smartphone supporting payment with EPC QR code.

View File

@@ -566,6 +566,39 @@ if (empty($reshook)) {
setEventMessages($object->error, $object->errors, 'errors'); setEventMessages($object->error, $object->errors, 'errors');
break; break;
} }
// Update level price extrafields
$price_extralabels = $extrafields->fetch_name_optionals_label("product_price");
if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && !empty($price_extralabels)) {
$sql = "SELECT rowid";
$sql .= " FROM ".$object->db->prefix()."product_price";
$sql .= " WHERE entity IN (".getEntity('productprice').")";
$sql .= " AND price_level=".((int) $key); // $i
$sql .= " AND fk_product = ".((int) $object->id);
$sql .= " ORDER BY date_price DESC, rowid DESC";
$sql .= " LIMIT 1";
$resql = $object->db->query($sql);
if ($resql) {
$lineid = $object->db->fetch_object($resql);
$db->free($resql);
}
if (!empty($lineid->rowid)) {
foreach ($price_extralabels as $code => $label) {
$code_array = GETPOST($code, 'array');
$object->array_options['options_'.$code] = $code_array[$key];
}
// We need to force table to update product_price and not product extrafields
$object->id = $lineid->rowid;
$object->table_element = 'product_price';
$result = $object->insertExtraFields();
// Back to product table
$object->id = $id;
$object->table_element = 'product';
if ($result < 0) {
$error++;
}
}
}
} }
} }
@@ -1536,39 +1569,6 @@ if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUS
} }
print '</td></tr>'; print '</td></tr>';
} }
// Extrafields
$extrafields->fetch_name_optionals_label("product");
$extralabels = !empty($extrafields->attributes["product"]['label']) ? $extrafields->attributes["product"]['label'] : [];
$extrafield_values = $extrafields->getOptionalsFromPost("product");
$sql = "SELECT";
$sql .= " fk_object";
foreach ($extralabels as $key => $value) {
$sql .= ", ".$key;
}
$sql .= " FROM ".MAIN_DB_PREFIX."product_extrafields";
$sql .= " WHERE fk_object = ".((int) $object->id);
$resql = $db->query($sql);
if ($resql) {
$obj = $db->fetch_object($resql);
foreach ($extralabels as $key => $value) {
if (!empty($extrafields->attributes["product"]['list'][$key]) && ($extrafields->attributes["product"]['list'][$key] == 1 || $extrafields->attributes["product"]['list'][$key] == 3 || ($action == "edit_price" && $extrafields->attributes["product"]['list'][$key] == 4))) {
if (!empty($extrafields->attributes["product"]['langfile'][$key])) {
$langs->load($extrafields->attributes["product"]['langfile'][$key]);
}
print '<tr><td'.($extrafields->attributes["product"]['required'][$key] ? ' class="fieldrequired"' : '').'>';
if (!empty($extrafields->attributes["product"]['help'][$key])) {
print $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product"]['help'][$key]));
} else {
print $langs->trans($value);
}
print '<td align="left">'.$extrafields->showOutputField($key, $obj->{$key}, '', 'product')."</td></tr>";
}
}
$db->free($resql);
}
} }
print "</table>\n"; print "</table>\n";
@@ -1783,59 +1783,6 @@ if (($action == 'edit_price' || $action == 'edit_level_price') && $object->getRi
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
// Extrafields
$extrafields->fetch_name_optionals_label("product");
$extralabels = !empty($extrafields->attributes["product"]['label']) ? $extrafields->attributes["product"]['label'] : '';
$extrafield_values = $extrafields->getOptionalsFromPost("product");
if (!empty($extralabels)) {
if (empty($object->id)) {
foreach ($extralabels as $key => $value) {
if (!empty($extrafields->attributes["product"]['list'][$key]) && ($extrafields->attributes["product"]['list'][$key] == 1 || $extrafields->attributes["product"]['list'][$key] == 3 || ($action == "edit_price" && $extrafields->attributes["product"]['list'][$key] == 4))) {
if (!empty($extrafields->attributes["product"]['langfile'][$key])) {
$langs->load($extrafields->attributes["product"]['langfile'][$key]);
}
print '<tr><td'.($extrafields->attributes["product"]['required'][$key] ? ' class="fieldrequired"' : '').'>';
if (!empty($extrafields->attributes["product"]['help'][$key])) {
print $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product"]['help'][$key]));
} else {
print $langs->trans($value);
}
print '</td><td>'.$extrafields->showInputField($key, GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : '', '', '', '', '', 0, 'product').'</td></tr>';
}
}
} else {
$sql = "SELECT";
$sql .= " fk_object";
foreach ($extralabels as $key => $value) {
$sql .= ", ".$key;
}
$sql .= " FROM ".MAIN_DB_PREFIX."product_extrafields";
$sql .= " WHERE fk_object = ".((int) $object->id);
$resql = $db->query($sql);
if ($resql) {
$obj = $db->fetch_object($resql);
foreach ($extralabels as $key => $value) {
if (!empty($extrafields->attributes["product"]['list'][$key]) && ($extrafields->attributes["product"]['list'][$key] == 1 || $extrafields->attributes["product"]['list'][$key] == 3 || ($action == "edit_price" && $extrafields->attributes["product"]['list'][$key] == 4))) {
if (!empty($extrafields->attributes["product"]['langfile'][$key])) {
$langs->load($extrafields->attributes["product"]['langfile'][$key]);
}
print '<tr><td'.($extrafields->attributes["product"]['required'][$key] ? ' class="fieldrequired"' : '').'>';
if (!empty($extrafields->attributes["product"]['help'][$key])) {
print $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product"]['help'][$key]));
} else {
print $langs->trans($value);
}
print '</td><td>'.$extrafields->showInputField($key, GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : $obj->{$key}, '', '', '', '', 0, 'product');
print '</td></tr>';
}
}
$db->free($resql);
}
}
}
$parameters = array(); $parameters = array();
$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
@@ -2490,6 +2437,8 @@ if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT
print '<table class="liste centpercent">'."\n"; print '<table class="liste centpercent">'."\n";
if (count($prodcustprice->lines) > 0 || $search_soc) { if (count($prodcustprice->lines) > 0 || $search_soc) {
$extrafields->fetch_name_optionals_label("product_customer_price");
$custom_price_extralabels = !empty($extrafields->attributes["product_customer_price"]['label']) ? $extrafields->attributes["product_customer_price"]['label'] : '';
if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
$colspan = 10; $colspan = 10;
} else { } else {
@@ -2498,8 +2447,8 @@ if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT
if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") { if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") {
$colspan++; $colspan++;
} }
if (!empty($price_extralabels) && is_array($price_extralabels)) { if (!empty($custom_price_extralabels) && is_array($custom_price_extralabels)) {
$colspan += count($price_extralabels); $colspan += count($custom_price_extralabels);
} }
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';

View File

@@ -507,15 +507,6 @@ if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT
} }
print '</td></tr>'; print '</td></tr>';
// Update all child soc
print '<tr><td>';
print $langs->trans('ForceUpdateChildPriceSoc');
print '</td>';
print '<td>';
print '<input type="checkbox" name="updatechildprice" value="1">';
print '</td>';
print '</tr>';
// Extrafields // Extrafields
$extrafields->fetch_name_optionals_label("product_customer_price"); $extrafields->fetch_name_optionals_label("product_customer_price");
$extralabels = !empty($extrafields->attributes["product_customer_price"]['label']) ? $extrafields->attributes["product_customer_price"]['label'] : ''; $extralabels = !empty($extrafields->attributes["product_customer_price"]['label']) ? $extrafields->attributes["product_customer_price"]['label'] : '';
@@ -572,6 +563,12 @@ if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT
print '</table>'; print '</table>';
// Update all child soc
print '<center>';
print '<input type="checkbox" name="updatechildprice" id="updatechildprice" value="1"> ';
print '<label for="updatechildprice">'.$langs->trans('ForceUpdateChildPriceSoc').'</label>';
print '</center>';
print $form->buttonsSaveCancel(); print $form->buttonsSaveCancel();
print '</form>'; print '</form>';
@@ -759,19 +756,26 @@ if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT
} }
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';
$colspan = 0;
foreach ($prodcustprice->fields as $key => $val) { foreach ($prodcustprice->fields as $key => $val) {
if (!empty($arrayfields['t.'.$key]['checked'])) { if (!empty($arrayfields['t.'.$key]['checked'])) {
print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], $key, '', $param, '', $sortfield, $sortorder)."\n"; print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], $key, '', $param, '', $sortfield, $sortorder)."\n";
$colspan++;
} }
} }
if (!empty($extralabels) && is_array($extralabels)) { if (!empty($extralabels) && is_array($extralabels)) {
foreach ($extralabels as $key => $val) { foreach ($extralabels as $key => $val) {
if (!empty($arrayfields['ef.'.$key]['checked'])) { if (!empty($arrayfields['ef.'.$key]['checked'])) {
print getTitleFieldOfList($arrayfields['ef.'.$key]['label'], 0, $_SERVER['PHP_SELF'], $key, '', $param, '', $sortfield, $sortorder)."\n"; print getTitleFieldOfList($arrayfields['ef.'.$key]['label'], 0, $_SERVER['PHP_SELF'], $key, '', $param, '', $sortfield, $sortorder)."\n";
$colspan++;
} }
} }
} }
print '<td></td>'; print '<td></td>';
$colspan++;
print '</tr>'; print '</tr>';
if (count($prodcustprice->lines) > 0 || $search_prod) { if (count($prodcustprice->lines) > 0 || $search_prod) {
@@ -826,6 +830,7 @@ if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT
print '<td class="left">'; print '<td class="left">';
print $userstatic->getNomUrl(-1); print $userstatic->getNomUrl(-1);
print '</td>'; print '</td>';
// Extrafields // Extrafields
$extrafields->fetch_name_optionals_label("product_customer_price"); $extrafields->fetch_name_optionals_label("product_customer_price");
$extralabels = $extrafields->attributes["product_customer_price"]['label']; $extralabels = $extrafields->attributes["product_customer_price"]['label'];
@@ -876,11 +881,10 @@ if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT
print "</tr>\n"; print "</tr>\n";
} }
} else { } else {
$colspan = 10;
if ($user->hasRight('produit', 'supprimer') || $user->hasRight('service', 'supprimer')) { if ($user->hasRight('produit', 'supprimer') || $user->hasRight('service', 'supprimer')) {
$colspan += 1; $colspan += 1;
} }
print '<tr class="oddeven"><td colspan="'.$colspan.'">'.$langs->trans('None').'</td></tr>'; print '<tr class="oddeven"><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans('None').'</span></td></tr>';
} }
print "</table>"; print "</table>";