From e46faacac1d99c8a82eee26a0bcee616e3347936 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Wed, 2 Jun 2021 18:11:47 +0200 Subject: [PATCH 01/58] FIX : Add process payment with online link order --- htdocs/public/payment/paymentok.php | 101 ++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index f4b9f0feb5b..5f8f90ba72b 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -721,6 +721,107 @@ if ($ispaymentok) $postactionmessages[] = 'Invoice paid '.$tmptag['INV'].' was not found'; $ispostactionok = -1; } + } elseif (array_key_exists('ORD', $tmptag) && $tmptag['ORD'] > 0) { + // Record payment + include_once DOL_DOCUMENT_ROOT . '/commande/class/commande.class.php'; + $object = new Commande($db); + $result = $object->fetch($tmptag['ORD']); + if ($result) { + $FinalPaymentAmt = $_SESSION["FinalPaymentAmt"]; + + $paymentTypeId = 0; + if ($paymentmethod == 'paybox') $paymentTypeId = $conf->global->PAYBOX_PAYMENT_MODE_FOR_PAYMENTS; + if ($paymentmethod == 'paypal') $paymentTypeId = $conf->global->PAYPAL_PAYMENT_MODE_FOR_PAYMENTS; + if ($paymentmethod == 'stripe') $paymentTypeId = $conf->global->STRIPE_PAYMENT_MODE_FOR_PAYMENTS; + if (empty($paymentTypeId)) { + $paymentType = $_SESSION["paymentType"]; + if (empty($paymentType)) $paymentType = 'CB'; + $paymentTypeId = dol_getIdFromCode($db, $paymentType, 'c_paiement', 'code', 'id', 1); + } + + $currencyCodeType = $_SESSION['currencyCodeType']; + + // Do action only if $FinalPaymentAmt is set (session variable is cleaned after this page to avoid duplicate actions when page is POST a second time) + if (!empty($FinalPaymentAmt) && $paymentTypeId > 0) { + include_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; + $invoice = new Facture($db); + $result = $invoice->createFromOrder($object, $user); + if ($result > 0) { + $object->classifyBilled($user); + $invoice->validate($user); + // Creation of payment line + include_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php'; + $paiement = new Paiement($db); + $paiement->datepaye = $now; + if ($currencyCodeType == $conf->currency) { + $paiement->amounts = array($invoice->id => $FinalPaymentAmt); // Array with all payments dispatching with invoice id + } else { + $paiement->multicurrency_amounts = array($invoice->id => $FinalPaymentAmt); // Array with all payments dispatching + + $postactionmessages[] = 'Payment was done in a different currency that currency expected of company'; + $ispostactionok = -1; + $error++; // Not yet supported + } + $paiement->paiementid = $paymentTypeId; + $paiement->num_payment = ''; + $paiement->note_public = 'Online payment ' . dol_print_date($now, 'standard') . ' from ' . $ipaddress; + $paiement->ext_payment_id = $TRANSACTIONID; + $paiement->ext_payment_site = $service; + + if (!$error) { + $paiement_id = $paiement->create($user, 1); // This include closing invoices and regenerating documents + if ($paiement_id < 0) { + $postactionmessages[] = $paiement->error . ' ' . join("
\n", $paiement->errors); + $ispostactionok = -1; + $error++; + } else { + $postactionmessages[] = 'Payment created'; + $ispostactionok = 1; + } + } + + if (!$error && !empty($conf->banque->enabled)) { + $bankaccountid = 0; + if ($paymentmethod == 'paybox') $bankaccountid = $conf->global->PAYBOX_BANK_ACCOUNT_FOR_PAYMENTS; + elseif ($paymentmethod == 'paypal') $bankaccountid = $conf->global->PAYPAL_BANK_ACCOUNT_FOR_PAYMENTS; + elseif ($paymentmethod == 'stripe') $bankaccountid = $conf->global->STRIPE_BANK_ACCOUNT_FOR_PAYMENTS; + + if ($bankaccountid > 0) { + $label = '(CustomerInvoicePayment)'; + if ($object->type == Facture::TYPE_CREDIT_NOTE) $label = '(CustomerInvoicePaymentBack)'; // Refund of a credit note + $result = $paiement->addPaymentToBank($user, 'payment', $label, $bankaccountid, '', ''); + if ($result < 0) { + $postactionmessages[] = $paiement->error . ' ' . join("
\n", $paiement->errors); + $ispostactionok = -1; + $error++; + } else { + $postactionmessages[] = 'Bank transaction of payment created'; + $ispostactionok = 1; + } + } else { + $postactionmessages[] = 'Setup of bank account to use in module ' . $paymentmethod . ' was not set. No way to record the payment.'; + $ispostactionok = -1; + $error++; + } + } + + if (!$error) { + $db->commit(); + } else { + $db->rollback(); + } + } else { + $postactionmessages[] = 'Failed to create invoice form order ' . $tmptag['ORD'] . '.'; + $ispostactionok = -1; + } + } else { + $postactionmessages[] = 'Failed to get a valid value for "amount paid" (' . $FinalPaymentAmt . ') or "payment type" (' . $paymentType . ') to record the payment of order ' . $tmptag['ORD'] . '. May be payment was already recorded.'; + $ispostactionok = -1; + } + } else { + $postactionmessages[] = 'Order paid ' . $tmptag['ORD'] . ' was not found'; + $ispostactionok = -1; + } } else { // Nothing done } From 4e1fe23b7e1a83d34b45c51348968d415626085c Mon Sep 17 00:00:00 2001 From: Nicolas Date: Wed, 9 Jun 2021 15:48:31 +0200 Subject: [PATCH 02/58] FIX: add check display payment link if invoice module is enabled --- htdocs/commande/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 1ef37552f1f..4913731efb5 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -2633,7 +2633,7 @@ if ($action == 'create' && $usercancreate) $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem, $compatibleImportElementsList); // Show online payment link - $useonlinepayment = (!empty($conf->paypal->enabled) || !empty($conf->stripe->enabled) || !empty($conf->paybox->enabled)); + $useonlinepayment = ((!empty($conf->paypal->enabled) || !empty($conf->stripe->enabled) || !empty($conf->paybox->enabled)) && !empty($conf->facture->enabled)); if (!empty($conf->global->ORDER_HIDE_ONLINE_PAYMENT_ON_ORDER)) $useonlinepayment = 0; if ($object->statut != Commande::STATUS_DRAFT && $useonlinepayment) { From 1e7df0ba9fe9f8b247e77ac8b0f75b98a969bb01 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Thu, 10 Jun 2021 21:53:06 +0200 Subject: [PATCH 03/58] NEW: holiday: handle monthly updates with cronjob --- htdocs/core/modules/modHoliday.class.php | 22 ++++++++++++++++++++++ htdocs/holiday/class/holiday.class.php | 2 +- htdocs/holiday/define_holiday.php | 4 ---- htdocs/holiday/list.php | 3 --- htdocs/hrm/index.php | 10 ---------- htdocs/langs/en_US/holiday.lang | 1 + test/phpunit/HolidayTest.php | 2 +- 7 files changed, 25 insertions(+), 19 deletions(-) diff --git a/htdocs/core/modules/modHoliday.class.php b/htdocs/core/modules/modHoliday.class.php index 23cbf7eddf8..76700b59b31 100644 --- a/htdocs/core/modules/modHoliday.class.php +++ b/htdocs/core/modules/modHoliday.class.php @@ -135,6 +135,28 @@ class modHoliday extends DolibarrModules //$r++; + // Cronjobs + $arraydate = dol_getdate(dol_now()); + $datestart = dol_mktime(4, 0, 0, $arraydate['mon'], $arraydate['mday'], $arraydate['year']); + $this->cronjobs = array( + 0 => array( + 'label' => 'HolidayBalanceMonthlyUpdate', + 'jobtype' => 'method', + 'class' => 'holiday/class/holiday.class.php', + 'objectname' => 'Holiday', + 'method' => 'updateBalance', + 'parameters' => '', + 'comment' => 'Update holiday balance every month', + 'frequency' => 1, + 'unitfrequency' => 3600 * 24, + 'priority' => 50, + 'status' => 1, + 'test' => '$conf->holiday->enabled', + 'datestart' => $datestart + ) + ); + + // Permissions $this->rights = array(); // Permission array used by this module $r = 0; diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index 55dd1c4bafb..b885202f3a9 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -227,7 +227,7 @@ class Holiday extends CommonObject if ($result >= 0) { $this->db->commit(); - return 1; + return 0; // for cronjob use (0 is OK, any other value is an error code) } else { $this->db->rollback(); return -1; diff --git a/htdocs/holiday/define_holiday.php b/htdocs/holiday/define_holiday.php index b3d2c25adda..fcb8b73d486 100644 --- a/htdocs/holiday/define_holiday.php +++ b/htdocs/holiday/define_holiday.php @@ -193,10 +193,6 @@ llxHeader('', $langs->trans('CPTitreMenu')); $typeleaves = $holiday->getTypes(1, 1); -$result = $holiday->updateBalance(); // Create users into table holiday if they don't exists. TODO Remove this whif we use field into table user. -if ($result < 0) { - setEventMessages($holiday->error, $holiday->errors, 'errors'); -} print '
'; diff --git a/htdocs/holiday/list.php b/htdocs/holiday/list.php index c62185d5f2a..9d569f4344e 100644 --- a/htdocs/holiday/list.php +++ b/htdocs/holiday/list.php @@ -231,9 +231,6 @@ $formfile = new FormFile($db); $fuser = new User($db); $holidaystatic = new Holiday($db); -// Update sold -$result = $object->updateBalance(); - $title = $langs->trans('CPTitreMenu'); llxHeader('', $title); diff --git a/htdocs/hrm/index.php b/htdocs/hrm/index.php index 50fd4c3f521..6cc4dc3b5bd 100644 --- a/htdocs/hrm/index.php +++ b/htdocs/hrm/index.php @@ -68,16 +68,6 @@ if (empty($conf->global->MAIN_INFO_SOCIETE_NOM) || empty($conf->global->MAIN_INF $max = $conf->global->MAIN_SIZE_SHORTLIST_LIMIT; -/* - * Actions - */ - -// Update sold -if (!empty($conf->holiday->enabled) && !empty($setupcompanynotcomplete)) { - $holidaystatic = new Holiday($db); - $result = $holidaystatic->updateBalance(); -} - /* * View diff --git a/htdocs/langs/en_US/holiday.lang b/htdocs/langs/en_US/holiday.lang index 2393a02ee50..0e6b1d69b36 100644 --- a/htdocs/langs/en_US/holiday.lang +++ b/htdocs/langs/en_US/holiday.lang @@ -132,3 +132,4 @@ FreeLegalTextOnHolidays=Free text on PDF WatermarkOnDraftHolidayCards=Watermarks on draft leave requests HolidaysToApprove=Holidays to approve NobodyHasPermissionToValidateHolidays=Nobody has permission to validate holidays +HolidayBalanceMonthlyUpdate=Monthly update of holiday balance diff --git a/test/phpunit/HolidayTest.php b/test/phpunit/HolidayTest.php index bba5d68c41e..415d45da674 100644 --- a/test/phpunit/HolidayTest.php +++ b/test/phpunit/HolidayTest.php @@ -366,6 +366,6 @@ class HolidayTest extends PHPUnit\Framework\TestCase $localobjecta->updateConfCP('lastUpdate', '20100101120000'); $result = $localobjecta->updateBalance(); - $this->assertEquals($result, 1); + $this->assertEquals($result, 0); } } From 82feb57fcfbfdd971a1a4c7581878fbc1c1349fc Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 10 Jun 2021 19:56:03 +0000 Subject: [PATCH 04/58] Fixing style errors. --- htdocs/core/modules/modHoliday.class.php | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/htdocs/core/modules/modHoliday.class.php b/htdocs/core/modules/modHoliday.class.php index 76700b59b31..71ab96e65bd 100644 --- a/htdocs/core/modules/modHoliday.class.php +++ b/htdocs/core/modules/modHoliday.class.php @@ -140,20 +140,20 @@ class modHoliday extends DolibarrModules $datestart = dol_mktime(4, 0, 0, $arraydate['mon'], $arraydate['mday'], $arraydate['year']); $this->cronjobs = array( 0 => array( - 'label' => 'HolidayBalanceMonthlyUpdate', - 'jobtype' => 'method', - 'class' => 'holiday/class/holiday.class.php', - 'objectname' => 'Holiday', - 'method' => 'updateBalance', - 'parameters' => '', - 'comment' => 'Update holiday balance every month', - 'frequency' => 1, - 'unitfrequency' => 3600 * 24, - 'priority' => 50, - 'status' => 1, - 'test' => '$conf->holiday->enabled', - 'datestart' => $datestart - ) + 'label' => 'HolidayBalanceMonthlyUpdate', + 'jobtype' => 'method', + 'class' => 'holiday/class/holiday.class.php', + 'objectname' => 'Holiday', + 'method' => 'updateBalance', + 'parameters' => '', + 'comment' => 'Update holiday balance every month', + 'frequency' => 1, + 'unitfrequency' => 3600 * 24, + 'priority' => 50, + 'status' => 1, + 'test' => '$conf->holiday->enabled', + 'datestart' => $datestart + ) ); From 9b71f1e16b5d699c6f0375f0fc192509b585325c Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 1 Jul 2021 11:55:06 +0200 Subject: [PATCH 05/58] fix : move check if invoice module is enabled into paymentok.php --- htdocs/commande/card.php | 2 +- htdocs/public/payment/paymentok.php | 119 +++++++++++++++------------- 2 files changed, 63 insertions(+), 58 deletions(-) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 4913731efb5..1ef37552f1f 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -2633,7 +2633,7 @@ if ($action == 'create' && $usercancreate) $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem, $compatibleImportElementsList); // Show online payment link - $useonlinepayment = ((!empty($conf->paypal->enabled) || !empty($conf->stripe->enabled) || !empty($conf->paybox->enabled)) && !empty($conf->facture->enabled)); + $useonlinepayment = (!empty($conf->paypal->enabled) || !empty($conf->stripe->enabled) || !empty($conf->paybox->enabled)); if (!empty($conf->global->ORDER_HIDE_ONLINE_PAYMENT_ON_ORDER)) $useonlinepayment = 0; if ($object->statut != Commande::STATUS_DRAFT && $useonlinepayment) { diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index 5f8f90ba72b..d6d4da28c9e 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -742,80 +742,85 @@ if ($ispaymentok) $currencyCodeType = $_SESSION['currencyCodeType']; // Do action only if $FinalPaymentAmt is set (session variable is cleaned after this page to avoid duplicate actions when page is POST a second time) - if (!empty($FinalPaymentAmt) && $paymentTypeId > 0) { - include_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; - $invoice = new Facture($db); - $result = $invoice->createFromOrder($object, $user); - if ($result > 0) { - $object->classifyBilled($user); - $invoice->validate($user); - // Creation of payment line - include_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php'; - $paiement = new Paiement($db); - $paiement->datepaye = $now; - if ($currencyCodeType == $conf->currency) { - $paiement->amounts = array($invoice->id => $FinalPaymentAmt); // Array with all payments dispatching with invoice id - } else { - $paiement->multicurrency_amounts = array($invoice->id => $FinalPaymentAmt); // Array with all payments dispatching - - $postactionmessages[] = 'Payment was done in a different currency that currency expected of company'; - $ispostactionok = -1; - $error++; // Not yet supported - } - $paiement->paiementid = $paymentTypeId; - $paiement->num_payment = ''; - $paiement->note_public = 'Online payment ' . dol_print_date($now, 'standard') . ' from ' . $ipaddress; - $paiement->ext_payment_id = $TRANSACTIONID; - $paiement->ext_payment_site = $service; - - if (!$error) { - $paiement_id = $paiement->create($user, 1); // This include closing invoices and regenerating documents - if ($paiement_id < 0) { - $postactionmessages[] = $paiement->error . ' ' . join("
\n", $paiement->errors); - $ispostactionok = -1; - $error++; + if (!empty($conf->banque->enabled)) { + if (!empty($FinalPaymentAmt) && $paymentTypeId > 0 ) { + include_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; + $invoice = new Facture($db); + $result = $invoice->createFromOrder($object, $user); + if ($result > 0) { + $object->classifyBilled($user); + $invoice->validate($user); + // Creation of payment line + include_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php'; + $paiement = new Paiement($db); + $paiement->datepaye = $now; + if ($currencyCodeType == $conf->currency) { + $paiement->amounts = array($invoice->id => $FinalPaymentAmt); // Array with all payments dispatching with invoice id } else { - $postactionmessages[] = 'Payment created'; - $ispostactionok = 1; + $paiement->multicurrency_amounts = array($invoice->id => $FinalPaymentAmt); // Array with all payments dispatching + + $postactionmessages[] = 'Payment was done in a different currency that currency expected of company'; + $ispostactionok = -1; + $error++; // Not yet supported } - } + $paiement->paiementid = $paymentTypeId; + $paiement->num_payment = ''; + $paiement->note_public = 'Online payment ' . dol_print_date($now, 'standard') . ' from ' . $ipaddress; + $paiement->ext_payment_id = $TRANSACTIONID; + $paiement->ext_payment_site = ''; - if (!$error && !empty($conf->banque->enabled)) { - $bankaccountid = 0; - if ($paymentmethod == 'paybox') $bankaccountid = $conf->global->PAYBOX_BANK_ACCOUNT_FOR_PAYMENTS; - elseif ($paymentmethod == 'paypal') $bankaccountid = $conf->global->PAYPAL_BANK_ACCOUNT_FOR_PAYMENTS; - elseif ($paymentmethod == 'stripe') $bankaccountid = $conf->global->STRIPE_BANK_ACCOUNT_FOR_PAYMENTS; - - if ($bankaccountid > 0) { - $label = '(CustomerInvoicePayment)'; - if ($object->type == Facture::TYPE_CREDIT_NOTE) $label = '(CustomerInvoicePaymentBack)'; // Refund of a credit note - $result = $paiement->addPaymentToBank($user, 'payment', $label, $bankaccountid, '', ''); - if ($result < 0) { + if (!$error) { + $paiement_id = $paiement->create($user, 1); // This include closing invoices and regenerating documents + if ($paiement_id < 0) { $postactionmessages[] = $paiement->error . ' ' . join("
\n", $paiement->errors); $ispostactionok = -1; $error++; } else { - $postactionmessages[] = 'Bank transaction of payment created'; + $postactionmessages[] = 'Payment created'; $ispostactionok = 1; } - } else { - $postactionmessages[] = 'Setup of bank account to use in module ' . $paymentmethod . ' was not set. No way to record the payment.'; - $ispostactionok = -1; - $error++; } - } - if (!$error) { - $db->commit(); + if (!$error && !empty($conf->banque->enabled)) { + $bankaccountid = 0; + if ($paymentmethod == 'paybox') $bankaccountid = $conf->global->PAYBOX_BANK_ACCOUNT_FOR_PAYMENTS; + elseif ($paymentmethod == 'paypal') $bankaccountid = $conf->global->PAYPAL_BANK_ACCOUNT_FOR_PAYMENTS; + elseif ($paymentmethod == 'stripe') $bankaccountid = $conf->global->STRIPE_BANK_ACCOUNT_FOR_PAYMENTS; + + if ($bankaccountid > 0) { + $label = '(CustomerInvoicePayment)'; + if ($object->type == Facture::TYPE_CREDIT_NOTE) $label = '(CustomerInvoicePaymentBack)'; // Refund of a credit note + $result = $paiement->addPaymentToBank($user, 'payment', $label, $bankaccountid, '', ''); + if ($result < 0) { + $postactionmessages[] = $paiement->error . ' ' . join("
\n", $paiement->errors); + $ispostactionok = -1; + $error++; + } else { + $postactionmessages[] = 'Bank transaction of payment created'; + $ispostactionok = 1; + } + } else { + $postactionmessages[] = 'Setup of bank account to use in module ' . $paymentmethod . ' was not set. No way to record the payment.'; + $ispostactionok = -1; + $error++; + } + } + + if (!$error) { + $db->commit(); + } else { + $db->rollback(); + } } else { - $db->rollback(); + $postactionmessages[] = 'Failed to create invoice form order ' . $tmptag['ORD'] . '.'; + $ispostactionok = -1; } } else { - $postactionmessages[] = 'Failed to create invoice form order ' . $tmptag['ORD'] . '.'; + $postactionmessages[] = 'Failed to get a valid value for "amount paid" (' . $FinalPaymentAmt . ') or "payment type" (' . $paymentType . ') to record the payment of order ' . $tmptag['ORD'] . '. May be payment was already recorded.'; $ispostactionok = -1; } } else { - $postactionmessages[] = 'Failed to get a valid value for "amount paid" (' . $FinalPaymentAmt . ') or "payment type" (' . $paymentType . ') to record the payment of order ' . $tmptag['ORD'] . '. May be payment was already recorded.'; + $postactionmessages[] = 'Invoice module is not enable'; $ispostactionok = -1; } } else { From 3e6eeeb977fca91c09e645cf8718ee05d50e6365 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 1 Jul 2021 11:59:00 +0200 Subject: [PATCH 06/58] fix : remove comments --- htdocs/public/payment/paymentok.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index d6d4da28c9e..18fef28d1c2 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -722,7 +722,6 @@ if ($ispaymentok) $ispostactionok = -1; } } elseif (array_key_exists('ORD', $tmptag) && $tmptag['ORD'] > 0) { - // Record payment include_once DOL_DOCUMENT_ROOT . '/commande/class/commande.class.php'; $object = new Commande($db); $result = $object->fetch($tmptag['ORD']); @@ -761,7 +760,7 @@ if ($ispaymentok) $postactionmessages[] = 'Payment was done in a different currency that currency expected of company'; $ispostactionok = -1; - $error++; // Not yet supported + $error++; } $paiement->paiementid = $paymentTypeId; $paiement->num_payment = ''; From b102dc619fad8f7c679c930fd5520f4bb06d7aaf Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Thu, 1 Jul 2021 10:15:55 +0000 Subject: [PATCH 07/58] Fixing style errors. --- htdocs/public/payment/paymentok.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index 71c338cb6fc..5bb3f4de0fc 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -916,17 +916,17 @@ if ($ispaymentok) { } } else { $postactionmessages[] = 'Order paid ' . $tmptag['ORD'] . ' was not found'; - $ispostactionok = -1; - } - } elseif (array_key_exists('DON', $tmptag) && $tmptag['DON'] > 0) { + $ispostactionok = -1; + } + } elseif (array_key_exists('DON', $tmptag) && $tmptag['DON'] > 0) { include_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php'; $don = new Don($db); $result = $don->fetch($tmptag['DON']); - if ($result) { + if ($result) { $FinalPaymentAmt = $_SESSION["FinalPaymentAmt"]; - - $paymentTypeId = 0; - if ($paymentmethod == 'paybox') { + + $paymentTypeId = 0; + if ($paymentmethod == 'paybox') { $paymentTypeId = $conf->global->PAYBOX_PAYMENT_MODE_FOR_PAYMENTS; } if ($paymentmethod == 'paypal') { @@ -940,9 +940,9 @@ if ($ispaymentok) { if (empty($paymentType)) { $paymentType = 'CB'; } - $paymentTypeId = dol_getIdFromCode($db, $paymentType, 'c_paiement', 'code', 'id', 1); + $paymentTypeId = dol_getIdFromCode($db, $paymentType, 'c_paiement', 'code', 'id', 1); } - + $currencyCodeType = $_SESSION['currencyCodeType']; // Do action only if $FinalPaymentAmt is set (session variable is cleaned after this page to avoid duplicate actions when page is POST a second time) From 110b0fecf5cc040e1de44f981619c77522deadc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20David?= Date: Thu, 1 Jul 2021 19:30:00 +0200 Subject: [PATCH 08/58] NEW #18046 Add ticket categories views --- htdocs/categories/viewcat.php | 90 +++++++++++++++++++++++++++++- htdocs/langs/fr_FR/categories.lang | 2 + htdocs/ticket/card.php | 18 +++++- 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index eeca990ef28..12263d8df2c 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -142,6 +142,11 @@ if ($id > 0 && $removeelem > 0) { $tmpobject = new User($db); $result = $tmpobject->fetch($removeelem); $elementtype = 'user'; + } elseif ($type == Categorie::TYPE_TICKET && $user->rights->ticket->write) { + require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php'; + $tmpobject = new Ticket($db); + $result = $tmpobject->fetch($removeelem); + $elementtype = 'ticket'; } $result = $object->del_type($tmpobject, $elementtype); @@ -167,7 +172,8 @@ if ($user->rights->categorie->supprimer && $action == 'confirm_delete' && $confi if ($elemid && $action == 'addintocategory' && (($type == Categorie::TYPE_PRODUCT && ($user->rights->produit->creer || $user->rights->service->creer)) || ($type == Categorie::TYPE_CUSTOMER && $user->rights->societe->creer) || - ($type == Categorie::TYPE_SUPPLIER && $user->rights->societe->creer) + ($type == Categorie::TYPE_SUPPLIER && $user->rights->societe->creer) || + ($type == Categorie::TYPE_TICKET && $user->rights->ticket->write) )) { if ($type == Categorie::TYPE_PRODUCT) { require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; @@ -181,6 +187,10 @@ if ($elemid && $action == 'addintocategory' && require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; $newobject = new Societe($db); $elementtype = 'supplier'; + } elseif ($type == Categorie::TYPE_TICKET) { + require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php'; + $newobject = new Ticket($db); + $elementtype = 'ticket'; } $result = $newobject->fetch($elemid); @@ -1024,6 +1034,84 @@ if ($type == Categorie::TYPE_WAREHOUSE) { } } +if ($type == Categorie::TYPE_TICKET) +{ + $permission = ($user->rights->categorie->creer || $user->rights->categorie->creer); + + $tickets = $object->getObjectsInCateg($type, 0, $limit, $offset); + if ($tickets < 0) + { + dol_print_error($db, $object->error, $object->errors); + } else { + // Form to add record into a category + $showclassifyform = 1; + if ($showclassifyform) + { + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print '
'; + print $langs->trans("AddTicketIntoCategory").'  '; + $form->select_tickets('', 'elemid'); + print '
'; + print ''; + } + + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + + print '
'; + $param = '&limit='.$limit.'&id='.$id.'&type='.$type; $num = count($tickets); $nbtotalofrecords = ''; $newcardbutton = ''; + print_barre_liste($langs->trans("Ticket"), $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'ticket', 0, $newcardbutton, '', $limit); + + + print ''."\n"; + print ''."\n"; + + if (count($tickets) > 0) + { + $i = 0; + foreach ($tickets as $ticket) + { + $i++; + if ($i > $limit) break; + + print "\t".''."\n"; + print '\n"; + print '\n"; + // Link to delete from category + print ''; + print "\n"; + } + } else { + print ''; + } + print "
'.$langs->trans("Ref").'
'; + print $ticket->getNomUrl(1); + print "'.$ticket->label."'; + if ($permission) + { + print ""; + print $langs->trans("DeleteFromCat"); + print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); + print ""; + } + print '
'.$langs->trans("ThisCategoryHasNoItems").'
\n"; + + print '
'."\n"; + } +} // End of page llxFooter(); diff --git a/htdocs/langs/fr_FR/categories.lang b/htdocs/langs/fr_FR/categories.lang index 4b806e1edbd..20bfb122c75 100644 --- a/htdocs/langs/fr_FR/categories.lang +++ b/htdocs/langs/fr_FR/categories.lang @@ -17,6 +17,7 @@ ContactsCategoriesArea=Espace tags/catégories de contacts AccountsCategoriesArea=Espace des tags/categories de comptes bancaires ProjectsCategoriesArea=Espace des tags/catégories des projets UsersCategoriesArea=Espace des tags/catégories des utilisateurs +TicketsCategoriesArea=Espace tags/catégories des tickets SubCats=Sous-catégories CatList=Liste des tags/catégories CatListAll=Liste de toutes les catégories (de tous types) @@ -90,6 +91,7 @@ CategorieRecursivHelp=Si l'option est activé, quand un produit est ajouté dans AddProductServiceIntoCategory=Ajouter le produit/service suivant AddCustomerIntoCategory=Assigner cette catégorie au client AddSupplierIntoCategory=Assigner cette catégorie au fournisseur +AddTicketIntoCategory=Assigner cette catégorie au ticket ShowCategory=Afficher tag/catégorie ByDefaultInList=Par défaut dans la liste ChooseCategory=Choisissez une catégorie diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 5faa7b201b7..9be858fd795 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -31,6 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; if (!empty($conf->projet->enabled)) { include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; include_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; @@ -202,6 +203,10 @@ if (empty($reshook)) { $contactid = GETPOST('contactid', 'int'); $type_contact = GETPOST("type", 'alpha'); + // Category association + $categories = GETPOST('categories', 'array'); + $object->setCategories($categories); + if ($contactid > 0 && $type_contact) { $typeid = (GETPOST('typecontact') ? GETPOST('typecontact') : GETPOST('type')); $result = $object->add_contact($contactid, $typeid, 'external'); @@ -312,7 +317,11 @@ if (empty($reshook)) { $object->severity_code = GETPOST('severity_code', 'alpha'); $ret = $object->update($user); - if ($ret <= 0) { + if ($ret > 0) { + // Category association + $categories = GETPOST('categories', 'array'); + $object->setCategories($categories); + } else { $error++; } @@ -1054,6 +1063,13 @@ if ($action == 'create' || $action == 'presend') { print ''; } + // Categories + if ($conf->categorie->enabled) { + print ''.$langs->trans("Categories").''; + print $form->showCategories($object->id, Categorie::TYPE_TICKET, 1); + print ""; + } + // Other attributes include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; From 079608fe00c1296787ba57fb7734c7fdee5f33af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20David?= Date: Fri, 2 Jul 2021 10:26:03 +0200 Subject: [PATCH 09/58] NEW #18046 Add ticket ticket categories functions --- htdocs/categories/class/categorie.class.php | 13 +- htdocs/core/class/html.form.class.php | 219 ++++++++++++++++++++ htdocs/core/class/html.formticket.class.php | 9 + htdocs/core/modules/modTicket.class.php | 13 ++ htdocs/ticket/class/ticket.class.php | 45 ++++ 5 files changed, 296 insertions(+), 3 deletions(-) diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index b98cff5b3a5..caeab5b8ddd 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -34,6 +34,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php'; require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php'; require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; @@ -56,6 +57,7 @@ class Categorie extends CommonObject const TYPE_WAREHOUSE = 'warehouse'; const TYPE_ACTIONCOMM = 'actioncomm'; const TYPE_WEBSITE_PAGE = 'website_page'; + const TYPE_TICKET = 'ticket'; /** * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png @@ -78,7 +80,8 @@ class Categorie extends CommonObject 'bank_line' => 8, 'warehouse' => 9, 'actioncomm' => 10, - 'website_page' => 11 + 'website_page' => 11, + 'ticket' => 12 ); /** @@ -98,7 +101,8 @@ class Categorie extends CommonObject 8 => 'bank_line', 9 => 'warehouse', 10 => 'actioncomm', - 11 => 'website_page' + 11 => 'website_page', + 12 => 'ticket' ); /** @@ -141,7 +145,8 @@ class Categorie extends CommonObject 'project' => 'Project', 'warehouse'=> 'Entrepot', 'actioncomm' => 'ActionComm', - 'website_page' => 'WebsitePage' + 'website_page' => 'WebsitePage', + 'ticket' => 'Ticket' ); /** @@ -234,6 +239,8 @@ class Categorie extends CommonObject * @see Categorie::TYPE_WAREHOUSE * @see Categorie::TYPE_ACTIONCOMM * @see Categorie::TYPE_WEBSITE_PAGE + * @see Categorie::TYPE_TICKET + */ public $type; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 0b1504d229a..2d648ef1fd9 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6578,6 +6578,225 @@ class Form return; } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return list of tickets in Ajax if Ajax activated or go to select_tickets_list + * + * @param int $selected Preselected tickets + * @param string $htmlname Name of HTML select field (must be unique in page). + * @param int $limit Limit on number of returned lines + * @param int $status Ticket status + * @param string $selected_input_value Value of preselected input text (for use with ajax) + * @param int $hidelabel Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after) + * @param array $ajaxoptions Options for ajax_autocompleter + * @param int $socid Thirdparty Id (to get also price dedicated to this customer) + * @param string $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text. + * @param int $forcecombo Force to use combo box + * @param string $morecss Add more css on select + * @param array $selected_combinations Selected combinations. Format: array([attrid] => attrval, [...]) + * @param string $nooutput No print, return the output into a string + * @return void|string + */ + public function select_tickets($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 0, $status = 1, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $selected_combinations = null, $nooutput = 0) + { + // phpcs:enable + global $langs, $conf; + + $out = ''; + + // check parameters + if (is_null($ajaxoptions)) $ajaxoptions = array(); + + if (!empty($conf->use_javascript_ajax) && !empty($conf->global->TICKET_USE_SEARCH_TO_SELECT)) + { + $placeholder = ''; + + if ($selected && empty($selected_input_value)) + { + require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php'; + $tickettmpselect = new Ticket($this->db); + $tickettmpselect->fetch($selected); + $selected_input_value = $tickettmpselect->ref; + unset($tickettmpselect); + } + + $out .= ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/ticket/ajax/tickets.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 1, $ajaxoptions); + + if (empty($hidelabel)) $out .= $langs->trans("RefOrLabel").' : '; + elseif ($hidelabel > 1) { + $placeholder = ' placeholder="'.$langs->trans("RefOrLabel").'"'; + if ($hidelabel == 2) { + $out .= img_picto($langs->trans("Search"), 'search'); + } + } + $out .= 'global->PRODUCT_SEARCH_AUTOFOCUS) ? 'autofocus' : '').' />'; + if ($hidelabel == 3) { + $out .= img_picto($langs->trans("Search"), 'search'); + } + } else { + $out .= $this->select_tickets_list($selected, $htmlname, $filtertype, $limit, $status, 0, $socid, $showempty, $forcecombo, $morecss); + } + + if (empty($nooutput)) print $out; + else return $out; + } + + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return list of tickets. + * Called by select_tickets. + * + * @param int $selected Preselected ticket + * @param string $htmlname Name of select html + * @param string $filtertype Filter on ticket type + * @param int $limit Limit on number of returned lines + * @param string $filterkey Filter on product + * @param int $status Ticket status + * @param int $outputmode 0=HTML select string, 1=Array + * @param string $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text. + * @param int $forcecombo Force to use combo box + * @param string $morecss Add more css on select + * @return array Array of keys for json + */ + public function select_tickets_list($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '') + { + // phpcs:enable + global $langs, $conf, $user, $db; + + $out = ''; + $outarray = array(); + + $selectFields = " p.rowid, p.ref, p.message"; + + $sql = "SELECT "; + $sql .= $selectFields; + $sql .= " FROM ".MAIN_DB_PREFIX."ticket as p"; + $sql .= ' WHERE p.entity IN ('.getEntity('ticket').')'; + + // Add criteria on ref/label + if ($filterkey != '') + { + $sql .= ' AND ('; + $prefix = empty($conf->global->TICKET_DONOTSEARCH_ANYWHERE) ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on + // For natural search + $scrit = explode(' ', $filterkey); + $i = 0; + if (count($scrit) > 1) $sql .= "("; + foreach ($scrit as $crit) + { + if ($i > 0) $sql .= " AND "; + $sql .= "(p.ref LIKE '".$this->db->escape($prefix.$crit)."%' OR p.label LIKE '".$this->db->escape($prefix.$crit)."%'"; + $sql .= ")"; + $i++; + } + if (count($scrit) > 1) $sql .= ")"; + $sql .= ')'; + } + + $sql .= $this->db->plimit($limit, 0); + + // Build output string + dol_syslog(get_class($this)."::select_tickets_list search tickets", LOG_DEBUG); + $result = $this->db->query($sql); + if ($result) + { + require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php'; + require_once DOL_DOCUMENT_ROOT.'/core/lib/ticket.lib.php'; + + $num = $this->db->num_rows($result); + + $events = null; + + if (!$forcecombo) + { + include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; + $out .= ajax_combobox($htmlname, $events, $conf->global->TICKET_USE_SEARCH_TO_SELECT); + } + + $out .= ''; + + $this->db->free($result); + + if (empty($outputmode)) return $out; + return $outarray; + } else { + dol_print_error($db); + } + } + + /** + * constructTicketListOption. + * This define value for &$opt and &$optJson. + * + * @param resource $objp Result set of fetch + * @param string $opt Option (var used for returned value in string option format) + * @param string $optJson Option (var used for returned value in json format) + * @param string $selected Preselected value + * @param string $filterkey Filter key to highlight + * @return void + */ + protected function constructTicketListOption(&$objp, &$opt, &$optJson, $selected, $filterkey = '') + { + global $langs, $conf, $user, $db; + + $outkey = ''; + $outval = ''; + $outref = ''; + $outlabel = ''; + $outtype = ''; + + $label = $objp->label; + + $outkey = $objp->rowid; + $outref = $objp->ref; + $outlabel = $objp->label; + $outtype = $objp->fk_product_type; + + $opt = '\n"; + $optJson = array('key'=>$outkey, 'value'=>$outref, 'type'=>$outtypem); + } + /** * Generic method to select a component from a combo list. diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index daafa88333f..2178a02cb89 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -272,6 +272,15 @@ class FormTicket print ''; } + //Categories + if ($conf->categorie->enabled) { + // Categories + print ''.$langs->trans("Categories").''; + $cate_arbo = $form->select_all_categories(Categorie::TYPE_TICKET, '', 'parent', 64, 0, 1); + print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); + print ""; + } + // Attached files if (!empty($this->withfile)) { // Define list of attached files diff --git a/htdocs/core/modules/modTicket.class.php b/htdocs/core/modules/modTicket.class.php index 8b1a1dc8525..2a717ae4f42 100644 --- a/htdocs/core/modules/modTicket.class.php +++ b/htdocs/core/modules/modTicket.class.php @@ -283,6 +283,19 @@ class modTicket extends DolibarrModules 'target' => '', 'user' => 0); $r++; + + $this->menu[$r] = array('fk_menu' => 'fk_mainmenu=ticket,fk_leftmenu=ticket', + 'type' => 'left', + 'titre' => 'Categories', + 'mainmenu' => 'ticket', + 'url' => '/categories/index.php?type=12', + 'langs' => 'ticket', + 'position' => 107, + 'enabled' => '$conf->categorie->enabled', + 'perms' => '$user->rights->ticket->read', + 'target' => '', + 'user' => 0); + $r++; } /** diff --git a/htdocs/ticket/class/ticket.class.php b/htdocs/ticket/class/ticket.class.php index 89f239db6c6..36d90c5519d 100644 --- a/htdocs/ticket/class/ticket.class.php +++ b/htdocs/ticket/class/ticket.class.php @@ -2497,6 +2497,51 @@ class Ticket extends CommonObject return array('listofpaths'=>$listofpaths, 'listofnames'=>$listofnames, 'listofmimes'=>$mimetype); } + /** + * Sets object to supplied categories. + * + * Deletes object from existing categories not supplied. + * Adds it to non existing supplied categories. + * Existing categories are left untouch. + * + * @param int[]|int $categories Category or categories IDs + * @return void + */ + public function setCategories($categories) + { + // Handle single category + if (!is_array($categories)) { + $categories = array($categories); + } + + // Get current categories + include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + $c = new Categorie($this->db); + $existing = $c->containing($this->id, Categorie::TYPE_TICKET, 'id'); + + // Diff + if (is_array($existing)) { + $to_del = array_diff($existing, $categories); + $to_add = array_diff($categories, $existing); + } else { + $to_del = array(); // Nothing to delete + $to_add = $categories; + } + + // Process + foreach ($to_del as $del) { + if ($c->fetch($del) > 0) { + $c->del_type($this, Categorie::TYPE_TICKET); + } + } + foreach ($to_add as $add) { + if ($c->fetch($add) > 0) { + $c->add_type($this, Categorie::TYPE_TICKET); + } + } + + return; + } /** * Add new message on a ticket (private/public area). Can also send it be email if GETPOST('send_email', 'int') is set. From ce9bd51cb203a249763b3078bdd0f4d80bbff236 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 12 Jul 2021 07:17:08 +0000 Subject: [PATCH 10/58] Fixing style errors. --- htdocs/categories/viewcat.php | 18 ++++++------------ htdocs/ticket/card.php | 2 +- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index 12263d8df2c..fb7e34fb9a0 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -1034,19 +1034,16 @@ if ($type == Categorie::TYPE_WAREHOUSE) { } } -if ($type == Categorie::TYPE_TICKET) -{ +if ($type == Categorie::TYPE_TICKET) { $permission = ($user->rights->categorie->creer || $user->rights->categorie->creer); $tickets = $object->getObjectsInCateg($type, 0, $limit, $offset); - if ($tickets < 0) - { + if ($tickets < 0) { dol_print_error($db, $object->error, $object->errors); } else { // Form to add record into a category $showclassifyform = 1; - if ($showclassifyform) - { + if ($showclassifyform) { print '
'; print '
'; print ''; @@ -1079,11 +1076,9 @@ if ($type == Categorie::TYPE_TICKET) print ''."\n"; print ''."\n"; - if (count($tickets) > 0) - { + if (count($tickets) > 0) { $i = 0; - foreach ($tickets as $ticket) - { + foreach ($tickets as $ticket) { $i++; if ($i > $limit) break; @@ -1094,8 +1089,7 @@ if ($type == Categorie::TYPE_TICKET) print '\n"; // Link to delete from category print '"; } - + // Other attributes include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; From 642d84a844db1666e6d8102f897aae43ef2100cd Mon Sep 17 00:00:00 2001 From: David Date: Mon, 12 Jul 2021 09:26:18 +0200 Subject: [PATCH 11/58] fix: code syntax --- htdocs/core/class/html.form.class.php | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index a569785863c..5ef8d804a6b 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6588,6 +6588,7 @@ class Form * * @param int $selected Preselected tickets * @param string $htmlname Name of HTML select field (must be unique in page). + * @param string $filtertype To add a filter * @param int $limit Limit on number of returned lines * @param int $status Ticket status * @param string $selected_input_value Value of preselected input text (for use with ajax) @@ -6611,12 +6612,10 @@ class Form // check parameters if (is_null($ajaxoptions)) $ajaxoptions = array(); - if (!empty($conf->use_javascript_ajax) && !empty($conf->global->TICKET_USE_SEARCH_TO_SELECT)) - { + if (!empty($conf->use_javascript_ajax) && !empty($conf->global->TICKET_USE_SEARCH_TO_SELECT)) { $placeholder = ''; - if ($selected && empty($selected_input_value)) - { + if ($selected && empty($selected_input_value)) { require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php'; $tickettmpselect = new Ticket($this->db); $tickettmpselect->fetch($selected); @@ -6679,16 +6678,14 @@ class Form $sql .= ' WHERE p.entity IN ('.getEntity('ticket').')'; // Add criteria on ref/label - if ($filterkey != '') - { + if ($filterkey != '') { $sql .= ' AND ('; $prefix = empty($conf->global->TICKET_DONOTSEARCH_ANYWHERE) ? '%' : ''; // Can use index if PRODUCT_DONOTSEARCH_ANYWHERE is on // For natural search $scrit = explode(' ', $filterkey); $i = 0; if (count($scrit) > 1) $sql .= "("; - foreach ($scrit as $crit) - { + foreach ($scrit as $crit) { if ($i > 0) $sql .= " AND "; $sql .= "(p.ref LIKE '".$this->db->escape($prefix.$crit)."%' OR p.label LIKE '".$this->db->escape($prefix.$crit)."%'"; $sql .= ")"; @@ -6703,8 +6700,7 @@ class Form // Build output string dol_syslog(get_class($this)."::select_tickets_list search tickets", LOG_DEBUG); $result = $this->db->query($sql); - if ($result) - { + if ($result) { require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/ticket.lib.php'; @@ -6712,8 +6708,7 @@ class Form $events = null; - if (!$forcecombo) - { + if (!$forcecombo) { include_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; $out .= ajax_combobox($htmlname, $events, $conf->global->TICKET_USE_SEARCH_TO_SELECT); } @@ -6723,8 +6718,7 @@ class Form $textifempty = ''; // Do not use textifempty = ' ' or ' ' here, or search on key will search on ' key'. //if (! empty($conf->use_javascript_ajax) || $forcecombo) $textifempty=''; - if (!empty($conf->global->TICKET_USE_SEARCH_TO_SELECT)) - { + if (!empty($conf->global->TICKET_USE_SEARCH_TO_SELECT)) { if ($showempty && !is_numeric($showempty)) $textifempty = $langs->trans($showempty); else $textifempty .= $langs->trans("All"); } else { @@ -6733,8 +6727,7 @@ class Form if ($showempty) $out .= ''; $i = 0; - while ($num && $i < $num) - { + while ($num && $i < $num) { $opt = ''; $optJson = array(); $objp = $this->db->fetch_object($result); From a2de6c00a00940a0edc76c32f4400f689141f54f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 12 Jul 2021 12:26:21 +0200 Subject: [PATCH 12/58] Prepare 13.0.4 --- ChangeLog | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ChangeLog b/ChangeLog index d3cc6da9b9c..281c8733ce6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,27 @@ English Dolibarr ChangeLog -------------------------------------------------------------- +***** ChangeLog for 13.0.4 compared to 13.0.2 ***** + +FIX: Allow disabling of a module (not a dangerous action) even if there is problem with token (due to bugged modules). +FIX: 13.0 - fatal - missing inclusion of ajax.lib.php for calling `ajax_autocompleter()` +FIX: #17919 pictures in docs. +FIX: #18006 +FIX: Accountancy - if we define a date start, automatic binding try to continue to solve old binding +FIX: Accoutancy Limit date payment not registered on purchases operations +FIX: Can't edit replacement invoice +FIX: deposit can create credit note in payment conf +FIX: division by zero on create +FIX: holiday: balances not updated correctly with pgsql because of case sensitivity field +FIX: holiday: status filter parameter has been renamed but not in links it was used +FIX: List and Create Companies Left Menus +FIX: method exists +FIX: need to add payment sum to getlibstatus function in object linked block +FIX: permission to close a proposal when using advanced permissions +FIX: Problem of z-index with popup and top menu +FIX: same thing on supplier orders +FIX: Status of invoice when making a replacement invoice +FIX: update contact birthday alert ***** ChangeLog for 13.0.3 compared to 13.0.2 ***** From deb9a374f3589325d817f7dce4a125824bd1356a Mon Sep 17 00:00:00 2001 From: John BOTELLA Date: Mon, 12 Jul 2021 12:28:21 +0200 Subject: [PATCH 13/58] Fix ui event badge status --- htdocs/core/lib/company.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index 21b6f9a68e4..cb710c19875 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -1899,7 +1899,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon = '', $noprin } // Status - $out .= ''; + $out .= ''; // Actions $out .= ''; From 91d27a556c7cf489a154eb113f8d38d888eb3cf3 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Mon, 12 Jul 2021 14:09:16 +0200 Subject: [PATCH 14/58] fix badge status bgcolor --- htdocs/theme/eldy/badges.inc.php | 8 ++++---- htdocs/theme/md/badges.inc.php | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/htdocs/theme/eldy/badges.inc.php b/htdocs/theme/eldy/badges.inc.php index dcb61499b63..58317deba15 100644 --- a/htdocs/theme/eldy/badges.inc.php +++ b/htdocs/theme/eldy/badges.inc.php @@ -258,9 +258,9 @@ function _createStatusBadgeCss($statusName, $statusVarNamePrefix = '', $commentL print $cssPrefix.".badge-status".$statusName." {\n"; print " color: ".$thisBadgeTextColor." !important;\n"; if (in_array((string) $statusName, $TBadgeBorderOnly)) { - print " border-color: ".$thisBadgeBorderColor.";\n"; + print " border-color: ".$thisBadgeBorderColor." !important;\n"; } - print " background-color: ".$thisBadgeBackgroundColor.";\n"; + print " background-color: ".$thisBadgeBackgroundColor." !important;\n"; print "}\n"; print $cssPrefix.".font-status".$statusName." {\n"; @@ -269,14 +269,14 @@ function _createStatusBadgeCss($statusName, $statusVarNamePrefix = '', $commentL print $cssPrefix.".badge-status".$statusName.".focus, ".$cssPrefix.".badge-status".$statusName.":focus {\n"; print " outline: 0;\n"; - print " box-shadow: 0 0 0 0.2rem ".colorHexToRgb($thisBadgeBackgroundColor, 0.5).";\n"; + print " box-shadow: 0 0 0 0.2rem ".colorHexToRgb($thisBadgeBackgroundColor, 0.5)." !important;\n"; print "}\n"; print $cssPrefix.".badge-status".$statusName.":focus, ".$cssPrefix.".badge-status".$statusName.":hover {\n"; print " color: ".$thisBadgeTextColor." !important;\n"; //print " background-color: " . colorDarker($thisBadgeBackgroundColor, 10) . ";\n"; if (in_array((string) $statusName, $TBadgeBorderOnly)) { - print " border-color: ".colorDarker($thisBadgeBorderColor, 10).";\n"; + print " border-color: ".colorDarker($thisBadgeBorderColor, 10)." !important;\n"; } print "}\n"; } diff --git a/htdocs/theme/md/badges.inc.php b/htdocs/theme/md/badges.inc.php index fd1b1122a17..4a36177e852 100644 --- a/htdocs/theme/md/badges.inc.php +++ b/htdocs/theme/md/badges.inc.php @@ -261,9 +261,9 @@ function _createStatusBadgeCss($statusName, $statusVarNamePrefix = '', $commentL print $cssPrefix.".badge-status".$statusName." {\n"; print " color: ".$thisBadgeTextColor." !important;\n"; if (in_array((string) $statusName, $TBadgeBorderOnly)) { - print " border-color: ".$thisBadgeBorderColor.";\n"; + print " border-color: ".$thisBadgeBorderColor." !important;\n"; } - print " background-color: ".$thisBadgeBackgroundColor.";\n"; + print " background-color: ".$thisBadgeBackgroundColor." !important;\n"; print "}\n"; print $cssPrefix.".font-status".$statusName." {\n"; @@ -272,14 +272,14 @@ function _createStatusBadgeCss($statusName, $statusVarNamePrefix = '', $commentL print $cssPrefix.".badge-status".$statusName.".focus, ".$cssPrefix.".badge-status".$statusName.":focus {\n"; print " outline: 0;\n"; - print " box-shadow: 0 0 0 0.2rem ".colorHexToRgb($thisBadgeBackgroundColor, 0.5).";\n"; + print " box-shadow: 0 0 0 0.2rem ".colorHexToRgb($thisBadgeBackgroundColor, 0.5)." !important;\n"; print "}\n"; print $cssPrefix.".badge-status".$statusName.":focus, ".$cssPrefix.".badge-status".$statusName.":hover {\n"; print " color: ".$thisBadgeTextColor." !important;\n"; //print " background-color: ".colorDarker($thisBadgeBackgroundColor, 10).";\n"; if (in_array((string) $statusName, $TBadgeBorderOnly)) { - print " border-color: ".colorDarker($thisBadgeBorderColor, 10).";\n"; + print " border-color: ".colorDarker($thisBadgeBorderColor, 10)." !important;\n"; } print "}\n"; } From d8db447112ef4b4fa688d551f6e0308435c62f63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20David?= Date: Mon, 12 Jul 2021 14:12:20 +0200 Subject: [PATCH 15/58] fix: rename select_tickets into selectTickets --- htdocs/categories/viewcat.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index fb7e34fb9a0..8ebb9f43b1e 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -1054,7 +1054,7 @@ if ($type == Categorie::TYPE_TICKET) { print '
'.$langs->trans("Ref").'
'.$ticket->label."'; - if ($permission) - { + if ($permission) { print ""; print $langs->trans("DeleteFromCat"); print img_picto($langs->trans("DeleteFromCat"), 'unlink', '', false, 0, 0, '', 'paddingleft'); diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 9be858fd795..be53c46b051 100644 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -1069,7 +1069,7 @@ if ($action == 'create' || $action == 'presend') { print $form->showCategories($object->id, Categorie::TYPE_TICKET, 1); print "
'.$actionstatic->LibStatut($histo[$key]['percent'], 3, 0, $histo[$key]['datestart']).''.$actionstatic->LibStatut($histo[$key]['percent'], 2, 0, $histo[$key]['datestart']).'
'; print ''; print ''; print '
'; print $langs->trans("AddTicketIntoCategory").'  '; - $form->select_tickets('', 'elemid'); + $form->selectTickets('', 'elemid'); print '
'; From b59c1f1a3487fb334c824802b69c5a6d5736752f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20David?= Date: Mon, 12 Jul 2021 14:17:30 +0200 Subject: [PATCH 16/58] fix: rename select_tickets into selectTickets --- htdocs/core/class/html.form.class.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 5ef8d804a6b..23a6b724d14 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6582,7 +6582,6 @@ class Form return; } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of tickets in Ajax if Ajax activated or go to select_tickets_list * @@ -6602,7 +6601,7 @@ class Form * @param string $nooutput No print, return the output into a string * @return void|string */ - public function select_tickets($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 0, $status = 1, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $selected_combinations = null, $nooutput = 0) + public function selectTickets($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 0, $status = 1, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $selected_combinations = null, $nooutput = 0) { // phpcs:enable global $langs, $conf; @@ -6648,7 +6647,7 @@ class Form // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of tickets. - * Called by select_tickets. + * Called by selectTickets. * * @param int $selected Preselected ticket * @param string $htmlname Name of select html From 12e327d6b4055711ef667999059d0aa27f02809e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20David?= Date: Mon, 12 Jul 2021 14:37:07 +0200 Subject: [PATCH 17/58] fix: remove phpcs:enable tag --- htdocs/core/class/html.form.class.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 23a6b724d14..cbb1f09f3d8 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6663,7 +6663,6 @@ class Form */ public function select_tickets_list($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '') { - // phpcs:enable global $langs, $conf, $user, $db; $out = ''; @@ -6738,7 +6737,6 @@ class Form $out .= $opt; array_push($outarray, $optJson); - $i++; } From cfb03f065c0307dc061552f610c45d14c51641f8 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Mon, 12 Jul 2021 16:12:28 +0200 Subject: [PATCH 18/58] Fix #18110 : update of formticket.class.php --- htdocs/core/class/html.formticket.class.php | 58 +++++++++++++++++---- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index 0a4a622f4a8..4724c57e885 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -656,11 +656,11 @@ class FormTicket print ajax_combobox('select'.$htmlname); } elseif ($htmlname!='') { $groupticket=GETPOST($htmlname, 'aZ09'); - $groupticketchild=GETPOST($htmlname.'_child', 'aZ09'); + $child_id=GETPOST($htmlname.'_child_id', 'aZ09')?GETPOST($htmlname.'_child_id', 'aZ09'):0; $arraycodenotparent[] = ""; $arrayidused = array(); $stringtoprint = ''.$langs->trans("GroupOfTicket").' '; - $stringtoprint .= ''; $stringtoprint .= ''; $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, "; @@ -697,13 +697,17 @@ class FormTicket } if ($num_rows_level0 == 1) { return ''; + }else{ + $stringtoprint .= ''; + $stringtoprint .= ''; } + $stringtoprint .= ''; $stringtoprint .= ' '; $levelid = 1; while ($levelid <= $use_multilevel) { $tabscript = array(); - $stringtoprint .= ''; $stringtoprint .= ''; $sql = "SELECT ctc.rowid, ctc.code, ctc.label, ctc.fk_parent, ctcjoin.code as codefather, "; @@ -742,7 +746,7 @@ class FormTicket if ($isparent == 'NOTPARENT') { $arraycodenotparent[] = $groupvalue; } - $iselected = $groupticketchild == $obj->code ?'selected':''; + $iselected = $groupticket == $obj->code ?'selected':''; $stringtoprint .= ''; if (empty($tabscript[$groupcodefather])) { $tabscript[$groupcodefather] = 'if ($("#'.$htmlname.($levelid > 1 ?'_child_'.$levelid-1:'').'")[0].value == "'.dol_escape_js($groupcodefather).'"){ @@ -760,15 +764,43 @@ class FormTicket dol_print_error($this->db); } $stringtoprint .=''; - //$stringtoprint .= ajax_combobox($htmlname.'_child_'.$levelid); $stringtoprint .=''; } - + $stringtoprint .=''; $stringtoprint .= ajax_combobox($htmlname); return $stringtoprint; From 5b1525e77c1941dc6e282ecc26bb6ab3ea576d51 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Mon, 12 Jul 2021 14:15:28 +0000 Subject: [PATCH 19/58] Fixing style errors. --- htdocs/core/class/html.formticket.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index 4724c57e885..48c861fdd95 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -697,7 +697,7 @@ class FormTicket } if ($num_rows_level0 == 1) { return ''; - }else{ + } else { $stringtoprint .= ''; $stringtoprint .= ''; } From d3f324c2d4267ab27c7cc127d238f8b563891889 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 12 Jul 2021 16:55:16 +0200 Subject: [PATCH 20/58] Try a better fix for #18105 --- htdocs/core/class/hookmanager.class.php | 23 ++++++++++++++++++----- htdocs/core/lib/functions.lib.php | 7 ++++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index d610203b3ad..8384886e50c 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -254,16 +254,29 @@ class HookManager // Hooks that must return int (hooks with type 'addreplace') if ($hooktype == 'addreplace') { - $resaction += $actionclassinstance->$method($parameters, $object, $action, $this); // $object and $action can be changed by method ($object->id during creation for example or $action to go back to other action for example) - if ($resaction < 0 || !empty($actionclassinstance->error) || (!empty($actionclassinstance->errors) && count($actionclassinstance->errors) > 0)) - { + $resactiontmp = $actionclassinstance->$method($parameters, $object, $action, $this); // $object and $action can be changed by method ($object->id during creation for example or $action to go back to other action for example) + $resaction += $resactiontmp; + + if ($resactiontmp < 0 || !empty($actionclassinstance->error) || (!empty($actionclassinstance->errors) && count($actionclassinstance->errors) > 0)) { $error++; $this->error = $actionclassinstance->error; $this->errors = array_merge($this->errors, (array) $actionclassinstance->errors); dol_syslog("Error on hook module=".$module.", method ".$method.", class ".get_class($actionclassinstance).", hooktype=".$hooktype.(empty($this->error) ? '' : " ".$this->error).(empty($this->errors) ? '' : " ".join(",", $this->errors)), LOG_ERR); } - if (isset($actionclassinstance->results) && is_array($actionclassinstance->results)) $this->resArray = array_merge($this->resArray, $actionclassinstance->results); - if (!empty($actionclassinstance->resprints)) $this->resPrint .= $actionclassinstance->resprints; + if (isset($actionclassinstance->results) && is_array($actionclassinstance->results)) { + if ($resactiontmp > 0) { + $this->resArray = $actionclassinstance->results; + } else { + $this->resArray = array_merge($this->resArray, $actionclassinstance->results); + } + } + if (!empty($actionclassinstance->resprints)) { + if ($resactiontmp > 0) { + $this->resPrint = $actionclassinstance->resprints; + } else { + $this->resPrint .= $actionclassinstance->resprints; + } + } } // Generic hooks that return a string or array (printLeftBlock, formAddObjectLine, formBuilddocOptions, ...) else { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 884b5ece6f7..54ef73f19d6 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -7754,11 +7754,12 @@ function complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, { $parameters = array('object' => $object, 'mode' => $mode, 'head' => $head); $reshook = $hookmanager->executeHooks('completeTabsHead', $parameters); - if ($reshook > 0) - { + if ($reshook > 0) { // Hook ask to replace completely the array $head = $hookmanager->resArray; - $h = count($head); + } else { // Hook + $head = array_merge($head, $hookmanager->resArray); } + $h = count($head); } } From a15d895b4ba16fe8c86b52f54b0eecf8d8dedd64 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Mon, 12 Jul 2021 14:09:16 +0200 Subject: [PATCH 21/58] fix badge status bgcolor --- htdocs/theme/eldy/badges.inc.php | 8 ++++---- htdocs/theme/md/badges.inc.php | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/htdocs/theme/eldy/badges.inc.php b/htdocs/theme/eldy/badges.inc.php index dcb61499b63..58317deba15 100644 --- a/htdocs/theme/eldy/badges.inc.php +++ b/htdocs/theme/eldy/badges.inc.php @@ -258,9 +258,9 @@ function _createStatusBadgeCss($statusName, $statusVarNamePrefix = '', $commentL print $cssPrefix.".badge-status".$statusName." {\n"; print " color: ".$thisBadgeTextColor." !important;\n"; if (in_array((string) $statusName, $TBadgeBorderOnly)) { - print " border-color: ".$thisBadgeBorderColor.";\n"; + print " border-color: ".$thisBadgeBorderColor." !important;\n"; } - print " background-color: ".$thisBadgeBackgroundColor.";\n"; + print " background-color: ".$thisBadgeBackgroundColor." !important;\n"; print "}\n"; print $cssPrefix.".font-status".$statusName." {\n"; @@ -269,14 +269,14 @@ function _createStatusBadgeCss($statusName, $statusVarNamePrefix = '', $commentL print $cssPrefix.".badge-status".$statusName.".focus, ".$cssPrefix.".badge-status".$statusName.":focus {\n"; print " outline: 0;\n"; - print " box-shadow: 0 0 0 0.2rem ".colorHexToRgb($thisBadgeBackgroundColor, 0.5).";\n"; + print " box-shadow: 0 0 0 0.2rem ".colorHexToRgb($thisBadgeBackgroundColor, 0.5)." !important;\n"; print "}\n"; print $cssPrefix.".badge-status".$statusName.":focus, ".$cssPrefix.".badge-status".$statusName.":hover {\n"; print " color: ".$thisBadgeTextColor." !important;\n"; //print " background-color: " . colorDarker($thisBadgeBackgroundColor, 10) . ";\n"; if (in_array((string) $statusName, $TBadgeBorderOnly)) { - print " border-color: ".colorDarker($thisBadgeBorderColor, 10).";\n"; + print " border-color: ".colorDarker($thisBadgeBorderColor, 10)." !important;\n"; } print "}\n"; } diff --git a/htdocs/theme/md/badges.inc.php b/htdocs/theme/md/badges.inc.php index fd1b1122a17..4a36177e852 100644 --- a/htdocs/theme/md/badges.inc.php +++ b/htdocs/theme/md/badges.inc.php @@ -261,9 +261,9 @@ function _createStatusBadgeCss($statusName, $statusVarNamePrefix = '', $commentL print $cssPrefix.".badge-status".$statusName." {\n"; print " color: ".$thisBadgeTextColor." !important;\n"; if (in_array((string) $statusName, $TBadgeBorderOnly)) { - print " border-color: ".$thisBadgeBorderColor.";\n"; + print " border-color: ".$thisBadgeBorderColor." !important;\n"; } - print " background-color: ".$thisBadgeBackgroundColor.";\n"; + print " background-color: ".$thisBadgeBackgroundColor." !important;\n"; print "}\n"; print $cssPrefix.".font-status".$statusName." {\n"; @@ -272,14 +272,14 @@ function _createStatusBadgeCss($statusName, $statusVarNamePrefix = '', $commentL print $cssPrefix.".badge-status".$statusName.".focus, ".$cssPrefix.".badge-status".$statusName.":focus {\n"; print " outline: 0;\n"; - print " box-shadow: 0 0 0 0.2rem ".colorHexToRgb($thisBadgeBackgroundColor, 0.5).";\n"; + print " box-shadow: 0 0 0 0.2rem ".colorHexToRgb($thisBadgeBackgroundColor, 0.5)." !important;\n"; print "}\n"; print $cssPrefix.".badge-status".$statusName.":focus, ".$cssPrefix.".badge-status".$statusName.":hover {\n"; print " color: ".$thisBadgeTextColor." !important;\n"; //print " background-color: ".colorDarker($thisBadgeBackgroundColor, 10).";\n"; if (in_array((string) $statusName, $TBadgeBorderOnly)) { - print " border-color: ".colorDarker($thisBadgeBorderColor, 10).";\n"; + print " border-color: ".colorDarker($thisBadgeBorderColor, 10)." !important;\n"; } print "}\n"; } From 202ee8340a4dafd6a17a066781bffdff729f0d7b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 12 Jul 2021 23:01:34 +0200 Subject: [PATCH 22/58] FIX #18091 --- htdocs/langs/en_US/errors.lang | 1 + htdocs/product/card.php | 2 +- .../product/class/html.formproduct.class.php | 4 +- htdocs/projet/class/task.class.php | 24 +++++- htdocs/projet/tasks/time.php | 75 ++++++++++++++----- 5 files changed, 81 insertions(+), 25 deletions(-) diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 3ed7441afa5..cb97af5c183 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -264,6 +264,7 @@ ErrorAnAmountWithoutTaxIsRequired=Error, amount is mandatory ErrorAPercentIsRequired=Error, please fill in the percentage correctly ErrorYouMustFirstSetupYourChartOfAccount=You must first setup your chart of account ErrorFailedToFindEmailTemplate=Failed to find template with code name %s +ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice=Duration not defined on service. No way to calculate the hourly price. # Warnings WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 01a2d9acfdd..2472c764d7e 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -1234,7 +1234,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { if ($type == 1) { print ''.$langs->trans("Duration").''; print ''; - print $formproduct->selectMeasuringUnits("duration_unit", "time", GETPOST('duration_value', 'alpha'), 0, 1); + print $formproduct->selectMeasuringUnits("duration_unit", "time", (GETPOSTISSET('duration_value') ? GETPOSTISSET('duration_value', 'alpha') : 'h'), 0, 1); print ''; } diff --git a/htdocs/product/class/html.formproduct.class.php b/htdocs/product/class/html.formproduct.class.php index 5be93a9b9d1..555bc08d03e 100644 --- a/htdocs/product/class/html.formproduct.class.php +++ b/htdocs/product/class/html.formproduct.class.php @@ -414,7 +414,7 @@ class FormProduct dol_print_error($db); return -1; } else { - $return .= ''; if ($adddefault || $adddefault === '') { $return .= ''; } @@ -447,6 +447,8 @@ class FormProduct $return .= ''; } + $return .= ajax_combobox($name); + return $return; } diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index 5e17c92c562..02c045e2ce1 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -116,6 +116,7 @@ class Task extends CommonObject public $timespent_datehour; // More accurate start date (same than timespent_date but includes hours, minutes and seconds) public $timespent_withhour; // 1 = we entered also start hours for timesheet line public $timespent_fk_user; + public $timespent_thm; public $timespent_note; public $comments = array(); @@ -1212,6 +1213,7 @@ class Task extends CommonObject $ret = -2; } + // Update hourly rate of this time spent entry $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task_time"; $sql .= " SET thm = (SELECT thm FROM ".MAIN_DB_PREFIX."user WHERE rowid = ".((int) $this->timespent_fk_user).")"; // set average hour rate of user $sql .= " WHERE rowid = ".((int) $tasktime_id); @@ -1425,6 +1427,7 @@ class Task extends CommonObject $sql .= " ptt.task_duration,"; $sql .= " ptt.fk_user,"; $sql .= " ptt.note,"; + $sql .= " ptt.thm,"; $sql .= " pt.rowid as task_id,"; $sql .= " pt.ref as task_ref,"; $sql .= " pt.label as task_label,"; @@ -1435,7 +1438,7 @@ class Task extends CommonObject $sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as ptt, ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."projet as p"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid"; $sql .= " WHERE ptt.fk_task = pt.rowid AND pt.fk_projet = p.rowid"; - $sql .= " AND ptt.fk_user = ".$userobj->id; + $sql .= " AND ptt.fk_user = ".((int) $userobj->id); $sql .= " AND pt.entity IN (".getEntity('project').")"; if ($morewherefilter) { $sql .= $morewherefilter; @@ -1471,6 +1474,7 @@ class Task extends CommonObject $newobj->timespent_withhour = $obj->task_date_withhour; $newobj->timespent_duration = $obj->task_duration; $newobj->timespent_fk_user = $obj->fk_user; + $newobj->timespent_thm = $obj->thm; // hourly rate $newobj->timespent_note = $obj->note; $arrayres[] = $newobj; @@ -1552,10 +1556,12 @@ class Task extends CommonObject } if ($ret == 1 && ($this->timespent_old_duration != $this->timespent_duration)) { - $newDuration = $this->timespent_duration - $this->timespent_old_duration; - + // Recalculate amount of time spent for task and update denormalized field $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task"; $sql .= " SET duration_effective = (SELECT SUM(task_duration) FROM ".MAIN_DB_PREFIX."projet_task_time as ptt where ptt.fk_task = ".((int) $this->id).")"; + if (isset($this->progress)) { + $sql .= ", progress = ".((float) $this->progress); // Do not overwrite value if not provided + } $sql .= " WHERE rowid = ".((int) $this->id); dol_syslog(get_class($this)."::updateTimeSpent", LOG_DEBUG); @@ -1564,6 +1570,18 @@ class Task extends CommonObject $this->db->rollback(); $ret = -2; } + + // Update hourly rate of this time spent entry, but only if it was not set initialy + $sql = "UPDATE ".MAIN_DB_PREFIX."projet_task_time"; + $sql .= " SET thm = (SELECT thm FROM ".MAIN_DB_PREFIX."user WHERE rowid = ".((int) $this->timespent_fk_user).")"; // set average hour rate of user + $sql .= " WHERE (thm IS NULL OR thm = 0) AND rowid = ".((int) $this->timespent_id); + + dol_syslog(get_class($this)."::addTimeSpent", LOG_DEBUG); + if (!$this->db->query($sql)) { + $this->error = $this->db->lasterror(); + $ret = -2; + } + } if ($ret >= 0) { diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index bbe9671faf3..f04b53c3d1e 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -261,10 +261,10 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us $object->timespent_duration = GETPOSTINT("new_durationhour") * 60 * 60; // We store duration in seconds $object->timespent_duration += (GETPOSTINT("new_durationmin") ? GETPOSTINT('new_durationmin') : 0) * 60; // We store duration in seconds if (GETPOST("timelinehour") != '' && GETPOST("timelinehour") >= 0) { // If hour was entered - $object->timespent_date = dol_mktime(GETPOST("timelinehour"), GETPOST("timelinemin"), 0, GETPOST("timelinemonth"), GETPOST("timelineday"), GETPOST("timelineyear")); + $object->timespent_date = dol_mktime(GETPOST("timelinehour", 'int'), GETPOST("timelinemin", 'int'), 0, GETPOST("timelinemonth", 'int'), GETPOST("timelineday", 'int'), GETPOST("timelineyear", 'int')); $object->timespent_withhour = 1; } else { - $object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timelinemonth"), GETPOST("timelineday"), GETPOST("timelineyear")); + $object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timelinemonth", 'int'), GETPOST("timelineday", 'int'), GETPOST("timelineyear", 'int')); } $object->timespent_fk_user = GETPOST("userid_line", 'int'); @@ -353,6 +353,13 @@ if ($action == 'confirm_generateinvoice') { $prodDurationHours = 1.0; if ($idprod > 0) { $tmpproduct->fetch($idprod); + + if (empty($tmpproduct->duration_value)) { + $error++; + $langs->load("errors"); + setEventMessages($langs->trans("ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice"), null, 'errors'); + } + if ($tmpproduct->duration_unit == 'i') { $prodDurationHours = 1. / 60; } @@ -380,6 +387,8 @@ if ($action == 'confirm_generateinvoice') { $localtax1 = $dataforprice['localtax1']; $localtax2 = $dataforprice['localtax2']; } else { + $prodDurationHours = 1; + $pu_ht = 0; $txtva = get_default_tva($mysoc, $projectstatic->thirdparty); $localtax1 = get_default_localtax($mysoc, $projectstatic->thirdparty, 1); @@ -482,14 +491,14 @@ if ($action == 'confirm_generateinvoice') { break; } } - } elseif ($generateinvoicemode == 'onelinepertask') { + } elseif ($generateinvoicemode == 'onelinepertask') { // One line for each different task $arrayoftasks = array(); foreach ($toselect as $key => $value) { // Get userid, timepent - $object->fetchTimeSpent($value); - // $object->id is the task id + $object->fetchTimeSpent($value); // Call method to get list of timespent for a timespent line id (We use the utiliy method found into Task object) + // $object->id is now the task id $arrayoftasks[$object->id]['timespent'] += $object->timespent_duration; - $arrayoftasks[$object->id]['totalvaluetodivideby3600'] += $object->timespent_duration * $object->timespent_thm; + $arrayoftasks[$object->id]['totalvaluetodivideby3600'] += ($object->timespent_duration * $object->timespent_thm); } foreach ($arrayoftasks as $task_id => $value) { @@ -499,24 +508,46 @@ if ($action == 'confirm_generateinvoice') { $qtyhour = $value['timespent'] / 3600; $qtyhourtext = convertSecondToTime($value['timespent'], 'all', $conf->global->MAIN_DURATION_OF_WORKDAY); - // If no unit price known - if (empty($pu_ht)) { - $pu_ht = price2num($value['totalvaluetodivideby3600'] / 3600, 'MU'); + if ($idprod > 0) { + // If a product is defined, we msut use the $prodDurationHours and $pu_ht of product (already set previously). + $pu_ht_for_task = $pu_ht; + // If we want to reuse the value of timespent (so use same price than cost price) + if (!empty($conf->global->PROJECT_TIME_SPENT_INTO_INVOICE_USE_VALUE)) { + $pu_ht_for_task = price2num($value['totalvaluetodivideby3600'] / $value['timespent'], 'MU') * $prodDurationHours; + } + $pa_ht = price2num($value['totalvaluetodivideby3600'] / $value['timespent'], 'MU') * $prodDurationHours; + } else { + // If not product used, we use the hour unit for duration and unit price. + $pu_ht_for_task = 0; + // If we want to reuse the value of timespent (so use same price than cost price) + if (!empty($conf->global->PROJECT_TIME_SPENT_INTO_INVOICE_USE_VALUE)) { + $pu_ht_for_task = price2num($value['totalvaluetodivideby3600'] / $value['timespent'], 'MU'); + } + $pa_ht = price2num($value['totalvaluetodivideby3600'] / $value['timespent'], 'MU'); } // Add lines + $date_start = ''; + $date_end = ''; $lineName = $ftask->ref.' - '.$ftask->label; - $lineid = $tmpinvoice->addline($lineName, $pu_ht, round($qtyhour / $prodDurationHours, 2), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0)); - - // Update lineid into line of timespent - $sql = 'UPDATE '.MAIN_DB_PREFIX.'projet_task_time SET invoice_line_id = '.((int) $lineid).', invoice_id = '.((int) $tmpinvoice->id); - $sql .= ' WHERE rowid IN ('.$db->sanitize(join(',', $toselect)).')'; - $result = $db->query($sql); - if (!$result) { + $lineid = $tmpinvoice->addline($lineName, $pu_ht_for_task, price2num($qtyhour / $prodDurationHours, 'MS'), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0), 0, $date_start, $date_end, 0, 0, '', 'HT', 0, 1, -1, 0, '', 0, 0, null, $pa_ht); + if ($lineid < 0) { $error++; - setEventMessages($db->lasterror(), null, 'errors'); + setEventMessages($tmpinvoice->error, $tmpinvoice->errors, 'errors'); break; } + + if (!$error) { + // Update lineid into line of timespent + $sql = 'UPDATE '.MAIN_DB_PREFIX.'projet_task_time SET invoice_line_id = '.((int) $lineid).', invoice_id = '.((int) $tmpinvoice->id); + $sql .= ' WHERE rowid IN ('.$db->sanitize(join(',', $toselect)).')'; + $result = $db->query($sql); + if (!$result) { + $error++; + setEventMessages($db->lasterror(), null, 'errors'); + break; + } + } } } } @@ -960,7 +991,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) { print ''; if ($projectstatic->thirdparty->id > 0) { - print ''; + print '
'; print ''; print ''; - $date1 = $db->jdate($task_time->task_date); $date2 = $db->jdate($task_time->task_datehour); + print ''; + // Date if (!empty($arrayfields['t.task_date']['checked'])) { print ''; if (!$i) { $totalarray['nbfield']++; From f9d60b15d956cac3e4bd14eacf1b0f1a30f4a159 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 12 Jul 2021 23:56:42 +0200 Subject: [PATCH 23/58] Fix phpcs --- htdocs/projet/class/task.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index 02c045e2ce1..574fb534b2c 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -1581,7 +1581,6 @@ class Task extends CommonObject $this->error = $this->db->lasterror(); $ret = -2; } - } if ($ret >= 0) { From 35b29481c786f2ea091160ad4d8550d8f9f26e74 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 13 Jul 2021 10:05:38 +0200 Subject: [PATCH 24/58] Close #18131 : new massaction for thirdparty --- htdocs/core/actions_massactions.inc.php | 74 +++++++++++++++++++++++++ htdocs/core/tpl/massactions_pre.tpl.php | 8 +++ htdocs/langs/en_US/main.lang | 10 ++++ htdocs/langs/fr_FR/main.lang | 10 ++++ htdocs/societe/list.php | 8 ++- 5 files changed, 109 insertions(+), 1 deletion(-) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index cd8a3817602..30433004f95 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1470,6 +1470,80 @@ if (!$error && ($action == 'affecttag' && $confirm == 'yes') && $permissiontoadd } } +if (!$error && ($massaction == 'enable' || ($action == 'enable' && $confirm == 'yes')) && $permissiontoadd) { + $db->begin(); + + $objecttmp = new $objectclass($db); + $nbok = 0; + foreach ($toselect as $toselectid) { + $result = $objecttmp->fetch($toselectid); + if($result>0){ + if (in_array($objecttmp->element,array('societe'))) { + $result =$objecttmp->setStatut(1); + } + if ($result <= 0) { + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); + $error++; + break; + } else { + $nbok++; + } + }else { + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); + $error++; + break; + } + } + + if (!$error) { + if ($nbok > 1) { + setEventMessages($langs->trans("RecordsEnabled", $nbok), null, 'mesgs'); + } else { + setEventMessages($langs->trans("RecordEnabled"), null, 'mesgs'); + } + $db->commit(); + } else { + $db->rollback(); + } +} + +if (!$error && ($massaction == 'disable' || ($action == 'disable' && $confirm == 'yes')) && $permissiontoadd) { + $db->begin(); + + $objecttmp = new $objectclass($db); + $nbok = 0; + foreach ($toselect as $toselectid) { + $result = $objecttmp->fetch($toselectid); + if($result>0){ + if (in_array($objecttmp->element,array('societe'))) { + $result =$objecttmp->setStatut(0); + } + if ($result <= 0) { + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); + $error++; + break; + } else { + $nbok++; + } + }else { + setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); + $error++; + break; + } + } + + if (!$error) { + if ($nbok > 1) { + setEventMessages($langs->trans("RecordsDisabled", $nbok), null, 'mesgs'); + } else { + setEventMessages($langs->trans("RecordDisabled"), null, 'mesgs'); + } + $db->commit(); + } else { + $db->rollback(); + } +} + $parameters['toselect'] = $toselect; $parameters['uploaddir'] = $uploaddir; $parameters['massaction'] = $massaction; diff --git a/htdocs/core/tpl/massactions_pre.tpl.php b/htdocs/core/tpl/massactions_pre.tpl.php index 4b8680e11bb..c40f896e702 100644 --- a/htdocs/core/tpl/massactions_pre.tpl.php +++ b/htdocs/core/tpl/massactions_pre.tpl.php @@ -194,6 +194,14 @@ if ($massaction == 'presend') { print dol_get_fiche_end(); } + +if ($massaction == 'preenable') { + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassEnabling"), $langs->trans("ConfirmMassEnablingQuestion", count($toselect)), "enable", null, '', 0, 200, 500, 1); +} +if ($massaction == 'predisable') { + print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassDisabling"), $langs->trans("ConfirmMassDisablingQuestion", count($toselect)), "disable", null, '', 0, 200, 500, 1); +} + // Allow Pre-Mass-Action hook (eg for confirmation dialog) $parameters = array( 'toselect' => $toselect, diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 863b94af564..44cdafdda09 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -1137,3 +1137,13 @@ CopiedToClipboard=Copied to clipboard InformationOnLinkToContract=This amount is only the total of all the lines of the contract. No notion of time is taken into consideration. ConfirmCancel=Are you sure you want to cancel EmailMsgID=Email MsgID +SetToEnabled=Set to enabled +SetToDisabled=Set to disabled +ConfirmMassEnabling=mass enabling confirmation +ConfirmMassEnablingQuestion=Are you sure you want to enable the %s selected record(s)? +ConfirmMassDisabling=mass disabling confirmation +ConfirmMassDisablingQuestion=Are you sure you want to disable the %s selected record(s)? +RecordsEnabled=%s record(s) enabled +RecordsDisabled=%s record(s) disabled +RecordEnabled=Record enabled +RecordDisabled=Record disabled diff --git a/htdocs/langs/fr_FR/main.lang b/htdocs/langs/fr_FR/main.lang index bf49ccccf54..2453fab1e16 100644 --- a/htdocs/langs/fr_FR/main.lang +++ b/htdocs/langs/fr_FR/main.lang @@ -1137,3 +1137,13 @@ CopiedToClipboard=Copié dans le presse-papier InformationOnLinkToContract=Ce montant n’est que le total de toutes les lignes du contrat. Aucune notion de temps n’est prise en considération. ConfirmCancel=Êtes-vous sûr de vous annuler EmailMsgID=E-mail MsgID +SetToEnabled=Activer +SetToDisabled=Désactiver +ConfirmMassEnabling=Confirmation d'activation en masse +ConfirmMassEnablingQuestion=Êtes-vous sur de vouloir activer les %s enregistrement(s) sélectionné(s) ? +ConfirmMassDisabling=Confirmation de desactivation en masse +ConfirmMassDisablingQuestion=Êtes-vous sur de vouloir desactiver les %s enregistrement(s) sélectionné(s) ? +RecordsEnabled=%s enregistrement(s) activé(s) +RecordsDisabled=%s enregistrement(s) désactivé(s) +RecordEnabled=Enregistrement activé +RecordDisabled=Enregistrement désactivé diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 5935ac43b70..6835794e916 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -865,7 +865,13 @@ if ($user->rights->societe->supprimer) { if ($user->rights->societe->creer) { $arrayofmassactions['preaffecttag'] = img_picto('', 'category', 'class="pictofixedwidth"').$langs->trans("AffectTag"); } -if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete', 'preaffecttag'))) { +if ($user->rights->societe->creer) { + $arrayofmassactions['preenable'] = img_picto('', '', 'class="pictofixedwidth"').$langs->trans("SetToEnabled"); +} +if ($user->rights->societe->creer) { + $arrayofmassactions['predisable'] = img_picto('', '', 'class="pictofixedwidth"').$langs->trans("SetToDisabled"); +} +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete', 'preaffecttag', 'preenable', 'preclose'))) { $arrayofmassactions = array(); } $massactionbutton = $form->selectMassAction('', $arrayofmassactions); From 85adefe721b9f5c49e357942602cd852f4512279 Mon Sep 17 00:00:00 2001 From: stickler-ci Date: Tue, 13 Jul 2021 08:08:01 +0000 Subject: [PATCH 25/58] Fixing style errors. --- htdocs/core/actions_massactions.inc.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 30433004f95..e5d4de26278 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1477,8 +1477,8 @@ if (!$error && ($massaction == 'enable' || ($action == 'enable' && $confirm == ' $nbok = 0; foreach ($toselect as $toselectid) { $result = $objecttmp->fetch($toselectid); - if($result>0){ - if (in_array($objecttmp->element,array('societe'))) { + if ($result>0) { + if (in_array($objecttmp->element, array('societe'))) { $result =$objecttmp->setStatut(1); } if ($result <= 0) { @@ -1488,7 +1488,7 @@ if (!$error && ($massaction == 'enable' || ($action == 'enable' && $confirm == ' } else { $nbok++; } - }else { + } else { setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); $error++; break; @@ -1514,8 +1514,8 @@ if (!$error && ($massaction == 'disable' || ($action == 'disable' && $confirm == $nbok = 0; foreach ($toselect as $toselectid) { $result = $objecttmp->fetch($toselectid); - if($result>0){ - if (in_array($objecttmp->element,array('societe'))) { + if ($result>0) { + if (in_array($objecttmp->element, array('societe'))) { $result =$objecttmp->setStatut(0); } if ($result <= 0) { @@ -1525,7 +1525,7 @@ if (!$error && ($massaction == 'disable' || ($action == 'disable' && $confirm == } else { $nbok++; } - }else { + } else { setEventMessages($objecttmp->error, $objecttmp->errors, 'errors'); $error++; break; From df3d88570c4527f7da70d526a77154f86c567324 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 13 Jul 2021 11:39:08 +0200 Subject: [PATCH 26/58] Fix missing column in migration --- htdocs/install/mysql/migration/12.0.0-13.0.0.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql index da4d0fd0a42..cb466f94b10 100644 --- a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql +++ b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql @@ -368,7 +368,7 @@ ALTER TABLE llx_actioncomm_reminder ADD UNIQUE uk_actioncomm_reminder_unique (fk ALTER TABLE llx_actioncomm_reminder ADD INDEX idx_actioncomm_reminder_status (status); - +ALTER TABLE llx_inventorydet ADD COLUMN fk_warehouse integer DEFAULT 0; ALTER TABLE llx_inventorydet ADD UNIQUE uk_inventorydet(fk_inventory, fk_warehouse, fk_product, batch); ALTER TABLE llx_commandedet ADD COLUMN ref_ext varchar(255) AFTER label; From bbce0f9c1bd89fda1c3774599d141d2a6e4a2bfc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 13 Jul 2021 13:01:34 +0200 Subject: [PATCH 27/58] Update html.form.class.php --- htdocs/core/class/html.form.class.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index cbb1f09f3d8..8c588cfb2e4 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4454,7 +4454,6 @@ class Form */ public function selectEstablishments($selected = '', $htmlname = 'entity', $status = 0, $filtre = '', $useempty = 0, $moreattrib = '') { - // phpcs:enable global $langs, $conf; $langs->load("admin"); @@ -6603,7 +6602,6 @@ class Form */ public function selectTickets($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 0, $status = 1, $selected_input_value = '', $hidelabel = 0, $ajaxoptions = array(), $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $selected_combinations = null, $nooutput = 0) { - // phpcs:enable global $langs, $conf; $out = ''; From 4c29a3ad994b9d9f43fbebdf33ccb1fe08ca7803 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 13 Jul 2021 13:06:28 +0200 Subject: [PATCH 28/58] Fix migration --- htdocs/install/mysql/migration/12.0.0-13.0.0.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql index 1ebb8e380a7..29c2aad9bd4 100644 --- a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql +++ b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql @@ -367,7 +367,7 @@ ALTER TABLE llx_actioncomm_reminder ADD UNIQUE uk_actioncomm_reminder_unique (fk ALTER TABLE llx_actioncomm_reminder ADD INDEX idx_actioncomm_reminder_status (status); - +ALTER TABLE llx_inventorydet ADD COLUMN fk_warehouse integer DEFAULT 0; ALTER TABLE llx_inventorydet ADD UNIQUE uk_inventorydet(fk_inventory, fk_warehouse, fk_product, batch); ALTER TABLE llx_commandedet ADD COLUMN ref_ext varchar(255) AFTER label; From 7a589921fe3d6cd902bff136b5047d8811bd80ec Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 13 Jul 2021 13:10:19 +0200 Subject: [PATCH 29/58] Fix #18142 --- htdocs/install/mysql/tables/llx_facture.sql | 2 +- htdocs/install/mysql/tables/llx_facture_fourn.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/install/mysql/tables/llx_facture.sql b/htdocs/install/mysql/tables/llx_facture.sql index 010cf1c1573..ee98752e5f3 100644 --- a/htdocs/install/mysql/tables/llx_facture.sql +++ b/htdocs/install/mysql/tables/llx_facture.sql @@ -86,7 +86,7 @@ create table llx_facture fk_incoterms integer, -- for incoterms location_incoterms varchar(255), -- for incoterms - fk_mode_transport integer, -- for intracomm report + fk_transport_mode integer, -- for intracomm report situation_cycle_ref smallint, -- situation cycle reference situation_counter smallint, -- situation counter diff --git a/htdocs/install/mysql/tables/llx_facture_fourn.sql b/htdocs/install/mysql/tables/llx_facture_fourn.sql index ef7e980b8aa..906125d0679 100644 --- a/htdocs/install/mysql/tables/llx_facture_fourn.sql +++ b/htdocs/install/mysql/tables/llx_facture_fourn.sql @@ -71,7 +71,7 @@ create table llx_facture_fourn fk_incoterms integer, -- for incoterms location_incoterms varchar(255), -- for incoterms - fk_mode_transport integer, -- for intracomm report + fk_transport_mode integer, -- for intracomm report model_pdf varchar(255), last_main_doc varchar(255), -- relative filepath+filename of last main generated document From e755d68b068dd1008b90ab62156fa7e606570969 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 13 Jul 2021 13:22:20 +0200 Subject: [PATCH 30/58] Merge branch '14.0' of git@github.com:Dolibarr/dolibarr.git into develop --- htdocs/core/class/hookmanager.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index b22caf17f04..5e24ee03fa4 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -296,9 +296,9 @@ class HookManager $this->resPrint .= $actionclassinstance->resprints; } } - } - // Generic hooks that return a string or array (printLeftBlock, formAddObjectLine, formBuilddocOptions, ...) - else { + } else { + // Generic hooks that return a string or array (printLeftBlock, formAddObjectLine, formBuilddocOptions, ...) + // TODO. this test should be done into the method of hook by returning nothing if (is_array($parameters) && !empty($parameters['special_code']) && $parameters['special_code'] > 3 && $parameters['special_code'] != $actionclassinstance->module_number) { continue; From af99cab839eeb185b2e40503b25476184b60a976 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 13 Jul 2021 13:46:20 +0200 Subject: [PATCH 31/58] CSS --- htdocs/compta/index.php | 2 +- htdocs/core/boxes/box_factures.php | 2 +- htdocs/core/boxes/box_factures_imp.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/index.php b/htdocs/compta/index.php index 8db217747ef..b1ad18e6461 100644 --- a/htdocs/compta/index.php +++ b/htdocs/compta/index.php @@ -226,7 +226,7 @@ if (!empty($conf->facture->enabled) && !empty($user->rights->facture->lire)) { print $thirdpartystatic->getNomUrl(1, 'customer', 44); print ''; if (!empty($conf->global->MAIN_SHOW_HT_ON_SUMMARY)) { - print ''; + print ''; } print ''; print ''; diff --git a/htdocs/core/boxes/box_factures.php b/htdocs/core/boxes/box_factures.php index 2a97d738cd8..12382ccb583 100644 --- a/htdocs/core/boxes/box_factures.php +++ b/htdocs/core/boxes/box_factures.php @@ -180,7 +180,7 @@ class box_factures extends ModeleBoxes ); $this->info_box_contents[$line][] = array( - 'td' => 'class="right nowraponall"', + 'td' => 'class="right nowraponall amount"', 'text' => price($objp->total_ht, 0, $langs, 0, -1, -1, $conf->currency), ); diff --git a/htdocs/core/boxes/box_factures_imp.php b/htdocs/core/boxes/box_factures_imp.php index 391fc2e7cd0..400ae910749 100644 --- a/htdocs/core/boxes/box_factures_imp.php +++ b/htdocs/core/boxes/box_factures_imp.php @@ -182,7 +182,7 @@ class box_factures_imp extends ModeleBoxes ); $this->info_box_contents[$line][] = array( - 'td' => 'class="nowraponall right"', + 'td' => 'class="nowraponall right amount"', 'text' => price($objp->total_ht, 0, $langs, 0, -1, -1, $conf->currency), ); From 66f38d001265fa8441fdd7c51ca6f4fbbc5fb495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20David?= Date: Tue, 13 Jul 2021 14:00:16 +0200 Subject: [PATCH 32/58] fix: rename select_tickets_list into selectTicketsList --- htdocs/core/class/html.form.class.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 8c588cfb2e4..482b1672d51 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6582,7 +6582,7 @@ class Form } /** - * Return list of tickets in Ajax if Ajax activated or go to select_tickets_list + * Return list of tickets in Ajax if Ajax activated or go to selectTicketsList * * @param int $selected Preselected tickets * @param string $htmlname Name of HTML select field (must be unique in page). @@ -6634,7 +6634,7 @@ class Form $out .= img_picto($langs->trans("Search"), 'search'); } } else { - $out .= $this->select_tickets_list($selected, $htmlname, $filtertype, $limit, $status, 0, $socid, $showempty, $forcecombo, $morecss); + $out .= $this->selectTicketsList($selected, $htmlname, $filtertype, $limit, $status, 0, $socid, $showempty, $forcecombo, $morecss); } if (empty($nooutput)) print $out; @@ -6642,7 +6642,6 @@ class Form } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return list of tickets. * Called by selectTickets. @@ -6659,7 +6658,7 @@ class Form * @param string $morecss Add more css on select * @return array Array of keys for json */ - public function select_tickets_list($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '') + public function selectTicketsList($selected = '', $htmlname = 'ticketid', $filtertype = '', $limit = 20, $filterkey = '', $status = 1, $outputmode = 0, $showempty = '1', $forcecombo = 0, $morecss = '') { global $langs, $conf, $user, $db; @@ -6694,7 +6693,7 @@ class Form $sql .= $this->db->plimit($limit, 0); // Build output string - dol_syslog(get_class($this)."::select_tickets_list search tickets", LOG_DEBUG); + dol_syslog(get_class($this)."::selectTicketsList search tickets", LOG_DEBUG); $result = $this->db->query($sql); if ($result) { require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php'; From 0d9cf07035708afe950967d2d62e0fe687a8b2ac Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 13 Jul 2021 14:07:35 +0200 Subject: [PATCH 33/58] Show ref of invoice into tooltip --- htdocs/takepos/invoice.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index 8cef291c2d7..721a7b92ae8 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -1095,7 +1095,7 @@ $( document ).ready(function() { $max_sale = 0; while ($obj = $db->fetch_object($resql)) { echo '$("#customerandsales").append(\''; - echo 'jdate($obj->datec), '%H:%M', 'tzuser'))).'" onclick="place=\\\''; + echo 'jdate($obj->datec), '%H:%M', 'tzuser')).' - '.$obj->ref).'" onclick="place=\\\''; $num_sale = str_replace(")", "", str_replace("(PROV-POS".$_SESSION["takeposterminal"]."-", "", $obj->ref)); echo $num_sale; if (str_replace("-", "", $num_sale) > $max_sale) { From b12aae4a99459193e93d710cfc242e94fdd02afd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 13 Jul 2021 14:26:32 +0200 Subject: [PATCH 34/58] FIX amount of payment deleted in unalterable log (for old record must look the log of creation to know amount). --- .../interface_50_modBlockedlog_ActionsBlockedLog.class.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php index cab0702c5c1..741cc4d09bc 100644 --- a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php +++ b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php @@ -118,6 +118,8 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers foreach ($object->amounts as $amount) { $amounts += price2num($amount); } + } elseif (!empty($object->amount)) { + $amounts = $object->amount; } } elseif (strpos($action, 'PAYMENT') !== false && !in_array($action, array('PAYMENT_ADD_TO_BANK'))) { $qualified++; From ba8d60f4d4b62b1cd1bda6d5faaeb995b600055d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 13 Jul 2021 14:48:05 +0200 Subject: [PATCH 35/58] FIX amount of payment deleted in unalterable log (for old record must look the log of creation to know amount). --- htdocs/blockedlog/class/blockedlog.class.php | 175 ++++++++++--------- 1 file changed, 88 insertions(+), 87 deletions(-) diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index 112456480e1..a7be2fb3630 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -549,110 +549,111 @@ class BlockedLog $totalamount = 0; - if (!is_array($object->amounts) && $object->amount) { - $object->amounts = array($object->id => $object->amount); - } + // Loop on each invoice payment amount + if (is_array($object->amounts) && !empty($object->amounts)) { + $paymentpartnumber = 0; + foreach ($object->amounts as $objid => $amount) { + if (empty($amount)) { + continue; + } - $paymentpartnumber = 0; - foreach ($object->amounts as $objid => $amount) { - if (empty($amount)) { - continue; - } + $totalamount += $amount; - $totalamount += $amount; + $tmpobject = null; + if ($this->element == 'payment_supplier') { + include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; + $tmpobject = new FactureFournisseur($this->db); + } elseif ($this->element == 'payment') { + include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + $tmpobject = new Facture($this->db); + } elseif ($this->element == 'payment_donation') { + include_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php'; + $tmpobject = new Don($this->db); + } elseif ($this->element == 'payment_various') { + include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php'; + $tmpobject = new PaymentVarious($this->db); + } - $tmpobject = null; - if ($this->element == 'payment_supplier') { - include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; - $tmpobject = new FactureFournisseur($this->db); - } elseif ($this->element == 'payment') { - include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; - $tmpobject = new Facture($this->db); - } elseif ($this->element == 'payment_donation') { - include_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php'; - $tmpobject = new Don($this->db); - } elseif ($this->element == 'payment_various') { - include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php'; - $tmpobject = new PaymentVarious($this->db); - } + if (!is_object($tmpobject)) { + continue; + } - if (!is_object($tmpobject)) { - continue; - } + $result = $tmpobject->fetch($objid); - $result = $tmpobject->fetch($objid); - - if ($result <= 0) { - $this->error = $tmpobject->error; - $this->errors = $tmpobject->errors; - dol_syslog("Failed to fetch object with id ".$objid, LOG_ERR); - return -1; - } - - $paymentpart = new stdClass(); - $paymentpart->amount = $amount; - - if (!in_array($this->element, array('payment_donation', 'payment_various'))) { - $result = $tmpobject->fetch_thirdparty(); - if ($result == 0) { - $this->error = 'Failed to fetch thirdparty for object with id '.$tmpobject->id; - $this->errors[] = $this->error; - dol_syslog("Failed to fetch thirdparty for object with id ".$tmpobject->id, LOG_ERR); - return -1; - } elseif ($result < 0) { + if ($result <= 0) { $this->error = $tmpobject->error; $this->errors = $tmpobject->errors; + dol_syslog("Failed to fetch object with id ".$objid, LOG_ERR); return -1; } - $paymentpart->thirdparty = new stdClass(); - foreach ($tmpobject->thirdparty as $key => $value) { - if (in_array($key, $arrayoffieldstoexclude)) { - continue; // Discard some properties - } - if (!in_array($key, array( - 'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode', - 'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur' - ))) { - continue; // Discard if not into a dedicated list - } - if (!is_object($value) && !is_null($value) && $value !== '') { - $paymentpart->thirdparty->{$key} = $value; - } - } - } + $paymentpart = new stdClass(); + $paymentpart->amount = $amount; - // Init object to avoid warnings - if ($this->element == 'payment_donation') { - $paymentpart->donation = new stdClass(); - } else { - $paymentpart->invoice = new stdClass(); - } + if (!in_array($this->element, array('payment_donation', 'payment_various'))) { + $result = $tmpobject->fetch_thirdparty(); + if ($result == 0) { + $this->error = 'Failed to fetch thirdparty for object with id '.$tmpobject->id; + $this->errors[] = $this->error; + dol_syslog("Failed to fetch thirdparty for object with id ".$tmpobject->id, LOG_ERR); + return -1; + } elseif ($result < 0) { + $this->error = $tmpobject->error; + $this->errors = $tmpobject->errors; + return -1; + } - if ($this->element != 'payment_various') { - foreach ($tmpobject as $key => $value) { - if (in_array($key, $arrayoffieldstoexclude)) { - continue; // Discard some properties - } - if (!in_array($key, array( - 'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public' - ))) { - continue; // Discard if not into a dedicated list - } - if (!is_object($value) && !is_null($value) && $value !== '') { - if ($this->element == 'payment_donation') { - $paymentpart->donation->{$key} = $value; - } elseif ($this->element == 'payment_various') { - $paymentpart->various->{$key} = $value; - } else { - $paymentpart->invoice->{$key} = $value; + $paymentpart->thirdparty = new stdClass(); + foreach ($tmpobject->thirdparty as $key => $value) { + if (in_array($key, $arrayoffieldstoexclude)) { + continue; // Discard some properties + } + if (!in_array($key, array( + 'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode', + 'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur' + ))) { + continue; // Discard if not into a dedicated list + } + if (!is_object($value) && !is_null($value) && $value !== '') { + $paymentpart->thirdparty->{$key} = $value; } } } - $paymentpartnumber++; // first payment will be 1 - $this->object_data->payment_part[$paymentpartnumber] = $paymentpart; + // Init object to avoid warnings + if ($this->element == 'payment_donation') { + $paymentpart->donation = new stdClass(); + } else { + $paymentpart->invoice = new stdClass(); + } + + if ($this->element != 'payment_various') { + foreach ($tmpobject as $key => $value) { + if (in_array($key, $arrayoffieldstoexclude)) { + continue; // Discard some properties + } + if (!in_array($key, array( + 'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public' + ))) { + continue; // Discard if not into a dedicated list + } + if (!is_object($value) && !is_null($value) && $value !== '') { + if ($this->element == 'payment_donation') { + $paymentpart->donation->{$key} = $value; + } elseif ($this->element == 'payment_various') { + $paymentpart->various->{$key} = $value; + } else { + $paymentpart->invoice->{$key} = $value; + } + } + } + + $paymentpartnumber++; // first payment will be 1 + $this->object_data->payment_part[$paymentpartnumber] = $paymentpart; + } } + } elseif (!empty($object->amount)) { + $totalamount = $object->amount; } $this->object_data->amount = $totalamount; From 9a12b5e424fb061d3650f7be2352ccb92037e5e1 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 13 Jul 2021 15:17:01 +0200 Subject: [PATCH 36/58] Fix : remove of a button which was forgotten --- htdocs/core/class/html.formticket.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/core/class/html.formticket.class.php b/htdocs/core/class/html.formticket.class.php index 48c861fdd95..9383c0a6e78 100644 --- a/htdocs/core/class/html.formticket.class.php +++ b/htdocs/core/class/html.formticket.class.php @@ -701,7 +701,6 @@ class FormTicket $stringtoprint .= ''; $stringtoprint .= ''; } - $stringtoprint .= ''; $stringtoprint .= ' '; $levelid = 1; From 0fe46b53d855ac0cfb56ab8c1fdff70195456ff2 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Tue, 13 Jul 2021 15:18:40 +0200 Subject: [PATCH 37/58] FIX : method_exists needs object at first param --- htdocs/core/actions_addupdatedelete.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index bb648a71625..f0bf57485a9 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -262,7 +262,7 @@ if ($action == 'confirm_delete' && !empty($permissiontodelete)) // Remove a line if ($action == 'confirm_deleteline' && $confirm == 'yes' && !empty($permissiontoadd)) { - if (method_exists('deleteline', $object)) { + if (method_exists($object, 'deleteline')) { $result = $object->deleteline($user, $lineid); // For backward compatibility } else { $result = $object->deleteLine($user, $lineid); From 1a330e0b887657c4d9a1596b84979c2508d52c01 Mon Sep 17 00:00:00 2001 From: ATM john Date: Wed, 14 Jul 2021 00:02:55 +0200 Subject: [PATCH 38/58] Fix dialog BTN and add doc --- htdocs/core/js/lib_foot.js.php | 13 +- htdocs/core/lib/functions.lib.php | 5 +- htdocs/public/test/badges.php | 21 +--- htdocs/public/test/buttons.php | 196 ++++++++++++++++++++++++++++++ 4 files changed, 214 insertions(+), 21 deletions(-) create mode 100644 htdocs/public/test/buttons.php diff --git a/htdocs/core/js/lib_foot.js.php b/htdocs/core/js/lib_foot.js.php index beb2788ca24..00f161a31ef 100644 --- a/htdocs/core/js/lib_foot.js.php +++ b/htdocs/core/js/lib_foot.js.php @@ -263,6 +263,8 @@ print '$( document ).ready(function() { var confirmContent = $(this).attr(\'data-confirm-content\'); var confirmActionBtnLabel = $(this).attr(\'data-confirm-action-btn-label\'); var confirmCancelBtnLabel = $(this).attr(\'data-confirm-cancel-btn-label\'); + var confirmModal = $(this).attr(\'data-confirm-modal\'); + if(confirmModal == undefined){ confirmModal = false; } var confirmId = \'confirm-dialog-box\'; if($(this).attr(\'id\') != undefined){ var confirmId = confirmId + "-" + $(this).attr(\'id\'); } @@ -277,8 +279,9 @@ print '$( document ).ready(function() { $confirmBox.dialog({ autoOpen: true, - modal: false, + modal: confirmModal, //width: Math.min($( window ).width() - 50, 1700), + width: \'auto\', dialogClass: \'confirm-dialog-box\', buttons: [ { @@ -297,11 +300,11 @@ print '$( document ).ready(function() { } ], close: function( event, ui ) { - $(\'#\'+confirmBox).remove(); -}, + $(\'#\'+confirmBox).remove(); + }, open: function( event, ui ) { - $confirmBox.html(confirmContent); -} + $confirmBox.html(confirmContent); + } }); }); }); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 7f69dfb8609..9107f9514e4 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -9818,7 +9818,7 @@ function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = } // Js Confirm button - if (!empty($params['confirm'])) { + if ($userRight && !empty($params['confirm'])) { if (!is_array($params['confirm'])) { $params['confirm'] = array( 'url' => $url . (strpos($url, '?') > 0 ? '&' : '?') . 'confirm=yes' @@ -9829,8 +9829,11 @@ function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = $attr['data-confirm-url'] = $params['confirm']['url']; $attr['data-confirm-title'] = !empty($params['confirm']['title']) ? $params['confirm']['title'] : $langs->trans('ConfirmBtnCommonTitle', $label); $attr['data-confirm-content'] = !empty($params['confirm']['content']) ? $params['confirm']['content'] : $langs->trans('ConfirmBtnCommonContent', $label); + $attr['data-confirm-content'] = preg_replace("/\r|\n/", "", $attr['data-confirm-content']); $attr['data-confirm-action-btn-label'] = !empty($params['confirm']['action-btn-label']) ? $params['confirm']['action-btn-label'] : $langs->trans('Confirm'); $attr['data-confirm-cancel-btn-label'] = !empty($params['confirm']['cancel-btn-label']) ? $params['confirm']['cancel-btn-label'] : $langs->trans('CloseDialog'); + $attr['data-confirm-modal'] = !empty($params['confirm']['modal']) ? $params['confirm']['modal'] : true; + $attr['class'].= ' butActionConfirm'; } diff --git a/htdocs/public/test/badges.php b/htdocs/public/test/badges.php index fd0add00af1..2190b96db7e 100644 --- a/htdocs/public/test/badges.php +++ b/htdocs/public/test/badges.php @@ -20,7 +20,9 @@ if (!defined('NOREQUIREAJAX')) { if (!defined('NOSESSION')) { define('NOSESSION', '1'); } - +if (!defined('NOREQUIREMENU')) { + define('NOREQUIREMENU', '1'); +} session_cache_limiter('public'); require_once '../../main.inc.php'; @@ -30,19 +32,9 @@ if ($dolibarr_main_prod) { accessforbidden(); } + +llxHeader('', 'Documentation and examples for theme'); ?> - - - - - - - - - - - -

Badges

Documentation and examples for badges, our small count and labeling component.

@@ -342,5 +334,4 @@ if ($dolibarr_main_prod) {
- - \ No newline at end of file + +
+

Button for action

+

Documentation and examples for buttons.

+ +

Example of simple usage

+ +

Buttons for user allowed to click.

+ +
+ My default action'; + $actionType = 'default'; + $n++; + $id = 'mybuttonid'.$n; + $url = '#'.$id; + $userRight = 1; + $params = array(); + + print dolGetButtonAction($label, $html, $actionType, $url, $id, $userRight); + + + $html = ' My delete action'; + $actionType = 'delete'; + $n++; + $id = 'mybuttonid'.$n; + $url = $_SERVER['PHP_SELF'] . '?token='.newToken().'#'.$id; + print dolGetButtonAction($label, $html, $actionType, $url, $id, $userRight); + + + $html = ' My danger action'; + $actionType = 'danger'; + $n++; + $id = 'mybuttonid'.$n; + $url = $_SERVER['PHP_SELF'] . '?token='.newToken().'#'.$id; + print dolGetButtonAction($label, $html, $actionType, $url, $id, $userRight); + + ?> +
+ +

Buttons for user NOT allowed to click.

+ +
+ My default action'; + $actionType = 'default'; + $n++; + $id = 'mybuttonid'.$n; + $url = '#'.$id; + $userRight = 0; + + print dolGetButtonAction($label, $html, $actionType, $url, $id, $userRight); + + + $html = ' My delete action'; + $actionType = 'delete'; + $n++; + $id = 'mybuttonid'.$n; + $url = $_SERVER['PHP_SELF'] . '?token='.newToken().'#'.$id; + print dolGetButtonAction($label, $html, $actionType, $url, $id, $userRight); + + + $html = ' My danger action'; + $actionType = 'danger'; + $n++; + $id = 'mybuttonid'.$n; + $url = $_SERVER['PHP_SELF'] . '?token='.newToken().'#'.$id; + print dolGetButtonAction($label, $html, $actionType, $url, $id, $userRight); + + ?> +
+ + +

Example of confirm dialog

+ +

Buttons for user allowed to click.

+ +
+ My default action'; + $actionType = 'default'; + $n++; + $id = 'mybuttonid'.$n; + $url = '#'.$id; + $userRight = 1; + $params = array( + 'confirm' => true + ); + + print dolGetButtonAction($label, $html, $actionType, $url, $id, $userRight, $params); + + + $html = ' My delete action'; + $actionType = 'delete'; + $n++; + $id = 'mybuttonid'.$n; + $url = $_SERVER['PHP_SELF'] . '?token='.newToken().'#'.$id; + + $params = array( + 'confirm' => array( + 'url' => 'your confirm action url', + 'title' => 'Your title to display', + 'action-btn-label' => 'Your confirm label', + 'cancel-btn-label' => 'Your cancel label', + 'content' => 'Content to display with HTML compatible
  • test 01
  • test 02
  • test 03
' + ) + ); + + print dolGetButtonAction($label, $html, $actionType, $url, $id, $userRight, $params); + + ?> +
+ +

Buttons for user NOT allowed to click.

+ +
+ My default action'; + $actionType = 'default'; + $n++; + $id = 'mybuttonid'.$n; + $url = '#'.$id; + $userRight = 0; + $params = array( + 'confirm' => true + ); + + print dolGetButtonAction($label, $html, $actionType, $url, $id, $userRight, $params); + + + $html = ' My delete action'; + $actionType = 'delete'; + $n++; + $id = 'mybuttonid'.$n; + $url = $_SERVER['PHP_SELF'] . '?token='.newToken().'#'.$id; + + $params = array( + 'confirm' => array( + 'url' => 'your confirm action url', + 'title' => 'Your title to display', + 'action-btn-label' => 'Your confirm label', + 'cancel-btn-label' => 'Your cancel label', + 'content' => 'Content to display with HTML compatible
  • test 01
  • test 02
  • test 03
' + ) + ); + + print dolGetButtonAction($label, $html, $actionType, $url, $id, $userRight, $params); + + ?> +
+ + +
+ + Date: Wed, 14 Jul 2021 02:20:15 +0200 Subject: [PATCH 39/58] Fix phpcs --- htdocs/core/class/hookmanager.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/class/hookmanager.class.php b/htdocs/core/class/hookmanager.class.php index b22caf17f04..5e24ee03fa4 100644 --- a/htdocs/core/class/hookmanager.class.php +++ b/htdocs/core/class/hookmanager.class.php @@ -296,9 +296,9 @@ class HookManager $this->resPrint .= $actionclassinstance->resprints; } } - } - // Generic hooks that return a string or array (printLeftBlock, formAddObjectLine, formBuilddocOptions, ...) - else { + } else { + // Generic hooks that return a string or array (printLeftBlock, formAddObjectLine, formBuilddocOptions, ...) + // TODO. this test should be done into the method of hook by returning nothing if (is_array($parameters) && !empty($parameters['special_code']) && $parameters['special_code'] > 3 && $parameters['special_code'] != $actionclassinstance->module_number) { continue; From 87c26ae0e2e28a658589e1445f72e748d3e96090 Mon Sep 17 00:00:00 2001 From: ATM john Date: Wed, 14 Jul 2021 10:07:03 +0200 Subject: [PATCH 40/58] Add php doc --- htdocs/core/lib/functions.lib.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 9107f9514e4..26da9ee3d21 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -9770,7 +9770,23 @@ function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $st * @param string $url the url for link * @param string $id attribute id of button * @param int $userRight user action right - * @param array $params various params for future : recommended rather than adding more function arguments + * // phpcs:disable + * @param array $params = [ // Various params for future : recommended rather than adding more function arguments + * 'attr' => [ // to add or override button attributes + * 'xxxxx' => '', // your xxxxx attribute you want + * 'class' => '', // to add more css class to the button class attribute + * 'classOverride' => '' // to replace class attribute of the button + * ], + * 'confirm' => [ + * 'url' => 'http://', // Overide Url to go when user click on action btn, if empty default url is $url.?confirm=yes, for no js compatibility use $url for fallback confirm. + * 'title' => '', // Overide title of modal, if empty default title use "ConfirmBtnCommonTitle" lang key + * 'action-btn-label' => '', // Overide label of action button, if empty default label use "Confirm" lang key + * 'cancel-btn-label' => '', // Overide label of cancel button, if empty default label use "CloseDialog" lang key + * 'content' => '', // Overide text of content, if empty default content use "ConfirmBtnCommonContent" lang key + * 'modal' => true, // true|false to display dialog as a modal (with dark background) + * ], + * ] + * // phpcs:enable * @return string html button */ function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = '', $id = '', $userRight = 1, $params = array()) From cd5e1d603e8dc26e312dc1d186298749537a847f Mon Sep 17 00:00:00 2001 From: Alexis LAURIER Date: Wed, 14 Jul 2021 12:02:03 +0200 Subject: [PATCH 41/58] fix showInputField checkbox and radio type --- htdocs/core/class/commonobject.class.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 9e6204bd364..a726987c607 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -5898,7 +5898,10 @@ abstract class CommonObject $type = 'varchar'; } elseif (is_array($this->fields[$key]['arrayofkeyval'])) { $param['options'] = $this->fields[$key]['arrayofkeyval']; - $type = 'select'; + $type = $this->fields[$key]['type']; + if(!in_array($type, array('select', 'checkbox', 'radio'))) { + $type = 'select'; + } } else { $param['options'] = array(); $type = $this->fields[$key]['type']; From 7406f2cc85a109e875bf2f81c45ab6f14032cdf2 Mon Sep 17 00:00:00 2001 From: BENKE Charlene <1179011+defrance@users.noreply.github.com> Date: Wed, 14 Jul 2021 12:55:33 +0200 Subject: [PATCH 42/58] a interventional drafts on commercial index --- htdocs/comm/index.php | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/htdocs/comm/index.php b/htdocs/comm/index.php index 9d0d9f1befc..609e43ff765 100644 --- a/htdocs/comm/index.php +++ b/htdocs/comm/index.php @@ -497,6 +497,50 @@ if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SU } } + +/* + * Draft interventionals + */ +if (!empty($conf->ficheinter->enabled)) { + $sql = "SELECT f.rowid, f.ref, s.nom as name, s.rowid as socid"; + $sql .= " FROM ".MAIN_DB_PREFIX."fichinter as f"; + $sql .= ", ".MAIN_DB_PREFIX."societe as s"; + if (!$user->rights->societe->client->voir && !$socid) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + } + $sql .= " WHERE f.entity IN (".getEntity('intervention').")"; + $sql .= " AND f.fk_soc = s.rowid"; + $sql .= " AND f.fk_statut = 0"; + if ($socid) { + $sql .= " AND f.fk_soc = ".$socid; + } + if (!$user->rights->societe->client->voir && !$socid) { + $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; + } + + $resql = $db->query($sql); + if ($resql) { + print '
'; + print '
'; print $langs->trans('DateInvoice'); @@ -1352,11 +1383,11 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) { break; } - print '
'; @@ -1480,9 +1511,13 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) { // Value spent if (!empty($arrayfields['value']['checked'])) { + $langs->load("salaries"); + print ''; $value = price2num($task_time->thm * $task_time->task_duration / 3600, 'MT', 1); + print 'thm).'">'; print price($value, 1, $langs, 1, -1, -1, $conf->currency); + print ''; print ''.price($obj->total_ht).''.price($obj->total_ht).''.price($obj->total_ttc).''.dol_print_date($db->jdate($obj->tms), 'day').'
'; + print ''; + print ''; + $langs->load("fichinter"); + $num = $db->num_rows($resql); + if ($num) { + $i = 0; + while ($i < $num) { + $obj = $db->fetch_object($resql); + print ''; + print '"; + print ''; + $i++; + } + } + print "
'.$langs->trans("DraftFichinter").'
'; + print "rowid."\">".img_object($langs->trans("ShowFichinter"), "intervention").' '.$obj->ref."'.img_object($langs->trans("ShowCompany"), "company").' '.dol_trunc($obj->name, 24).'
"; + } +} + print '
'; print '
'; From 0fd980b00593d1dacf234545e9cbbb44c0a15258 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 14 Jul 2021 13:57:17 +0200 Subject: [PATCH 43/58] Update index.php --- htdocs/comm/index.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/index.php b/htdocs/comm/index.php index 609e43ff765..11accdb3f0a 100644 --- a/htdocs/comm/index.php +++ b/htdocs/comm/index.php @@ -512,10 +512,10 @@ if (!empty($conf->ficheinter->enabled)) { $sql .= " AND f.fk_soc = s.rowid"; $sql .= " AND f.fk_statut = 0"; if ($socid) { - $sql .= " AND f.fk_soc = ".$socid; + $sql .= " AND f.fk_soc = ".((int) $socid); } if (!$user->rights->societe->client->voir && !$socid) { - $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$user->id; + $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id); } $resql = $db->query($sql); From b2425c2a9d2d91ffa0e796e11920c7257a7b367e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 14 Jul 2021 14:04:44 +0200 Subject: [PATCH 44/58] Update paymentok.php --- htdocs/public/payment/paymentok.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/public/payment/paymentok.php b/htdocs/public/payment/paymentok.php index 5bb3f4de0fc..f5d1e60a3fc 100644 --- a/htdocs/public/payment/paymentok.php +++ b/htdocs/public/payment/paymentok.php @@ -833,7 +833,7 @@ if ($ispaymentok) { $currencyCodeType = $_SESSION['currencyCodeType']; // Do action only if $FinalPaymentAmt is set (session variable is cleaned after this page to avoid duplicate actions when page is POST a second time) - if (!empty($conf->banque->enabled)) { + if (!empty($conf->facture->enabled)) { if (!empty($FinalPaymentAmt) && $paymentTypeId > 0 ) { include_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; $invoice = new Facture($db); From b552c6b4fe012d64511875795c837e8e9eda707d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 14 Jul 2021 14:32:05 +0200 Subject: [PATCH 45/58] Fix status color --- htdocs/compta/facture/list.php | 2 +- htdocs/holiday/class/holiday.class.php | 8 ++++++-- htdocs/holiday/list.php | 3 ++- htdocs/langs/en_US/main.lang | 1 + 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index cc52984d6d4..f25b2b05975 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -1043,7 +1043,7 @@ if ($resql) { $moreforfilter .= img_picto($tmptitle, 'user', 'class="pictofixedwidth"').$form->select_dolusers($search_user, 'search_user', $tmptitle, '', 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth250'); $moreforfilter .= '
'; } - // If the user can view prospects other than his' + // Filter on product tags if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire && ($user->rights->produit->lire || $user->rights->service->lire)) { include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; $moreforfilter .= '
'; diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index 2b0641ff9ae..82229198185 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -1251,6 +1251,8 @@ class Holiday extends CommonObject public function LibStatut($status, $mode = 0, $startdate = '') { // phpcs:enable + global $langs; + if (empty($this->labelStatus) || empty($this->labelStatusShort)) { global $langs; //$langs->load("mymodule"); @@ -1266,9 +1268,11 @@ class Holiday extends CommonObject $this->labelStatusShort[self::STATUS_REFUSED] = $langs->trans('RefuseCP'); } + $params = array(); $statusType = 'status6'; - if (!empty($startdate) && $startdate > dol_now()) { + if (!empty($startdate) && $startdate >= dol_now()) { // If not yet passed, we use a green "in live" color $statusType = 'status4'; + $params = array('tooltip'=>$this->labelStatus[$status].' - '.$langs->trans("Forthcoming")); } if ($status == self::STATUS_DRAFT) { $statusType = 'status0'; @@ -1283,7 +1287,7 @@ class Holiday extends CommonObject $statusType = 'status5'; } - return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); + return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode, '', $params); } diff --git a/htdocs/holiday/list.php b/htdocs/holiday/list.php index ece1f9c9ec7..ab57a497e8e 100644 --- a/htdocs/holiday/list.php +++ b/htdocs/holiday/list.php @@ -730,6 +730,7 @@ if ($resql) { $holidaystatic->id = $obj->rowid; $holidaystatic->ref = ($obj->ref ? $obj->ref : $obj->rowid); $holidaystatic->statut = $obj->status; + $holidaystatic->date_debut = $db->jdate($obj->date_debut); // User $userstatic->id = $obj->fk_user; @@ -790,7 +791,7 @@ if ($resql) { } if (!empty($arrayfields['duration']['checked'])) { print ''; - $nbopenedday = num_open_day($db->jdate($obj->date_debut, 1), $db->jdate($obj->date_fin, 1), 0, 1, $obj->halfday); + $nbopenedday = num_open_day($db->jdate($obj->date_debut, 1), $db->jdate($obj->date_fin, 1), 0, 1, $obj->halfday); // user jdate(..., 1) because num_open_day need UTC dates print $nbopenedday.' '.$langs->trans('DurationDays'); print ''; if (!$i) { diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 863b94af564..94c851bf346 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -1137,3 +1137,4 @@ CopiedToClipboard=Copied to clipboard InformationOnLinkToContract=This amount is only the total of all the lines of the contract. No notion of time is taken into consideration. ConfirmCancel=Are you sure you want to cancel EmailMsgID=Email MsgID +Forthcoming=Forthcoming \ No newline at end of file From a773652c04e4158ab9661e48db7fac0b97106dcd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 14 Jul 2021 14:37:07 +0200 Subject: [PATCH 46/58] Fix phpcs --- htdocs/core/class/commonobject.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 51254bede5d..d050af4883a 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -5918,8 +5918,10 @@ abstract class CommonObject } elseif (is_array($this->fields[$key]['arrayofkeyval'])) { $param['options'] = $this->fields[$key]['arrayofkeyval']; $type = $this->fields[$key]['type']; - if(!in_array($type, array('select', 'checkbox', 'radio'))) { + if (!in_array($type, array('select', 'checkbox', 'radio'))) { $type = 'select'; + } else { + $type = $this->fields[$key]['type']; } } else { $param['options'] = array(); From 901a158238d9e7071f1981f3ea77596eaa743894 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 14 Jul 2021 17:19:43 +0200 Subject: [PATCH 47/58] Fix backward compatibility --- htdocs/societe/class/societe.class.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index eff2ba39c21..422a3f118d8 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1280,7 +1280,8 @@ class Societe extends CommonObject $this->get_codefournisseur($this, 1); } - $this->code_compta = trim($this->code_compta); + $this->code_compta_client = trim(empty($this->code_compta) ? $this->code_compta_client : $this->code_compta); + $this->code_compta = $this->code_compta_client; // for backward compatbility $this->code_compta_fournisseur = trim($this->code_compta_fournisseur); // Check parameters. More tests are done later in the ->verify() @@ -1292,8 +1293,8 @@ class Societe extends CommonObject $customer = false; if (!empty($allowmodcodeclient) && !empty($this->client)) { - // Attention get_codecompta peut modifier le code suivant le module utilise - if (empty($this->code_compta)) { + // If $allowmodcodeclient is set and value is not set, we generate it + if (empty($this->code_compta_client)) { $ret = $this->get_codecompta('customer'); if ($ret < 0) { return -1; @@ -1305,8 +1306,8 @@ class Societe extends CommonObject $supplier = false; if (!empty($allowmodcodefournisseur) && !empty($this->fournisseur)) { - // Attention get_codecompta peut modifier le code suivant le module utilise - if ($this->code_compta_fournisseur == "") { + // If $allowmodcodefournisseur is set and value is not set, we generate it + if (empty($this->code_compta_fournisseur)) { $ret = $this->get_codecompta('supplier'); if ($ret < 0) { return -1; @@ -1460,7 +1461,7 @@ class Societe extends CommonObject if ($customer) { $sql .= ", code_client = ".(!empty($this->code_client) ? "'".$this->db->escape($this->code_client)."'" : "null"); - $sql .= ", code_compta = ".(!empty($this->code_compta) ? "'".$this->db->escape($this->code_compta)."'" : "null"); + $sql .= ", code_compta = ".(!empty($this->code_compta_client) ? "'".$this->db->escape($this->code_compta_client)."'" : "null"); } if ($supplier) { @@ -3311,7 +3312,8 @@ class Societe extends CommonObject $result = $mod->get_code($this->db, $this, $type); if ($type == 'customer') { - $this->code_compta = $mod->code; + $this->code_compta_client = $mod->code; + $this->code_compta = $this->code_compta_client; // For backward compatibility } elseif ($type == 'supplier') { $this->code_compta_fournisseur = $mod->code; } @@ -3323,6 +3325,7 @@ class Societe extends CommonObject } } else { if ($type == 'customer') { + $this->code_compta_client = ''; $this->code_compta = ''; } elseif ($type == 'supplier') { $this->code_compta_fournisseur = ''; From 83d931f3c740f88b1e15e09f3ccb87b76959fb4e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 14 Jul 2021 17:40:36 +0200 Subject: [PATCH 48/58] FIX #18143 --- htdocs/core/lib/functions.lib.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index a53162b7f2c..6e259e3c7fb 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -6828,6 +6828,8 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray = array_merge($substitutionarray, array( '__MYCOMPANY_NAME__' => $mysoc->name, '__MYCOMPANY_EMAIL__' => $mysoc->email, + '__MYCOMPANY_PHONE__' => $mysoc->phone, + '__MYCOMPANY_FAX__' => $mysoc->fax, '__MYCOMPANY_PROFID1__' => $mysoc->idprof1, '__MYCOMPANY_PROFID2__' => $mysoc->idprof2, '__MYCOMPANY_PROFID3__' => $mysoc->idprof3, From 5da40d80f71b2a00fba9b4e8c86c2f12b3e889e9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 15 Jul 2021 16:35:06 +0200 Subject: [PATCH 49/58] Fix css --- htdocs/core/class/commonobject.class.php | 2 +- htdocs/societe/project.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index b3ae722a5d3..e372e2211b3 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7492,7 +7492,7 @@ abstract class CommonObject if ($display_type == 'card') { $out .= ''; - if ( ! empty($conf->global->MAIN_VIEW_LINE_NUMBER) ) { + if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER) && $action == 'view') { $out .= ''; } $out .= 'id.'&backtopage='.urlencode($backtopage), '', 1, $params); + $newcardbutton = dolGetButtonTitle($langs->trans("NewProject"), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/projet/card.php?action=create&socid='.$object->id.'&backtopageforcancel='.urlencode($backtopage), '', 1, $params); print '
'; From 9aad07f20c3ce870692b4416b57a25cc4af35dad Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 15 Jul 2021 21:57:32 +0200 Subject: [PATCH 50/58] Remove log --- htdocs/core/class/commonobject.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index e372e2211b3..cd1810ed06c 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -8532,7 +8532,6 @@ abstract class CommonObject // Retrieve all extrafield // fetch optionals attributes and labels $this->fetch_optionals(); - dol_syslog("aaa=".$this->id); return $this->id; } else { From 0aeeb62628220517a719330bee78916193b9578d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 15 Jul 2021 22:29:03 +0200 Subject: [PATCH 51/58] More log on imap card --- htdocs/admin/emailcollector_card.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index 4e2c9e34bf9..fdc0b893087 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -103,6 +103,7 @@ $debuginfo = ''; $parameters = array(); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); } @@ -239,7 +240,6 @@ if ($action == 'confirm_collect') { - /* * View */ @@ -434,6 +434,14 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $connectstringtarget = $connectstringserver.$object->getEncodedUtf7($targetdir); } + $timeoutconnect = empty($conf->global->MAIN_USE_CONNECT_TIMEOUT) ? 10 : $conf->global->MAIN_USE_CONNECT_TIMEOUT; + $timeoutread = empty($conf->global->MAIN_USE_RESPONSE_TIMEOUT) ? 30 : $conf->global->MAIN_USE_RESPONSE_TIMEOUT; + + dol_syslog("imap_open connectstring=".$connectstringsource." login=".$object->login." password=".$object->password." timeoutconnect=".$timeoutconnect." timeoutread=".$timeoutread); + + imap_timeout(IMAP_OPENTIMEOUT, $timeoutconnect); + imap_timeout(IMAP_READTIMEOUT, $timeoutread); + $connection = imap_open($connectstringsource, $object->login, $object->password); } catch (Exception $e) { print $e->getMessage(); @@ -449,12 +457,15 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if (function_exists('imap_last_error')) { $morehtml .= '
'.imap_last_error(); } + dol_syslog("Error ".$morehtml, LOG_WARNING); //var_dump(imap_errors()) } else { + dol_syslog("Imap connected. Now we call imap_num_msg()"); $morehtml .= imap_num_msg($connection); } if ($connection) { + dol_syslog("Imap close"); imap_close($connection); } From 1e93a3f8f42a69246cfc1b509a41d1342553c2d8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 15 Jul 2021 22:29:03 +0200 Subject: [PATCH 52/58] More log on imap card --- htdocs/admin/emailcollector_card.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index 4e2c9e34bf9..fdc0b893087 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -103,6 +103,7 @@ $debuginfo = ''; $parameters = array(); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); } @@ -239,7 +240,6 @@ if ($action == 'confirm_collect') { - /* * View */ @@ -434,6 +434,14 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $connectstringtarget = $connectstringserver.$object->getEncodedUtf7($targetdir); } + $timeoutconnect = empty($conf->global->MAIN_USE_CONNECT_TIMEOUT) ? 10 : $conf->global->MAIN_USE_CONNECT_TIMEOUT; + $timeoutread = empty($conf->global->MAIN_USE_RESPONSE_TIMEOUT) ? 30 : $conf->global->MAIN_USE_RESPONSE_TIMEOUT; + + dol_syslog("imap_open connectstring=".$connectstringsource." login=".$object->login." password=".$object->password." timeoutconnect=".$timeoutconnect." timeoutread=".$timeoutread); + + imap_timeout(IMAP_OPENTIMEOUT, $timeoutconnect); + imap_timeout(IMAP_READTIMEOUT, $timeoutread); + $connection = imap_open($connectstringsource, $object->login, $object->password); } catch (Exception $e) { print $e->getMessage(); @@ -449,12 +457,15 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea if (function_exists('imap_last_error')) { $morehtml .= '
'.imap_last_error(); } + dol_syslog("Error ".$morehtml, LOG_WARNING); //var_dump(imap_errors()) } else { + dol_syslog("Imap connected. Now we call imap_num_msg()"); $morehtml .= imap_num_msg($connection); } if ($connection) { + dol_syslog("Imap close"); imap_close($connection); } From 0637ef781f0116810bce288e9d02bfd873fbe3f6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 15 Jul 2021 23:03:24 +0200 Subject: [PATCH 53/58] Add samples for imap functions test --- test/phpunit/imap_header.txt | 75 +++++++++++++++++++++++++++++++++ test/phpunit/imap_htmlmsg.txt | 1 + test/phpunit/imap_plaintext.txt | 1 + 3 files changed, 77 insertions(+) create mode 100644 test/phpunit/imap_header.txt create mode 100644 test/phpunit/imap_htmlmsg.txt create mode 100644 test/phpunit/imap_plaintext.txt diff --git a/test/phpunit/imap_header.txt b/test/phpunit/imap_header.txt new file mode 100644 index 00000000000..5891c66a3da --- /dev/null +++ b/test/phpunit/imap_header.txt @@ -0,0 +1,75 @@ +Delivered-To: testldrdev@gmail.com +Received: by 2002:ab3:5782:0:0:0:0:0 with SMTP id e2csp698208ltc; Thu, 15 Jul + 2021 13:49:41 -0700 (PDT) +X-Received: by 2002:a63:eb51:: with SMTP id b17mr490127pgk.288.1626382180943; + Thu, 15 Jul 2021 13:49:40 -0700 (PDT) +ARC-Seal: i=1; a=rsa-sha256; t=1626382180; cv=none; d=google.com; + s=arc-20160816; + b=rEpZkUN9MvFJ+8ckMD+urx6epAp5zUAICUiJjTY9yAAwmp54gZ9XYu/qoVgqVe5rAU + oayiqojPUzHArxaIlmftWyK4kF6ErAQxMZocn944kHeCGOigIB2y+u+ij3Ip4Vg6PW62 + 4cATlnRoDTpnckwrXHnOonzSEHunE2smZgtujdNJ/1p/vbmhByQl3Kg71NzCLzdE3nr6 + PYQNl/XbTL4BUpKBsbPCbJDNeNOqu/FHBI3R7Nfoy+HDY9LR+aYBR4N6jBQMKyKM32JJ + 2yrN9ky6N1n2xfvD4lnbqDyqvgWjmTGP+Dk+UAUeAj3YsS/hM2z41UA9xicPoC/B+Wft XWPQ== +ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; + s=arc-20160816; h=to:from:subject:message-id:feedback-id:date:mime-version + :dkim-signature; bh=jzUFV8bCmEmAeTpb8amH8O1QwkNos0xYlYqLtpP6SBc=; + b=cLnW/O5/vTbct4uiVIanDpvITsoy5pp8c0Cy3ZKppY1t2U0bCaedhyI9LkbwXU0ytU + i+qgnSrwydhnvY8Yy13KDUkVtjU9dxmQ/YDYBsLjS7WeFEy9OQkIqCR1czmUoUSEPbgr + d/tsVEPg/LwHW74WuG6vUVRidF9XBBQqQHR7ADCvo4DQKRURzpeDF4ggDceiWfhpYjbZ + Un//GKujM5WGfV7kkqfprw5UsVG8+pjbKdnTwsCKJ3htju9eYXANf4Odn/kjA5OjP3l3 + fuqCeus0fSyUw9T4DLe4knRxReOL+MfjQc65ATjFlOfl/9/CPauSFkmPrGKeUHi7m2bA rVCQ== +ARC-Authentication-Results: i=1; mx.google.com; dkim=pass + header.i=@accounts.google.com header.s=20161025 header.b=XOpeYXK3; spf=pass + (google.com: domain of + 3zj_wyagtcnmef-ivgcprttflekj.xffxcv.tfdkvjkcuiuvmxdrzc.tfd@gaia.bounces.google.com + designates 209.85.220.73 as permitted sender) + smtp.mailfrom=3ZJ_wYAgTCnMef-iVgcpRTTflekj.XffXcV.TfdkVjkcUiUVmXdRZc.Tfd@gaia.bounces.google.com; + dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=accounts.google.com +Return-Path: <3ZJ_wYAgTCnMef-iVgcpRTTflekj.XffXcV.TfdkVjkcUiUVmXdRZc.Tfd@gaia.bounces.google.com> +Received: from mail-sor-f73.google.com (mail-sor-f73.google.com. + [209.85.220.73]) by mx.google.com with SMTPS id + m24sor3147147pls.67.2021.07.15.13.49.40 for (Google + Transport Security); Thu, 15 Jul 2021 13:49:40 -0700 (PDT) +Received-SPF: pass (google.com: domain of + 3zj_wyagtcnmef-ivgcprttflekj.xffxcv.tfdkvjkcuiuvmxdrzc.tfd@gaia.bounces.google.com + designates 209.85.220.73 as permitted sender) client-ip=209.85.220.73; +Authentication-Results: mx.google.com; dkim=pass header.i=@accounts.google.com + header.s=20161025 header.b=XOpeYXK3; spf=pass (google.com: domain of + 3zj_wyagtcnmef-ivgcprttflekj.xffxcv.tfdkvjkcuiuvmxdrzc.tfd@gaia.bounces.google.com + designates 209.85.220.73 as permitted sender) + smtp.mailfrom=3ZJ_wYAgTCnMef-iVgcpRTTflekj.XffXcV.TfdkVjkcUiUVmXdRZc.Tfd@gaia.bounces.google.com; + dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=accounts.google.com +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=accounts.google.com; + s=20161025; h=mime-version:date:feedback-id:message-id:subject:from:to; + bh=jzUFV8bCmEmAeTpb8amH8O1QwkNos0xYlYqLtpP6SBc=; + b=XOpeYXK3QbrfDh9/pqAG7UruMxyCVah4Lj5tfBPHRh8C6AvzStTVsgRTFzPGuxB9cq + XRneLOf3kYKud2kkKMNShaG+/t65suM2MTo3q81Qvt9N6n8motuXmnLnNM7kVCaXM//s + BxZjiL4nXdjrQBF0N7wcns7xFS+J9pKZbfbm0BaUV32Kb7ef63PQHwhE+au4ytUynBqj + hxfA977RfwEXbFmUInVRJ6IJhMoygnx/Y10AccV0TuuLtnNKJIsPFv04SJcOclwaNJ3H + 69GSdpRSNJyqn7Rzm4va6l4Lxhjfjzm7+IVzMx717A5e8dLiLjxftCRS1F6EXTeYUvQ+ QcUQ== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; + s=20161025; + h=x-gm-message-state:mime-version:date:feedback-id:message-id:subject + :from:to; bh=jzUFV8bCmEmAeTpb8amH8O1QwkNos0xYlYqLtpP6SBc=; + b=uWWatGm2u/TYFa5pXhZCPJ59bmYVNEj9qv3Z5wiotMZ7pWc9mR0LYGgD99IjNs7E0G + hhv+GwtrMGft69VPG4GyUbmd7pm27G+ykFu2kLfB5lTRhZNjaqeLLkIS4KgbTlAsJJ7q + UNrIvPgpAksxnY79qtneThZOTI4o0s+V94A5T5p3/PN99YXq22RxE/aHCIpMIj/NyJeJ + RUGdEaiAjQXuG70ekiFAy2cePOI+WCFZEfYmq6vAJO4y285ID/ovjv4cpFIqTu3QFb/u + gdZFQriVXnKyZryLbjN1PlpK0772vsatNh5jC8GgOsJjSqJmZLNR5urtUlnRmTaJ8hoV F3lA== +X-Gm-Message-State: AOAM5338zSEHryX6TtcvwcYlbrnaMvleKLH9RhoGJaqMLvXSPlD7sWEt + pW5IuEivfKUIAHzbl8HeQWtM86OUvsPb26Z/ddNWtw== +X-Google-Smtp-Source: ABdhPJxfD6pBcAwUGMIoqNyPu3KT+9RON4ujFwzRhm3eCKUYxpRR+2hPoCLgdMzCE1TnOL7ShV3hLBEBAQzFtzZ6ue8glg== +MIME-Version: 1.0 +X-Received: by 2002:a17:902:ed82:b029:ef:48c8:128e with SMTP id + e2-20020a170902ed82b02900ef48c8128emr4950093plj.72.1626382180494; Thu, 15 Jul + 2021 13:49:40 -0700 (PDT) +Date: Thu, 15 Jul 2021 20:49:40 GMT +X-Account-Notification-Type: 46-anexp#nret-fa +Feedback-ID: 46-anexp#nret-fa:account-notifier +X-Notifications: 56c00ab9d6600000 +X-Notifications-Bounce-Info: ARgXy4C6Xm7P0JA65M5w_0EB-KbSHnYA8DuTVsZzaMJT7AktG4DWNKZC7qYb4FkrhakLBYzS11Hsoc4qaJocq__FbWMZwTVOmo9d1gWCxx2JMJOgcGQxMKdQ_UVnkuDZugVRr6nih0prpV8OI7Y0ijFI5KVo1M_9f-HXojR-v_jydOpt3lpHGJ-AIQ +Message-ID: +Subject: =?UTF-8?B?QWxlcnRlIGRlIHPDqWN1cml0w6k=?= +From: Google +To: testldrdev@gmail.com +Content-Type: multipart/alternative; boundary="000000000000232f0005c72f9c4b" diff --git a/test/phpunit/imap_htmlmsg.txt b/test/phpunit/imap_htmlmsg.txt new file mode 100644 index 00000000000..fe6eb0de8d3 --- /dev/null +++ b/test/phpunit/imap_htmlmsg.txt @@ -0,0 +1 @@ +
Clé de sécurité ajoutée pour la validation en deux étapes
testldrdev@gmail.com
Si vous n'avez pas ajouté de clé de sécurité, quelqu'un utilise peut-être votre compte. Vérifiez et sécurisez votre compte dès maintenant.
Vous pouvez aussi voir l'activité liée à la sécurité de votre compte ici :
https://myaccount.google.com/notifications
Cet e-mail vous a été envoyé pour vous informer de modifications importantes apportées à votre compte et aux services Google que vous utilisez.


\ No newline at end of file diff --git a/test/phpunit/imap_plaintext.txt b/test/phpunit/imap_plaintext.txt new file mode 100644 index 00000000000..33d44eb847c --- /dev/null +++ b/test/phpunit/imap_plaintext.txt @@ -0,0 +1 @@ +[image: Google] Clé de sécurité ajoutée pour la validation en deux étapes testldrdev@gmail.com Si vous n'avez pas ajouté de clé de sécurité, quelqu'un utilise peut-être votre compte. Vérifiez et sécurisez votre compte dès maintenant. Consulter l'activité Vous pouvez aussi voir l'activité liée à la sécurité de votre compte ici : https://myaccount.google.com/notifications Cet e-mail vous a été envoyé pour vous informer de modifications importantes apportées à votre compte et aux services Google que vous utilisez. © 2021 Google Ireland Ltd., Gordon House, Barrow Street, Dublin 4, Ireland \ No newline at end of file From ce27feda84e75c916980bf58ef20eab7433b20c6 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 16 Jul 2021 00:05:00 +0200 Subject: [PATCH 54/58] Debug v14 Fix email collector (Creation of thirparty, set of extrafields) --- htdocs/core/class/commonobject.class.php | 4 +- .../class/emailcollector.class.php | 63 +++++++++++++------ htdocs/langs/en_US/admin.lang | 2 +- htdocs/societe/class/societe.class.php | 31 +-------- 4 files changed, 48 insertions(+), 52 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index cd1810ed06c..ceac7015065 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -6521,11 +6521,11 @@ abstract class CommonObject } elseif (in_array($type, array('int', 'integer'))) { $tmp = explode(',', $size); $newsize = $tmp[0]; - $out = ''; + $out = ' 0 ? ' maxlength="'.$newsize.'"' : '').' value="'.dol_escape_htmltag($value).'"'.($moreparam ? $moreparam : '').($autofocusoncreate ? ' autofocus' : '').'>'; } elseif (in_array($type, array('real'))) { $out = ''; } elseif (preg_match('/varchar/', $type)) { - $out = ''; + $out = ' 0 ? ' maxlength="'.$size.'"' : '').' value="'.dol_escape_htmltag($value).'"'.($moreparam ? $moreparam : '').($autofocusoncreate ? ' autofocus' : '').'>'; } elseif (in_array($type, array('mail', 'phone', 'url'))) { $out = ''; } elseif (preg_match('/^text/', $type)) { diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index 0b45db6a808..16df7774470 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -324,6 +324,9 @@ class EmailCollector extends CommonObject // Clear fields $object->ref = "copy_of_".$object->ref; $object->title = $langs->trans("CopyOf")." ".$object->title; + if (empty($object->host)) { + $object->host = 'imap.example.com'; + } // ... // Clear extrafields that are unique if (is_array($object->array_options) && count($object->array_options) > 0) { @@ -849,11 +852,11 @@ class EmailCollector extends CommonObject $regexstring = ''; //$transformationstring=''; $regforregex = array(); - if (preg_match('/^EXTRACT:([a-zA-Z0-9]+):(.*):([^:])$/', $valueforproperty, $regforregex)) { + if (preg_match('/^EXTRACT:([a-zA-Z0-9_]+):(.*):([^:])$/', $valueforproperty, $regforregex)) { $sourcefield = $regforregex[1]; $regexstring = $regforregex[2]; //$transofrmationstring=$regforregex[3]; - } elseif (preg_match('/^EXTRACT:([a-zA-Z0-9]+):(.*)$/', $valueforproperty, $regforregex)) { + } elseif (preg_match('/^EXTRACT:([a-zA-Z0-9_]+):(.*)$/', $valueforproperty, $regforregex)) { $sourcefield = $regforregex[1]; $regexstring = $regforregex[2]; } @@ -1199,15 +1202,20 @@ class EmailCollector extends CommonObject $iforemailloop = 0; foreach ($arrayofemail as $imapemail) { if ($nbemailprocessed > 1000) { - break; // Do not process more than 1000 email per launch (this is a different protection than maxnbcollectedpercollect + break; // Do not process more than 1000 email per launch (this is a different protection than maxnbcollectedpercollect) } $iforemailloop++; + // GET header and overview datas + $header = imap_fetchheader($connection, $imapemail, 0); + $overview = imap_fetch_overview($connection, $imapemail, 0); + + /* print $header; var_dump($overview); */ + + // Process $header of email $header = preg_replace('/\r\n\s+/m', ' ', $header); // When a header line is on several lines, merge lines - /*print $header; - print $header;*/ $matches = array(); preg_match_all('/([^: ]+): (.+?(?:\r\n\s(?:.+?))*)\r\n/m', $header, $matches); @@ -1297,9 +1305,6 @@ class EmailCollector extends CommonObject $this->db->begin(); - // GET Email meta datas - $overview = imap_fetch_overview($connection, $imapemail, 0); - dol_syslog("msgid=".$overview[0]->message_id." date=".dol_print_date($overview[0]->udate, 'dayrfc', 'gmt')." from=".$overview[0]->from." to=".$overview[0]->to." subject=".$overview[0]->subject); $overview[0]->subject = $this->decodeSMTPSubject($overview[0]->subject); @@ -1309,10 +1314,14 @@ class EmailCollector extends CommonObject // Removed emojis $overview[0]->subject = preg_replace('/[\x{10000}-\x{10FFFF}]/u', "\xEF\xBF\xBD", $overview[0]->subject); - // Parse IMAP email structure + // GET IMAP email structure/content + global $htmlmsg, $plainmsg, $charset, $attachments; + $this->getmsg($connection, $imapemail); + //print $plainmsg; var_dump($plainmsg); exit; + //$htmlmsg,$plainmsg,$charset,$attachments $messagetext = $plainmsg ? $plainmsg : dol_string_nohtmltag($htmlmsg, 0); // Removed emojis @@ -1640,13 +1649,15 @@ class EmailCollector extends CommonObject if ($operation['type'] == 'loadthirdparty' || $operation['type'] == 'loadandcreatethirdparty') { if (empty($operation['actionparam'])) { $errorforactions++; - $this->error = "Action loadthirdparty or loadandcreatethirdparty has empty parameter. Must be a rule like 'SET:xxx' or 'EXTRACT:(body|subject):regex' to define how to set or extract data"; + $this->error = "Action loadthirdparty or loadandcreatethirdparty has empty parameter. Must be a rule like 'name=HEADER:^From:(.*);' or 'name=SET:xxx' or 'name=EXTRACT:(body|subject):regex where 'name' can be replaced with 'id' or 'email' to define how to set or extract data. More properties can also be set, for example client=SET:2;"; $this->errors[] = $this->error; } else { $actionparam = $operation['actionparam']; + $idtouseforthirdparty = ''; $nametouseforthirdparty = ''; + $emailtouseforthirdparty = ''; - // $this->actionparam = 'SET:aaa' or 'EXTRACT:BODY:....' + // $actionparam = 'param=SET:aaa' or 'param=EXTRACT:BODY:....' $arrayvaluetouse = dolExplodeIntoArray($actionparam, ';', '='); foreach ($arrayvaluetouse as $propertytooverwrite => $valueforproperty) { $sourcestring = ''; @@ -1654,7 +1665,7 @@ class EmailCollector extends CommonObject $regexstring = ''; $regforregex = array(); - if (preg_match('/^EXTRACT:([a-zA-Z0-9]+):(.*)$/', $valueforproperty, $regforregex)) { + if (preg_match('/^EXTRACT:([a-zA-Z0-9_]+):(.*)$/', $valueforproperty, $regforregex)) { $sourcefield = $regforregex[1]; $regexstring = $regforregex[2]; } @@ -1674,10 +1685,18 @@ class EmailCollector extends CommonObject if (preg_match('/'.$regexstring.'/ms', $sourcestring, $regforval)) { //var_dump($regforval[count($regforval)-1]);exit; // Overwrite param $tmpproperty - $nametouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; + if ($propertytooverwrite == 'id') { + $idtouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; + } elseif ($propertytooverwrite == 'email') { + $emailtouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; + } else { + $nametouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; + } } else { // Regex not found + $idtouseforthirdparty = null; $nametouseforthirdparty = null; + $emailtouseforthirdparty = null; } //var_dump($object->$tmpproperty);exit; } else { @@ -1689,7 +1708,13 @@ class EmailCollector extends CommonObject } elseif (preg_match('/^(SET|SETIFEMPTY):(.*)$/', $valueforproperty, $reg)) { //if (preg_match('/^options_/', $tmpproperty)) $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $reg[1]; //else $object->$tmpproperty = $reg[1]; - $nametouseforthirdparty = $reg[2]; + if ($propertytooverwrite == 'id') { + $idtouseforthirdparty = $reg[2]; + } elseif ($propertytooverwrite == 'email') { + $emailtouseforthirdparty = $reg[2]; + } else { + $nametouseforthirdparty = $reg[2]; + } } else { $errorforactions++; $this->error = 'Bad syntax for description of action parameters: '.$actionparam; @@ -1698,8 +1723,8 @@ class EmailCollector extends CommonObject } } - if (!$errorforactions && $nametouseforthirdparty) { - $result = $thirdpartystatic->fetch(0, $nametouseforthirdparty); + if (!$errorforactions && ($idtouseforthirdparty || $emailtouseforthirdparty || $nametouseforthirdparty)) { + $result = $thirdpartystatic->fetch($idtouseforthirdparty, $nametouseforthirdparty, '', '', '', '', '', '', '', '', $emailtouseforthirdparty); if ($result < 0) { $errorforactions++; $this->error = 'Error when getting thirdparty with name '.$nametouseforthirdparty.' (may be 2 record exists with same name ?)'; @@ -1707,20 +1732,20 @@ class EmailCollector extends CommonObject break; } elseif ($result == 0) { if ($operation['type'] == 'loadthirdparty') { - dol_syslog("Third party with name ".$nametouseforthirdparty." was not found"); + dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." was not found"); $errorforactions++; $this->error = 'ErrorFailedToLoadThirdParty'; $this->errors[] = 'ErrorFailedToLoadThirdParty'; } elseif ($operation['type'] == 'loadandcreatethirdparty') { - dol_syslog("Third party with name ".$nametouseforthirdparty." was not found. We try to create it."); + dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." was not found. We try to create it."); // Create thirdparty $thirdpartystatic->name = $nametouseforthirdparty; if ($fromtext != $nametouseforthirdparty) { $thirdpartystatic->name_alias = $fromtext; } - $thirdpartystatic->email = $from; + $thirdpartystatic->email = ($emailtouseforthirdparty ? $emailtouseforthirdparty : $from); // Overwrite values with values extracted from source email $errorforthisaction = $this->overwritePropertiesOfObject($thirdpartystatic, $operation['actionparam'], $messagetext, $subject, $header); diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 7af07369759..aca631eef99 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2090,7 +2090,7 @@ LargerThan=Larger than IfTrackingIDFoundEventWillBeLinked=Note that If a tracking ID of an object is found into email, or if the email is an answer of an email aready collected and linked to an object, the created event will be automatically linked to the known related object. WithGMailYouCanCreateADedicatedPassword=With a GMail account, if you enabled the 2 steps validation, it is recommanded to create a dedicated second password for the application instead of using your own account passsword from https://myaccount.google.com/. EmailCollectorTargetDir=It may be a desired behaviour to move the email into another tag/directory when it was processed successfully. Just set name of directory here to use this feature (Do NOT use special characters in name). Note that you must also use a read/write login account. -EmailCollectorLoadThirdPartyHelp=You can use this action to use the email content to find and load an existing thirdparty in your database. The found (or created) thirdparty will be used for following actions that need it. In the parameter field you can use for example 'EXTRACT:BODY:Name:\s([^\s]*)' if you want to extract the name of the thirdparty from a string 'Name: name to find' found into the body. +EmailCollectorLoadThirdPartyHelp=You can use this action to use the email content to find and load an existing thirdparty in your database. The found (or created) thirdparty will be used for following actions that need it.
For example, if you want to create a thirdparty with a name extracted a string 'Name: name to find' found into the body, use sender email as email, you can set the parameter field like this:
'email=HEADER:^From:(.*);name=EXTRACT:BODY:Name:\s([^\s]*);client=SET:2;'
EndPointFor=End point for %s : %s DeleteEmailCollector=Delete email collector ConfirmDeleteEmailCollector=Are you sure you want to delete this email collector? diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 422a3f118d8..dc074c817f8 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2019 Laurent Destailleur + * Copyright (C) 2004-2021 Laurent Destailleur * Copyright (C) 2004 Eric Seigne * Copyright (C) 2003 Brian Fraval * Copyright (C) 2006 Andre Cianfarani @@ -4265,21 +4265,6 @@ class Societe extends CommonObject return $lib; } - - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Set prospect level - * - * @param User $user User who sets the discount - * @return int <0 if KO, >0 if OK - * @deprecated Use update function instead - */ - public function set_prospect_level(User $user) - { - // phpcs:enable - return $this->update($this->id, $user); - } - /** * Return status of prospect * @@ -4359,20 +4344,6 @@ class Societe extends CommonObject return "Error, mode/status not found"; } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Set outstanding value - * - * @param User $user User making change - * @return int <0 if KO, >0 if OK - * @deprecated Use update function instead - */ - public function set_OutstandingBill(User $user) - { - // phpcs:enable - return $this->update($this->id, $user); - } - /** * Return amount of order not paid and total * From 180527d23a582498f8fd3330a708a9d40c1b0c3b Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Fri, 16 Jul 2021 10:10:57 +0200 Subject: [PATCH 55/58] FIX 13.0: class CommandeFournisseurDispatch provides trigger for UPDATE but not for CREATE / DELETE --- .../fourn/class/fournisseur.commande.dispatch.class.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/fourn/class/fournisseur.commande.dispatch.class.php b/htdocs/fourn/class/fournisseur.commande.dispatch.class.php index a7abed27369..0cffacc19a3 100644 --- a/htdocs/fourn/class/fournisseur.commande.dispatch.class.php +++ b/htdocs/fourn/class/fournisseur.commande.dispatch.class.php @@ -204,8 +204,8 @@ class CommandeFournisseurDispatch extends CommonObject // want this action calls a trigger. //// Call triggers - //$result=$this->call_trigger('MYOBJECT_CREATE',$user); - //if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail} + $result=$this->call_trigger('LINERECEPTION_CREATE', $user); + if ($result < 0) $error++; //// End call triggers } } @@ -419,8 +419,8 @@ class CommandeFournisseurDispatch extends CommonObject // want this action calls a trigger. //// Call triggers - //$result=$this->call_trigger('MYOBJECT_DELETE',$user); - //if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail} + $result=$this->call_trigger('LINERECEPTION_DELETE', $user); + if ($result < 0) $error++; //// End call triggers } } From c928de89c6c3b84f5192a4740785b384bf98759d Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Fri, 16 Jul 2021 10:41:06 +0200 Subject: [PATCH 56/58] fix: print barcode sould not be available for external user --- htdocs/core/modules/modBarcode.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/modBarcode.class.php b/htdocs/core/modules/modBarcode.class.php index 6a894972eb7..4b55f2e438f 100644 --- a/htdocs/core/modules/modBarcode.class.php +++ b/htdocs/core/modules/modBarcode.class.php @@ -104,7 +104,7 @@ class modBarcode extends DolibarrModules 'enabled'=>'$conf->barcode->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. 'perms'=>'($conf->global->MAIN_USE_ADVANCED_PERMS && $user->rights->barcode->lire_advance) || (! $conf->global->MAIN_USE_ADVANCED_PERMS)', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules 'target'=>'', - 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + 'user'=>0); // 0=Menu for internal users, 1=external users, 2=both $r++; $this->menu[$r] = array('fk_menu'=>'fk_mainmenu=home,fk_leftmenu=admintools', // Use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode From 4d6372dda12f9c36c00c1901fb0c9f529f7a8ab1 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio <68746600+marc-dll@users.noreply.github.com> Date: Fri, 16 Jul 2021 12:10:25 +0200 Subject: [PATCH 57/58] FIX: holiday balances: revert part of commit 1e7df0ba9 to still increment on page visit --- htdocs/holiday/define_holiday.php | 4 ++++ htdocs/holiday/list.php | 3 +++ htdocs/hrm/index.php | 10 ++++++++++ 3 files changed, 17 insertions(+) diff --git a/htdocs/holiday/define_holiday.php b/htdocs/holiday/define_holiday.php index fcb8b73d486..b3d2c25adda 100644 --- a/htdocs/holiday/define_holiday.php +++ b/htdocs/holiday/define_holiday.php @@ -193,6 +193,10 @@ llxHeader('', $langs->trans('CPTitreMenu')); $typeleaves = $holiday->getTypes(1, 1); +$result = $holiday->updateBalance(); // Create users into table holiday if they don't exists. TODO Remove this whif we use field into table user. +if ($result < 0) { + setEventMessages($holiday->error, $holiday->errors, 'errors'); +} print ''; diff --git a/htdocs/holiday/list.php b/htdocs/holiday/list.php index 9d569f4344e..c62185d5f2a 100644 --- a/htdocs/holiday/list.php +++ b/htdocs/holiday/list.php @@ -231,6 +231,9 @@ $formfile = new FormFile($db); $fuser = new User($db); $holidaystatic = new Holiday($db); +// Update sold +$result = $object->updateBalance(); + $title = $langs->trans('CPTitreMenu'); llxHeader('', $title); diff --git a/htdocs/hrm/index.php b/htdocs/hrm/index.php index 6cc4dc3b5bd..50fd4c3f521 100644 --- a/htdocs/hrm/index.php +++ b/htdocs/hrm/index.php @@ -68,6 +68,16 @@ if (empty($conf->global->MAIN_INFO_SOCIETE_NOM) || empty($conf->global->MAIN_INF $max = $conf->global->MAIN_SIZE_SHORTLIST_LIMIT; +/* + * Actions + */ + +// Update sold +if (!empty($conf->holiday->enabled) && !empty($setupcompanynotcomplete)) { + $holidaystatic = new Holiday($db); + $result = $holidaystatic->updateBalance(); +} + /* * View From 501bc853af6c32b74c9a3c8fc6e939f969f643bd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 16 Jul 2021 12:44:15 +0200 Subject: [PATCH 58/58] Fix default value --- htdocs/install/mysql/tables/llx_object_lang.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/tables/llx_object_lang.sql b/htdocs/install/mysql/tables/llx_object_lang.sql index cc4352f3acc..01b70b208ff 100644 --- a/htdocs/install/mysql/tables/llx_object_lang.sql +++ b/htdocs/install/mysql/tables/llx_object_lang.sql @@ -25,7 +25,7 @@ create table llx_object_lang fk_object integer DEFAULT 0 NOT NULL, type_object varchar(32) NOT NULL, -- value found into $object->element: 'thirdparty', 'contact', '...' property varchar(32) NOT NULL, -- name of property - lang varchar(5) DEFAULT 0 NOT NULL, + lang varchar(5) DEFAULT '' NOT NULL, value text, import_key varchar(14) DEFAULT NULL )ENGINE=innodb;