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

This commit is contained in:
Laurent Destailleur 2021-06-15 22:23:46 +02:00
commit 8b238c43ce
5 changed files with 327 additions and 30 deletions

View File

@ -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:

View File

@ -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 <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
@ -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();

View File

@ -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

View File

@ -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;
}

View File

@ -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');
}
}