diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 432f30f2332..00000000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,35 +0,0 @@
----
-name: Bug report
-about: Create a report to help us fix something that is broken
-title: ''
-labels: Bug
-assignees: ''
-
----
-
-# Instructions
-*This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.*
-*Please:*
-- *replace the bracket enclosed texts with meaningful information*
-- *remove any unused sub-section*
-
-
-# Bug
-[*Short description*]
-
-## Environment
-- **Version**: [*Affected Dolibarr version(s)*]
-- **OS**: [*Server OS type and version*]
-- **Web server**: [*Webserver type and version*]
-- **PHP**: [*PHP version*]
-- **Database**: [*Database type and version*]
-- **URL(s)**: [*Affected URL(s)*]
-
-## Expected and actual behavior
-[*Verbose description*]
-
-## Steps to reproduce the behavior
-[*Verbose description*]
-
-## [Attached files](https://help.github.com/articles/issue-attachments) (Screenshots, screencasts, dolibarr.log, debugging informations…)
-[*Files*]
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 00000000000..d7dc3d584e3
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,71 @@
+name: Bug report
+description: Create a report to help us fix something that is broken
+labels: ["Bug"]
+
+body:
+ - type: markdown
+ attributes:
+ value: |
+ This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.
+
+ - type: textarea
+ id: bug
+ attributes:
+ label: Bug
+ description: Please give a short description of the bug
+ validations:
+ required: true
+
+ - type: input
+ id: environment-version
+ attributes:
+ label: Environment Version
+ description: Affected Dolibarr version(s)
+
+ - type: input
+ id: environment-os
+ attributes:
+ label: Environment OS
+ description: Server OS type and version
+
+ - type: input
+ id: environment-webserver
+ attributes:
+ label: Environment Web server
+ description: Webserver type and version
+
+ - type: input
+ id: environment-php
+ attributes:
+ label: Environment PHP
+ description: PHP version
+
+ - type: input
+ id: environment-database
+ attributes:
+ label: Environment Database
+ description: Database type and version
+
+ - type: input
+ id: environment-urls
+ attributes:
+ label: Environment URL(s)
+ description: Affected URL(s)
+
+ - type: textarea
+ id: expected-behaviour
+ attributes:
+ label: Expected and actual behavior
+ description: Verbose description
+
+ - type: textarea
+ id: reproduce
+ attributes:
+ label: Steps to reproduce the behavior
+ description: Verbose description
+
+ - type: textarea
+ id: files
+ attributes:
+ label: Attached files
+ description: Screenshots, screencasts, dolibarr.log, debugging informations
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index 32e2deff2c1..00000000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-name: Feature request
-about: Suggest a new idea for this project
-title: ''
-labels: Feature request
-assignees: ''
-
----
-
-# Instructions
-*This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.*
-*Please:*
-- *replace the bracket enclosed texts with meaningful information*
-- *remove any unused sub-section*
-
-
-# Feature Request
-[*Short description*]
-
-## Use case
-[*Verbose description*]
-
-## Suggested implementation
-[*Verbose description*]
-
-## Suggested steps
-[*List of tasks to achieve goal*]
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 00000000000..885f3472d18
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,35 @@
+name: Feature request
+description: Suggest a new idea for this project
+labels: ["Feature request"]
+
+body:
+ - type: markdown
+ attributes:
+ value: |
+ This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.
+
+ - type: textarea
+ id: feature-request
+ attributes:
+ label: Feature Request
+ description: Short description
+ validations:
+ required: true
+
+ - type: textarea
+ id: use-case
+ attributes:
+ label: Use case
+ description: Verbose description
+
+ - type: textarea
+ id: suggested-implementation
+ attributes:
+ label: Suggested implementation
+ description: Verbose description
+
+ - type: textarea
+ id: suggested-steps
+ attributes:
+ label: Suggested steps
+ description: List of tasks to achieve goal
diff --git a/ChangeLog b/ChangeLog
index a8211da486a..a9a42c8d878 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,10 +12,9 @@ NEW: Online proposal signature
NEW: Can define some max limit on expense report (per period, per type or expense, ...)
NEW: Allow the use of __NEWREF__ to get for example the new reference a draft order will get after validation.
NEW: Add option to disable globaly some notifications emails.
-NEW: #18326 Workflow: Close order on shipment closing.
NEW: #18401 Add __NEWREF__ subtitute to get new object reference.
NEW: #18403 Add __URL_SHIPMENT__ substitute to get the URL of a shipment
-NEW: #18689 REST API module: add api key generate / modify right.
+NEW: #18689 REST API module: add api key generate / modify permission.
NEW: #18663 Make "L'Annuaire des Entreprises" the default provider for SIREN verification for French thirdparties.
NEW: #18046 Add tags on ticket/categories
NEW: #18326 Workflow: Close order on shipment closing.
@@ -109,6 +108,13 @@ NEW: External backups can be downloaded from the "About info page".
NEW: Add massaction to switch status on sale / on purchase of a product.
+ Modules
+NEW: Stable module Knowledge Management
+NEW: Experimental module Event Organization Management
+NEW: Experimental module Workstations Management
+NEW: Development of module Partnership Management
+
+
For developers:
---------------
@@ -116,6 +122,7 @@ NEW: Introduce method hasRight
NEW: Can use textarea field into a confirm popup.
NEW: Can use the result_mode of mysqli driver. Save memory for list count
NEW: #18319 REST API - Shipment: Add 'close' action / endpoint / POST method.
+NEW: Add API /approve and /makeOrder for purchase orders.
NEW: add action trigger for member excluded
NEW: add option MAIN_IBAN_IS_NEVER_MANDATORY, MAIN_IBAN_NOT_MANDATORY, PROPAL_NOT_BILLABLE, PROPAL_REOPEN_UNSIGNED_ONLY, PROPOSAL_ARE_NOT_BILLABLE, TICKETS_MESSAGE_FORCE_MAIL
NEW: Add code codebar column on serial/lot structure
diff --git a/SECURITY.md b/SECURITY.md
index 4e7e5fa933a..cadd4a23791 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -67,7 +67,7 @@ Scope is the web application (back office) and the APIs.
* Remote code execution (RCE)
* Local files access and manipulation (LFI, RFI, XXE, SSRF, XSPA)
* Code injections (HTML, JS, SQL, PHP, ...)
-* Cross-Site Scripting (XSS), except from setup page of module "External web site" (allowing any content here, editable by admin user only, is accepted on purpose or into module "Web site" when permission to edit website content is allowed).
+* Cross-Site Scripting (XSS), except from setup page of module "External web site" (allowing any content here, editable by admin user only, is accepted on purpose) and except into module "Web site" when permission to edit website content is allowed (injecting any data in this case is allowed too).
* Cross-Site Requests Forgery (CSRF) with real security impact (when using GET URLs, CSRF are qualified only for creating, updating or deleting data from pages restricted to admin users)
* Open redirect
* Broken authentication & session management
diff --git a/build/docker/Dockerfile b/build/docker/Dockerfile
index eb8e3ade6dc..ead2a8af1c5 100644
--- a/build/docker/Dockerfile
+++ b/build/docker/Dockerfile
@@ -39,15 +39,13 @@ RUN chmod +x /usr/local/bin/docker-run.sh
RUN pecl install xdebug && docker-php-ext-enable xdebug
RUN echo 'zend_extension="/usr/local/lib/php/extensions/no-debug-non-zts-20180731/xdebug.so"' >> ${PHP_INI_DIR}/php.ini
-RUN echo 'xdebug.remote_autostart=1' >> ${PHP_INI_DIR}/php.ini
-RUN echo 'xdebug.remote_enable=1' >> ${PHP_INI_DIR}/php.ini
-RUN echo 'xdebug.default_enable=1' >> ${PHP_INI_DIR}/php.ini
-#RUN echo 'xdebug.remote_host=docker.host' >> ${PHP_INI_DIR}/php.ini
-RUN echo 'xdebug.remote_port=9000' >> ${PHP_INI_DIR}/php.ini
-RUN echo 'xdebug.remote_connect_back=1' >> ${PHP_INI_DIR}/php.ini
-RUN echo 'xdebug.profiler_enable=0' >> ${PHP_INI_DIR}/php.ini
-RUN echo 'xdebug.remote_log="/tmp/xdebug.log"' >> ${PHP_INI_DIR}/php.ini
-#RUN echo 'localhost docker.host' >> /etc/hosts
+RUN echo 'xdebug.mode=debug' >> ${PHP_INI_DIR}/php.ini
+RUN echo 'xdebug.start_with_request=yes' >> ${PHP_INI_DIR}/php.ini
+RUN echo 'xdebug.client_host=host.docker.internal' >> ${PHP_INI_DIR}/php.ini
+RUN echo 'xdebug.client_port=9003' >> ${PHP_INI_DIR}/php.ini
+RUN echo 'xdebug.discover_client_host=true' >> ${PHP_INI_DIR}/php.ini
+#RUN echo 'xdebug.log="/tmp/xdebug.log"' >> ${PHP_INI_DIR}/php.ini
+RUN echo 'xdebug.idekey="netbeans-xdebug"' >> ${PHP_INI_DIR}/php.ini
# set up sendmail config, to use maildev
RUN echo "account default" > /etc/msmtprc
diff --git a/build/docker/docker-compose.yml b/build/docker/docker-compose.yml
index b72118de5fb..8994043cd8a 100644
--- a/build/docker/docker-compose.yml
+++ b/build/docker/docker-compose.yml
@@ -48,6 +48,7 @@ services:
- external-pod
extra_hosts:
- "localhost.localdomain:127.0.0.1"
+ - "host.docker.internal:host-gateway"
mail:
image: maildev/maildev
diff --git a/dev/setup/apache/virtualhost b/dev/setup/apache/virtualhost
index c3a2dff3e43..8c7682fe3d9 100644
--- a/dev/setup/apache/virtualhost
+++ b/dev/setup/apache/virtualhost
@@ -1,62 +1,93 @@
| '; print ' | '; print $generic_commande->getNomUrl(1, ($search_status != 2 ? 0 : $obj->fk_statut), 0, 0, 0, 1, 1); - // Warning late icon and note - if ($generic_commande->hasDelay()) { - print img_picto($langs->trans("Late").' : '.$generic_commande->showDelay(), "warning"); - } - $filename = dol_sanitizeFileName($obj->ref); $filedir = $conf->commande->multidir_output[$conf->entity].'/'.dol_sanitizeFileName($obj->ref); $urlsource = $_SERVER['PHP_SELF'].'?id='.$obj->rowid; @@ -1590,6 +1585,10 @@ if ($resql) { if (!empty($arrayfields['c.date_commande']['checked'])) { print ' | '; print dol_print_date($db->jdate($obj->date_commande), 'day'); + // Warning late icon and note + if ($generic_commande->hasDelay()) { + print img_picto($langs->trans("Late").' : '.$generic_commande->showDelay(), "warning"); + } print ' | '; if (!$i) { $totalarray['nbfield']++; @@ -1854,10 +1853,13 @@ if ($resql) { print '';
if (!empty($show_shippable_command) && !empty($conf->stock->enabled)) {
if (($obj->fk_statut > $generic_commande::STATUS_DRAFT) && ($obj->fk_statut < $generic_commande::STATUS_CLOSED)) {
- $generic_commande->getLinesArray(); // This set ->lines
+ $generic_commande->getLinesArray(); // Load array ->lines
+ $generic_commande->loadExpeditions(); // Load array ->expeditions
$numlines = count($generic_commande->lines); // Loop on each line of order
for ($lig = 0; $lig < $numlines; $lig++) {
+ $reliquat = $generic_commande->lines[$lig]->qty - $generic_commande->expeditions[$generic_commande->lines[$lig]->id];
+
if ($generic_commande->lines[$lig]->product_type == 0 && $generic_commande->lines[$lig]->fk_product > 0) { // If line is a product and not a service
$nbprod++; // order contains real products
$generic_product->id = $generic_commande->lines[$lig]->fk_product;
@@ -1872,15 +1874,15 @@ if ($resql) {
$generic_product->stock_theorique = $productstat_cachevirtual[$generic_commande->lines[$lig]->fk_product]['stock_reel'] = $generic_product->stock_theorique;
}
+ if ($reliquat > $generic_product->stock_reel) {
+ $notshippable++;
+ }
if (empty($conf->global->SHIPPABLE_ORDER_ICON_IN_LIST)) { // Default code. Default should be this case.
- $text_info .= $generic_commande->lines[$lig]->qty.' X '.$generic_commande->lines[$lig]->product_ref.' '.dol_trunc($generic_commande->lines[$lig]->product_label, 25);
+ $text_info .= $reliquat.' x '.$generic_commande->lines[$lig]->product_ref.' '.dol_trunc($generic_commande->lines[$lig]->product_label, 20);
$text_info .= ' - '.$langs->trans("Stock").': '.$generic_product->stock_reel.'';
$text_info .= ' - '.$langs->trans("VirtualStock").': '.$generic_product->stock_theorique.'';
+ $text_info .= ($reliquat != $generic_commande->lines[$lig]->qty ? ' ('.$langs->trans("QtyInOtherShipments").' '.($generic_commande->lines[$lig]->qty - $reliquat).')' : '');
$text_info .= ' '; - - if ($generic_commande->lines[$lig]->qty > $generic_product->stock_reel) { - $notshippable++; - } } else { // BUGGED CODE. // DOES NOT TAKE INTO ACCOUNT MANUFACTURING. THIS CODE SHOULD BE USELESS. PREVIOUS CODE SEEMS COMPLETE. // COUNT STOCK WHEN WE SHOULD ALREADY HAVE VALUE @@ -1908,32 +1910,31 @@ if ($resql) { $stock_order_supplier = $generic_product->stats_commande_fournisseur['qty']; } } - $text_info .= $generic_commande->lines[$lig]->qty.' X '.$generic_commande->lines[$lig]->ref.' '.dol_trunc($generic_commande->lines[$lig]->product_label, 25); + $text_info .= $reliquat.' x '.$generic_commande->lines[$lig]->ref.' '.dol_trunc($generic_commande->lines[$lig]->product_label, 20); $text_stock_reel = $generic_product->stock_reel.'/'.$stock_order; if ($stock_order > $generic_product->stock_reel && !($generic_product->stock_reel < $generic_commande->lines[$lig]->qty)) { $warning++; $text_warning .= ''.$langs->trans('Available').' : '.$text_stock_reel.''; } - if ($generic_product->stock_reel < $generic_commande->lines[$lig]->qty) { - $notshippable++; + if ($reliquat > $generic_product->stock_reel) { $text_info .= ''.$langs->trans('Available').' : '.$text_stock_reel.''; } else { $text_info .= ''.$langs->trans('Available').' : '.$text_stock_reel.''; } if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled)) { - $text_info .= ' '.$langs->trans('SupplierOrder').' : '.$stock_order_supplier.' '; - } else { - $text_info .= ' '; + $text_info .= ' '.$langs->trans('SupplierOrder').' : '.$stock_order_supplier; } + $text_info .= ($reliquat != $generic_commande->lines[$lig]->qty ? ' ('.$langs->trans("QtyInOtherShipments").' '.($generic_commande->lines[$lig]->qty - $reliquat).')' : ''); + $text_info .= ' '; } } } if ($notshippable == 0) { $text_icon = img_picto('', 'dolly', '', false, 0, 0, '', 'green paddingleft'); - $text_info = $langs->trans('Shippable').' '.$text_info; + $text_info = $text_icon.' '.$langs->trans('Shippable').' '.$text_info; } else { $text_icon = img_picto('', 'dolly', '', false, 0, 0, '', 'error paddingleft'); - $text_info = $langs->trans('NonShippable').' '.$text_info; + $text_info = $text_icon.' '.$langs->trans('NonShippable').' '.$text_info; } } diff --git a/htdocs/compta/bank/bankentries_list.php b/htdocs/compta/bank/bankentries_list.php index c05f0f4530c..3d8e6f8bd98 100644 --- a/htdocs/compta/bank/bankentries_list.php +++ b/htdocs/compta/bank/bankentries_list.php @@ -1339,14 +1339,15 @@ if ($resql) { $labeltoshow = $langs->trans($reg[1]); } else { if ($objp->label == '(payment_salary)') { - $labeltoshow = dol_trunc($langs->trans("SalaryPayment", 40)); + $labeltoshow = $langs->trans("SalaryPayment"); } else { $labeltoshow = dol_escape_htmltag($objp->label); $titletoshow = $objp->label; } } - print ' | '; - print $labeltoshow; // Already escaped + + + print ' | '; // Add info about links after description $cachebankaccount = array(); @@ -1355,70 +1356,70 @@ if ($resql) { if ($links[$key]['type'] == 'withdraw') { $banktransferstatic->id = $links[$key]['url_id']; $banktransferstatic->ref = $links[$key]['label']; - print ' '.$banktransferstatic->getNomUrl(0); + print $banktransferstatic->getNomUrl(0).' '; } elseif ($links[$key]['type'] == 'payment') { $paymentstatic->id = $links[$key]['url_id']; $paymentstatic->ref = $links[$key]['url_id']; // FIXME This is id, not ref of payment $paymentstatic->date = $db->jdate($objp->do); - print ' '.$paymentstatic->getNomUrl(2); + print $paymentstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_supplier') { $paymentsupplierstatic->id = $links[$key]['url_id']; $paymentsupplierstatic->ref = $links[$key]['url_id']; // FIXME This is id, not ref of payment - print ' '.$paymentsupplierstatic->getNomUrl(2); + print $paymentsupplierstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_sc') { $paymentscstatic->id = $links[$key]['url_id']; $paymentscstatic->ref = $links[$key]['url_id']; $paymentscstatic->label = $links[$key]['label']; - print ' '.$paymentscstatic->getNomUrl(2); + print $paymentscstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_vat') { $paymentvatstatic->id = $links[$key]['url_id']; $paymentvatstatic->ref = $links[$key]['url_id']; - print ' '.$paymentvatstatic->getNomUrl(2); + print $paymentvatstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_salary') { $paymentsalstatic->id = $links[$key]['url_id']; $paymentsalstatic->ref = $links[$key]['url_id']; $paymentsalstatic->label = $links[$key]['label']; - print ' '.$paymentsalstatic->getNomUrl(2); + print $paymentsalstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_loan') { print ''; print ' '.img_object($langs->trans('ShowPayment'), 'payment').' '; - print ''; + print ' '; } elseif ($links[$key]['type'] == 'payment_donation') { $paymentdonationstatic->id = $links[$key]['url_id']; $paymentdonationstatic->ref = $links[$key]['url_id']; - print ' '.$paymentdonationstatic->getNomUrl(2); + print $paymentdonationstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_expensereport') { $paymentexpensereportstatic->id = $links[$key]['url_id']; $paymentexpensereportstatic->ref = $links[$key]['url_id']; - print ' '.$paymentexpensereportstatic->getNomUrl(2); + print $paymentexpensereportstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'payment_various') { $paymentvariousstatic->id = $links[$key]['url_id']; $paymentvariousstatic->ref = $links[$key]['url_id']; - print ' '.$paymentvariousstatic->getNomUrl(2); + print $paymentvariousstatic->getNomUrl(2).' '; } elseif ($links[$key]['type'] == 'banktransfert') { // Do not show link to transfer since there is no transfer card (avoid confusion). Can already be accessed from transaction detail. if ($objp->amount > 0) { $banklinestatic->fetch($links[$key]['url_id']); $bankstatic->id = $banklinestatic->fk_account; $bankstatic->label = $banklinestatic->bank_account_ref; - print ' ('.$langs->trans("TransferFrom").' '; + print $langs->trans("TransferFrom").' '; print $bankstatic->getNomUrl(1, 'transactions'); print ' '.$langs->trans("toward").' '; $bankstatic->id = $objp->bankid; $bankstatic->label = $objp->bankref; print $bankstatic->getNomUrl(1, ''); - print ')'; + print ' - '; } else { $bankstatic->id = $objp->bankid; $bankstatic->label = $objp->bankref; - print ' ('.$langs->trans("TransferFrom").' '; + print $langs->trans("TransferFrom").' '; print $bankstatic->getNomUrl(1, ''); print ' '.$langs->trans("toward").' '; $banklinestatic->fetch($links[$key]['url_id']); $bankstatic->id = $banklinestatic->fk_account; $bankstatic->label = $banklinestatic->bank_account_ref; print $bankstatic->getNomUrl(1, 'transactions'); - print ')'; + print ' - '; } //var_dump($links); } elseif ($links[$key]['type'] == 'company') { @@ -1430,22 +1431,22 @@ if ($resql) { // Information is already shown using the payment_salary link. No need of this link. } else { // Show link with label $links[$key]['label'] - if (!empty($objp->label) && !empty($links[$key]['label'])) { - print ' - '; - } print ''; if (preg_match('/^\((.*)\)$/i', $links[$key]['label'], $reg)) { // Label generique car entre parentheses. On l'affiche en le traduisant if ($reg[1] == 'paiement') { $reg[1] = 'Payment'; } - print ' '.$langs->trans($reg[1]); + print $langs->trans($reg[1]); } else { - print ' '.$links[$key]['label']; + print $links[$key]['label']; } - print ''; + print ''.($labeltoshow ? ' - ' : ''); } } + + print $labeltoshow; // Already escaped + print ' | '; if (!$i) { $totalarray['nbfield']++; @@ -1488,7 +1489,7 @@ if ($resql) { // Payment type if (!empty($arrayfields['type']['checked'])) { - print ''; + print ' | '; $labeltype = ($langs->trans("PaymentTypeShort".$objp->fk_type) != "PaymentTypeShort".$objp->fk_type) ? $langs->trans("PaymentTypeShort".$objp->fk_type) : $langs->getLabelFromKey($db, $objp->fk_type, 'c_paiement', 'code', 'libelle', '', 1); if ($labeltype == 'SOLD') { print ' '; //$langs->trans("InitialBankBalance"); @@ -1514,9 +1515,9 @@ if ($resql) { print ' | '; $companylinked_id = 0; - $userlinked_id = 0; + $userlinked_id = 0; - //payment line type to define user display and user or company linked + //payment line type to define user display and user or company linked foreach ($links as $key => $value) { if ($links[$key]['type'] == 'payment_sc') { $type_link = 'payment_sc'; diff --git a/htdocs/compta/facture/card-rec.php b/htdocs/compta/facture/card-rec.php index a76332197bc..3909d9437b4 100644 --- a/htdocs/compta/facture/card-rec.php +++ b/htdocs/compta/facture/card-rec.php @@ -1354,6 +1354,7 @@ if ($action == 'create') { $dateexample = $object->date_when; } + // Help of substitution key $substitutionarray = getCommonSubstitutionArray($langs, 2, null, $object); $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%m').')'; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index ec8e2864451..da438af9e01 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -130,6 +130,7 @@ $usercanread = $user->rights->facture->lire; $usercancreate = $user->rights->facture->creer; $usercanissuepayment = $user->rights->facture->paiement; $usercandelete = $user->rights->facture->supprimer; +$usercancreatecontract = $user->rights->contrat->creer; $usercanvalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->facture->invoice_advance->validate))); $usercansend = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->facture->invoice_advance->send))); $usercanreopen = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->facture->invoice_advance->reopen))); @@ -609,7 +610,7 @@ if (empty($reshook)) { // Check parameters // Check for mandatory fields in thirdparty (defined into setup) - $array_to_check = array('IDPROF1', 'IDPROF2', 'IDPROF3', 'IDPROF4', 'IDPROF5', 'IDPROF6', 'EMAIL'); + $array_to_check = array('IDPROF1', 'IDPROF2', 'IDPROF3', 'IDPROF4', 'IDPROF5', 'IDPROF6', 'EMAIL', 'ACCOUNTANCY_CODE_CUSTOMER'); foreach ($array_to_check as $key) { $keymin = strtolower($key); $i = (int) preg_replace('/[^0-9]/', '', $key); @@ -637,6 +638,14 @@ if (empty($reshook)) { setEventMessages($langs->trans("ErrorBadEMail", $object->thirdparty->email).' ('.$langs->trans("ForbiddenBySetupRules").')', null, 'errors'); } } + if ($key == 'ACCOUNTANCY_CODE_CUSTOMER') { + // Check for mandatory + if (!empty($conf->global->SOCIETE_ACCOUNTANCY_CODE_CUSTOMER_INVOICE_MANDATORY) && empty($object->thirdparty->code_compta)) { + $langs->load("errors"); + $error++; + setEventMessages($langs->trans("ErrorAccountancyCodeCustomerIsMandatory", $object->thirdparty->name).' ('.$langs->trans("ForbiddenBySetupRules").')', null, 'errors'); + } + } } } @@ -1126,6 +1135,8 @@ if (empty($reshook)) { $facture_source->fetchPreviousNextSituationInvoice(); } } + + $id = $object->create($user); if ($id < 0) { $error++; @@ -1253,6 +1264,7 @@ if (empty($reshook)) { $line->multicurrency_total_tva = -$line->multicurrency_total_tva; $line->multicurrency_total_ttc = -$line->multicurrency_total_ttc; + $line->context['createcreditnotefrominvoice'] = 1; $result = $line->insert(0, 1); // When creating credit note with same lines than source, we must ignore error if discount alreayd linked $object->lines[] = $line; // insert new line in current object @@ -3417,6 +3429,10 @@ if ($action == 'create') { $optionsav .= ' | '; print '