From 0b4105880e1c3d89c7ad080ea20ec0be305a93f2 Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Mon, 14 Jun 2021 21:59:37 +0200 Subject: [PATCH 1/5] Update ChangeLog --- ChangeLog | 52 +++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 95a4a7a3ae6..5808fbf313f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,19 +16,12 @@ NEW: A lot of fix into english text after a small proofreading campaign (still n NEW: All main menu entries are using the picto of the module NEW: Add a copy to clipboard button on some fields NEW: Add an example of scheduled job to send email reminder for unpaid invoices -NEW: Accountancy - Add FEC import -NEW: Accountancy - Add a confirmation form with options on export -NEW: Accountancy - Add select date from/to in already bind customer and supplier list -NEW: Accountancy - Format FEC - Add new field DateLimitReglmt -NEW: Accountancy - In ledger & journals, show link on bank transaction -NEW: Accountancy - Possibility to filter on journals in balance -NEW: Accountancy - Add a page to list subledger accounts -NEW: add the Channel column into the list of orders NEW: Add a check to avoid an invoice date in the future NEW: Add some color and picto for the direction of movement +NEW: add the column "Channel" into the list of orders NEW: Add the column "alias" of company in the list of proposal, order, invoice NEW: Add the column "Office phone" and "User mobile" in user list -NEW: Add the column "Price level"in thirdparty list +NEW: Add the column "Price level" in thirdparty list NEW: Add some company information in the dropdown login menu NEW: Add constant MAIN_BUGTRACK_URL to set a custom url to redirect to when clicking on link "declare a bug" NEW: Add contact tag and bulk email status on the thirdparty + contact create form @@ -92,13 +85,22 @@ NEW: When a doc file is shared, link is visible from the main page of doc. NEW: #16378 More E-Mail Contact substitution Values for better salutation NEW: option to keep the "Automatically create a total payment" checkbox empty on the tax creation page + Accountancy +NEW: Accountancy - Add FEC import +NEW: Accountancy - Add a confirmation form with options on export +NEW: Accountancy - Add select date from/to in already bind customer and supplier list +NEW: Accountancy - Format FEC - Add new field DateLimitReglmt +NEW: Accountancy - In ledger & journals, show link on bank transaction +NEW: Accountancy - Possibility to filter on journals in balance +NEW: Accountancy - Add a page to list subledger accounts + ECM/GED -NEW: Add db fields note_public and note_private for ECM module -NEW: Can filter files in GED on status Shared/Not shared +NEW: add DB fields note_public and note_private for ECM module +NEW: Can filter files in ECM/GED on status Shared/Not shared Members NEW: #17292 default subscription amount by adherent type -NEW: Option to automatically create a login/user when a new subscription of a member is done online +NEW: option to automatically create a login/user when a new subscription of a member is done online NEW: option to select membership type on the online payment page for membership subscription or renewal Projects/Tasks @@ -122,17 +124,17 @@ NEW: option for TakePOS to show the total price without tax NEW: more permissions in TakePOS (can edit added line, can modify once order sent to kitchen) Third-Parties -NEW: Can set a Warehouse on a Thirdparty +NEW: can set a warehouse on a Thirdparty Tickets NEW: can use captcha on public page to create a ticket #16347 NEW: can set if a ticket group is visible on public interface or not Warehouse -NEW: Can make massive stock transfers from a CSV file -NEW: Stock movement list - Add more complete date field -NEW: Can set a Warehouse on a Thirdparty +NEW: can make massive stock transfers from a CSV file +NEW: Stock movement list - add more complete date field NEW: can set a warehouse in a proposal +NEW: can set a warehouse on a Thirdparty Website Module NEW: #17113 Can upload a favicon in website module @@ -147,10 +149,10 @@ NEW: start new experimental module Knowledge Management NEW: start new experimental module Workstations Management new Options -NEW: Add option CONTRACT_ALLOW_EXTERNAL_DOWNLOAD to make generated doc automatically shared -NEW: Add option SUPPLIER_PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD to make generated doc automatically shared -NEW: Add option MAIN_SECURITY_ANTI_SSRF_SERVER_IP to define list of IPs that are local IPs -NEW: Add option SOCIETE_DISABLE_WORKFORCE to hide staff field +NEW: add option CONTRACT_ALLOW_EXTERNAL_DOWNLOAD to make generated doc automatically shared +NEW: add option SUPPLIER_PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD to make generated doc automatically shared +NEW: add option MAIN_SECURITY_ANTI_SSRF_SERVER_IP to define list of IPs that are local IPs +NEW: add option SOCIETE_DISABLE_WORKFORCE to hide staff field For developers: @@ -164,10 +166,7 @@ NEW: Add experimental repair script to switch to dynamic row format and utf8mb4 NEW: add form confirm hook on company card NEW: Add function showValueWithClipboardCPButton() to add a copy/paste NEW: Add hook addSectionECMAuto method to add custom diretory into ECM auto files -NEW: Add native compression in rest apis -NEW: Product Variants API, add variant stock to response by parameter NEW: Upgrade Stripe PHP lib to 7.67.0 -NEW: Add link to OpenAPI specifications xml file in REST API module setup: swagger.json file can be included into external tools like redoc NEW: Support sepa_debit in stripe paymentmethods list NEW: Update doleditor.class.php for easily activate SCAYT NEW: Add triggers in the function add_object_linked(), updateObjectLinked() and deleteObjectLinked() @@ -181,8 +180,11 @@ NEW: unit selection on object edit line NEW: #13739 #17390 Product API route added to get product stock and product with or without variants APIs -NEW: API Add option $includeifobjectisused to get a product -NEW: API Get the list of product ids only +NEW: API add option $includeifobjectisused to get a product +NEW: API get the list of product ids only +NEW: add native compression in REST APIs +NEW: Product Variants API, add variant stock to response by parameter +NEW: add link to OpenAPI specifications XML file in REST API module setup: swagger.json file can be included into external tools like redoc WARNING: From 5ceb957059ac21cd5e608bddbf68407eb52405ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Tue, 15 Jun 2021 08:48:52 +0200 Subject: [PATCH 2/5] fix php warning --- htdocs/core/tpl/document_actions_post_headers.tpl.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/htdocs/core/tpl/document_actions_post_headers.tpl.php b/htdocs/core/tpl/document_actions_post_headers.tpl.php index 45090824248..4ec69efbac8 100644 --- a/htdocs/core/tpl/document_actions_post_headers.tpl.php +++ b/htdocs/core/tpl/document_actions_post_headers.tpl.php @@ -47,6 +47,9 @@ if (!isset($permission)) { if (!isset($permtoedit)) { $permtoedit = $permissiontoadd; } +if (!isset($param)) { + $param = ''; +} // Drag and drop for up and down allowed on product, thirdparty, ... // The drag and drop call the page core/ajax/row.php From 77f0645c0efc07f8794402d7bb32fffbb3024dac Mon Sep 17 00:00:00 2001 From: UT from dolibit <45215329+dolibit-ut@users.noreply.github.com> Date: Tue, 15 Jun 2021 10:30:58 +0200 Subject: [PATCH 3/5] Update index.php --- htdocs/accountancy/closure/index.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/htdocs/accountancy/closure/index.php b/htdocs/accountancy/closure/index.php index bcb3d7901f5..b612762d358 100644 --- a/htdocs/accountancy/closure/index.php +++ b/htdocs/accountancy/closure/index.php @@ -12,7 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . * */ @@ -124,7 +124,11 @@ if ($action == 'validate_movements_confirm' && !empty($user->rights->accounting- $form = new Form($db); $formaccounting = new FormAccounting($db); -llxHeader('', $langs->trans("Closure")); +$title = $langs->trans('Closure'); + +$help_url ='EN:Module_Double_Entry_Accounting'; + +llxHeader('', $title, $help_url); if ($action == 'validate_movements') { $form_question = array(); From 2688b902b65f73c25650c8328709669a07499447 Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 15 Jun 2021 11:35:41 +0200 Subject: [PATCH 4/5] Close #17890 : produceandconsume into api finished --- htdocs/mrp/class/api_mos.class.php | 290 ++++++++++++++++++++++++++++- 1 file changed, 289 insertions(+), 1 deletion(-) diff --git a/htdocs/mrp/class/api_mos.class.php b/htdocs/mrp/class/api_mos.class.php index 33d4a108f17..22420733a45 100644 --- a/htdocs/mrp/class/api_mos.class.php +++ b/htdocs/mrp/class/api_mos.class.php @@ -327,6 +327,12 @@ class Mos extends DolibarrApi if ($field == 'autoclose') { $autoclose = $value; } + if ($field == 'arraytoconsume') { + $arraytoconsume = $value; + } + if ($field == 'arraytoproduce') { + $arraytoproduce = $value; + } } if (empty($labelmovement)) { @@ -337,7 +343,289 @@ class Mos extends DolibarrApi } // TODO Add code for consume and produce... - throw new RestException(500, "Feature not yet available"); + require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; + require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php'; + dol_include_once('/mrp/lib/mrp_mo.lib.php'); + $stockmove = new MouvementStock($this->db); + if (!empty($arraytoconsume) && !empty($arraytoproduce)) { + $pos = 0; + $arrayofarrayname = array("arraytoconsume","arraytoproduce"); + foreach ($arrayofarrayname as $arrayname) { + foreach ($$arrayname as $value) { + $tmpproduct = new Product($this->db); + if (empty($value["objectid"])) { + throw new RestException(500, "Field objectid required in ".$arrayname); + } + $tmpproduct->fetch($value["qty"]); + if (empty($value["qty"])) { + throw new RestException(500, "Field qty required in ".$arrayname); + } + if ($value["qty"]!=0) { + $qtytoprocess = $value["qty"]; + if (isset($value["fk_warehouse"])) { // If there is a warehouse to set + if (!($value["fk_warehouse"] > 0)) { // If there is no warehouse set. + throw new RestException(500, "Field fk_warehouse must be > 0 in ".$arrayname); + $error++; + } + if ($tmpproduct->status_batch) { + throw new RestException(500, "Product ".$tmpproduct->ref."must be in batch"); + $error++; + } + } + $idstockmove = 0; + if (!$error && $value["fk_warehouse"] > 0) { + // Record stock movement + $id_product_batch = 0; + $stockmove->origin = $this->mo; + if ($qtytoprocess >= 0) { + $moline = new MoLine($this->db); + $moline->fk_mo = $this->mo->id; + $moline->position = $pos; + $moline->fk_product = $value["objectid"]; + $moline->fk_warehouse = $value["fk_warehouse"]; + $moline->qty = $qtytoprocess; + $moline->batch = $tmpproduct->status_batch; + $moline->role = 'toproduce'; + $moline->fk_mrp_production = ""; + $moline->fk_stock_movement = $idstockmove; + $moline->fk_user_creat = DolibarrApiAccess::$user->id; + + $resultmoline = $moline->create(DolibarrApiAccess::$user); + if ($resultmoline <= 0) { + $error++; + throw new RestException(500, $moline->error); + } + $idstockmove = $stockmove->livraison(DolibarrApiAccess::$user, $value["objectid"], $value["fk_warehouse"], $qtytoprocess, 0, $labelmovement, dol_now(), '', '', $tmpproduct->status_batch, $id_product_batch, $codemovement); + } else { + $moline = new MoLine($this->db); + $moline->fk_mo = $this->mo->id; + $moline->position = $pos; + $moline->fk_product = $value["objectid"]; + $moline->fk_warehouse = $value["fk_warehouse"]; + $moline->qty = $qtytoprocess; + $moline->batch = $tmpproduct->status_batch; + $moline->role = 'toconsume'; + $moline->fk_mrp_production = ""; + $moline->fk_stock_movement = $idstockmove; + $moline->fk_user_creat = DolibarrApiAccess::$user->id; + + $resultmoline = $moline->create(DolibarrApiAccess::$user); + if ($resultmoline <= 0) { + $error++; + throw new RestException(500, $moline->error); + } + $idstockmove = $stockmove->reception(DolibarrApiAccess::$user, $value["objectid"], $value["fk_warehouse"], $qtytoprocess, 0, $labelmovement, dol_now(), '', '', $tmpproduct->status_batch, $id_product_batch, $codemovement); + } + if ($idstockmove < 0) { + $error++; + throw new RestException(500, $stockmove->error); + } + } + if (!$error) { + // Record consumption + $moline = new MoLine($this->db); + $moline->fk_mo = $this->mo->id; + $moline->position = $pos; + $moline->fk_product = $value["objectid"]; + $moline->fk_warehouse = $value["fk_warehouse"]; + $moline->qty = $qtytoprocess; + $moline->batch = $tmpproduct->status_batch; + if ($arrayname == "arraytoconsume") { + $moline->role = 'consumed'; + } else { + $moline->role = 'produced'; + } + $moline->fk_mrp_production = ""; + $moline->fk_stock_movement = $idstockmove; + $moline->fk_user_creat = DolibarrApiAccess::$user->id; + + $resultmoline = $moline->create(DolibarrApiAccess::$user); + if ($resultmoline <= 0) { + $error++; + throw new RestException(500, $moline->error); + } + + $pos++; + } + } + } + } + if (!$error) { + $consumptioncomplete = true; + $productioncomplete = true; + + if ($autoclose <= 0) { + $consumptioncomplete = false; + $productioncomplete = false; + } + } + } else { + $pos = 0; + foreach ($this->mo->lines as $line) { + if ($line->role == 'toconsume') { + $tmpproduct = new Product($this->db); + $tmpproduct->fetch($line->fk_product); + if ($line->qty != 0) { + $qtytoprocess = $line->qty; + if (isset($line->fk_warehouse)) { // If there is a warehouse to set + if (!($line->fk_warehouse > 0)) { // If there is no warehouse set. + $langs->load("errors"); + throw new RestException(500, $langs->trans("ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv("Warehouse"), $tmpproduct->ref)); + $error++; + } + if ($tmpproduct->status_batch) { + $langs->load("errors"); + throw new RestException(500, $langs->trans("ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv("Batch"), $tmpproduct->ref)); + $error++; + } + } + $idstockmove = 0; + if (!$error && $line->fk_warehouse > 0) { + // Record stock movement + $id_product_batch = 0; + $stockmove->origin = $this->mo; + if ($qtytoprocess >= 0) { + $idstockmove = $stockmove->livraison(DolibarrApiAccess::$user, $line->fk_product, $line->fk_warehouse, $qtytoprocess, 0, $labelmovement, dol_now(), '', '', $tmpproduct->status_batch, $id_product_batch, $codemovement); + } else { + $idstockmove = $stockmove->reception(DolibarrApiAccess::$user, $line->fk_product, $line->fk_warehouse, $qtytoprocess, 0, $labelmovement, dol_now(), '', '', $tmpproduct->status_batch, $id_product_batch, $codemovement); + } + if ($idstockmove < 0) { + $error++; + throw new RestException(500, $stockmove->error); + } + } + if (!$error) { + // Record consumption + $moline = new MoLine($this->db); + $moline->fk_mo = $this->mo->id; + $moline->position = $pos; + $moline->fk_product = $line->fk_product; + $moline->fk_warehouse = $line->fk_warehouse; + $moline->qty = $qtytoprocess; + $moline->batch = $tmpproduct->status_batch; + $moline->role = 'consumed'; + $moline->fk_mrp_production = $line->id; + $moline->fk_stock_movement = $idstockmove; + $moline->fk_user_creat = DolibarrApiAccess::$user->id; + + $resultmoline = $moline->create(DolibarrApiAccess::$user); + if ($resultmoline <= 0) { + $error++; + throw new RestException(500, $moline->error); + } + + $pos++; + } + } + } + } + $pos = 0; + foreach ($this->mo->lines as $line) { + if ($line->role == 'toproduce') { + $tmpproduct = new Product($this->db); + $tmpproduct->fetch($line->fk_product); + if ($line->qty != 0) { + $qtytoprocess = $line->qty; + if (isset($line->fk_warehouse)) { // If there is a warehouse to set + if (!($line->fk_warehouse > 0)) { // If there is no warehouse set. + $langs->load("errors"); + throw new RestException(500, $langs->trans("ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv("Warehouse"), $tmpproduct->ref)); + $error++; + } + if ($tmpproduct->status_batch) { + $langs->load("errors"); + throw new RestException(500, $langs->trans("ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv("Batch"), $tmpproduct->ref)); + $error++; + } + } + $idstockmove = 0; + if (!$error && $line->fk_warehouse > 0) { + // Record stock movement + $id_product_batch = 0; + $stockmove->origin = $this->mo; + if ($qtytoprocess >= 0) { + $idstockmove = $stockmove->livraison(DolibarrApiAccess::$user, $line->fk_product, $line->fk_warehouse, $qtytoprocess, 0, $labelmovement, dol_now(), '', '', $tmpproduct->status_batch, $id_product_batch, $codemovement); + } else { + $idstockmove = $stockmove->reception(DolibarrApiAccess::$user, $line->fk_product, $line->fk_warehouse, $qtytoprocess, 0, $labelmovement, dol_now(), '', '', $tmpproduct->status_batch, $id_product_batch, $codemovement); + } + if ($idstockmove < 0) { + $error++; + throw new RestException(500, $stockmove->error); + } + } + if (!$error) { + // Record consumption + $moline = new MoLine($this->db); + $moline->fk_mo = $this->mo->id; + $moline->position = $pos; + $moline->fk_product = $line->fk_product; + $moline->fk_warehouse = $line->fk_warehouse; + $moline->qty = $qtytoprocess; + $moline->batch = $tmpproduct->status_batch; + $moline->role = 'produced'; + $moline->fk_mrp_production = $line->id; + $moline->fk_stock_movement = $idstockmove; + $moline->fk_user_creat = DolibarrApiAccess::$user->id; + + $resultmoline = $moline->create(DolibarrApiAccess::$user); + if ($resultmoline <= 0) { + $error++; + throw new RestException(500, $moline->error); + } + + $pos++; + } + } + } + } + + if (!$error) { + $consumptioncomplete = true; + $productioncomplete = true; + + if ($autoclose > 0) { + foreach ($this->mo->lines as $line) { + if ($line->role == 'toconsume') { + $arrayoflines = $this->mo->fetchLinesLinked('consumed', $line->id); + $alreadyconsumed = 0; + foreach ($arrayoflines as $line2) { + $alreadyconsumed += $line2['qty']; + } + + if ($alreadyconsumed < $line->qty) { + $consumptioncomplete = false; + } + } + if ($line->role == 'toproduce') { + $arrayoflines = $this->mo->fetchLinesLinked('produced', $line->id); + $alreadyproduced = 0; + foreach ($arrayoflines as $line2) { + $alreadyproduced += $line2['qty']; + } + + if ($alreadyproduced < $line->qty) { + $productioncomplete = false; + } + } + } + } else { + $consumptioncomplete = false; + $productioncomplete = false; + } + } + } + // Update status of MO + dol_syslog("consumptioncomplete = ".$consumptioncomplete." productioncomplete = ".$productioncomplete); + //var_dump("consumptioncomplete = ".$consumptioncomplete." productioncomplete = ".$productioncomplete); + if ($consumptioncomplete && $productioncomplete) { + $result = $this->mo->setStatut($this->mo::STATUS_PRODUCED, 0, '', 'MRP_MO_PRODUCED'); + } else { + $result = $this->mo->setStatut($this->mo::STATUS_INPROGRESS, 0, '', 'MRP_MO_PRODUCED'); + } + if ($result <= 0) { + $error++; + throw new RestException(500, $this->mo->error); + } return $this->mo->id; } From d070c5b75d6b3d5a918cc290fdd0b15b9ccb413c Mon Sep 17 00:00:00 2001 From: lmarcouiller Date: Tue, 15 Jun 2021 15:13:25 +0200 Subject: [PATCH 5/5] Fix #17930 : input boxes can be empty as previously --- htdocs/opensurvey/wizard/choix_date.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/opensurvey/wizard/choix_date.php b/htdocs/opensurvey/wizard/choix_date.php index ce5f79b1174..817f3d88139 100644 --- a/htdocs/opensurvey/wizard/choix_date.php +++ b/htdocs/opensurvey/wizard/choix_date.php @@ -55,7 +55,7 @@ if (GETPOST('confirmation')) { $tmphorairesi = GETPOST('horaires'.$i, 'array'); - if (!is_array($tmphorairesi) || empty($tmphorairesi[$j])) { + if (!is_array($tmphorairesi)) { $errheure[$i][$j] = true; $erreur = true; continue; @@ -155,7 +155,7 @@ if (GETPOST('confirmation')) { } } - if (isset($errheure)) { + if (!empty($errheure)) { setEventMessages($langs->trans("ErrorBadFormat"), null, 'errors'); } }