diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index e258011de76302868f978087d400bae310b3a38d..492c77f1dba20ac838843fce50dd3a435b65b3c9 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -73,12 +73,27 @@ if($action) || $action == 'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER' || $action == 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER') { + //Use variable cause empty(GETPOST()) do not work with php version < 5.4 + $valdispatch=GETPOST('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER','alpha'); + $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_BILL", '','chaine',0,'',$conf->entity); $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER", '','chaine',0,'',$conf->entity); $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER", '','chaine',0,'',$conf->entity); if ($action == 'STOCK_CALCULATE_ON_SUPPLIER_BILL') $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_BILL", GETPOST('STOCK_CALCULATE_ON_SUPPLIER_BILL','alpha'),'chaine',0,'',$conf->entity); if ($action == 'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER') $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER", GETPOST('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER','alpha'),'chaine',0,'',$conf->entity); - if ($action == 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER') $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER", GETPOST('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER','alpha'),'chaine',0,'',$conf->entity); + if ($action == 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER') $res=dolibarr_set_const($db, "STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER", $valdispatch,'chaine',0,'',$conf->entity); + if ($conf->workflow->enabled && !empty($conf->global->WORKFLOW_ORDER_CLASSIFY_RECEIPT_ORDER)) { + if (empty($valdispatch)) { + $res=dolibarr_set_const($db, "WORKFLOW_ORDER_CLASSIFY_RECEIPT_ORDER", '','chaine',0,'',$conf->entity); + } + } + if (empty($valdispatch)) { + $res=dolibarr_set_const($db, "SUPPLIER_ORDER_USE_DISPATCH_STATUS", '','chaine',0,'',$conf->entity); + } + } + + if($action == 'SUPPLIER_ORDER_USE_DISPATCH_STATUS') { + $res = dolibarr_set_const($db, "SUPPLIER_ORDER_USE_DISPATCH_STATUS", GETPOST('SUPPLIER_ORDER_USE_DISPATCH_STATUS','alpha'),'chaine',0,'',$conf->entity); } if($action == 'STOCK_USE_VIRTUAL_STOCK') { @@ -163,7 +178,7 @@ if (! empty($conf->facture->enabled)) } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module30Name")); + print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module30Name")); } print "</td>\n</tr>\n"; $found++; @@ -183,7 +198,7 @@ if (! empty($conf->commande->enabled)) } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module25Name")); + print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module25Name")); } print "</td>\n</tr>\n"; $found++; @@ -205,7 +220,7 @@ if (! empty($conf->expedition->enabled)) } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")); + print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")); } print "</td>\n</tr>\n"; $found++; @@ -225,7 +240,7 @@ if (! empty($conf->expedition->enabled)) } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")); + print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")); } print "</td>\n</tr>\n"; $found++; @@ -267,7 +282,7 @@ if (! empty($conf->fournisseur->enabled)) } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); + print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); } print "</td>\n</tr>\n"; $found++; @@ -288,7 +303,7 @@ if (! empty($conf->fournisseur->enabled)) } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); + print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); } print "</td>\n</tr>\n"; $found++; @@ -308,9 +323,30 @@ if (! empty($conf->fournisseur->enabled)) } else { - print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); + print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); } print "</td>\n</tr>\n"; + +if (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)) { + $var=!$var; + print "<tr ".$bc[$var].">"; + print '<td width="60%">'.$langs->trans("UseDispatchStatus").'</td>'; + print '<td width="160" align="right">'; + if (! empty($conf->fournisseur->enabled)) + { + print "<form method=\"post\" action=\"stock.php\">"; + print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">'; + print "<input type=\"hidden\" name=\"action\" value=\"SUPPLIER_ORDER_USE_DISPATCH_STATUS\">"; + print $form->selectyesno("SUPPLIER_ORDER_USE_DISPATCH_STATUS",$conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS,1,$disabled); + print '<input type="submit" class="button" value="'.$langs->trans("Modify").'"'.$disabled.'>'; + print "</form>\n"; + } + else + { + print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); + } + print "</td>\n</tr>\n"; +} $found++; /*if (! $found) @@ -446,13 +482,13 @@ print '<br>'; /* I keep the option/feature, but hidden to end users for the moment. If feature is used by module, no need to have users see it. If not used by a module, I still need to understand in which case user may need this now we can set rule on product page. -if ($conf->global->PRODUIT_SOUSPRODUITS) +if ($conf->global->PRODUIT_SOUSPRODUITS) { $var=!$var; - + print "<tr ".$bc[$var].">"; print '<td width="60%">'.$langs->trans("IndependantSubProductStock").'</td>'; - + print '<td width="160" align="right">'; print "<form method=\"post\" action=\"stock.php\">"; print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">'; diff --git a/htdocs/admin/workflow.php b/htdocs/admin/workflow.php index 28feb8ab23e8db8fd585eb5a59d3a40e408a6f2b..b81162c5cfaeeddf1f4488886d4f0b0cb125f9fb 100644 --- a/htdocs/admin/workflow.php +++ b/htdocs/admin/workflow.php @@ -79,6 +79,7 @@ $workflowcodes=array( // For the following 2 options, if module invoice is disabled, they does not exists, so "Classify billed" for order must be done manually from order card. 'WORKFLOW_INVOICE_CLASSIFY_BILLED_ORDER'=>array('family'=>'classify', 'position'=>40, 'enabled'=>'! empty($conf->facture->enabled) && ! empty($conf->commande->enabled)', 'picto'=>'bill','warning'=>'WarningCloseAlways'), 'WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER'=>array('family'=>'classify', 'position'=>50, 'enabled'=>'! empty($conf->facture->enabled) && ! empty($conf->commande->enabled)', 'picto'=>'bill','warning'=>'WarningCloseAlways'), + 'WORKFLOW_SUPPLIER_ORDER_CLASSIFY_RECEIPT_ORDER'=>array('family'=>'classify', 'position'=>50, 'enabled'=>'! empty($conf->fournisseur->enabled) && ! empty($conf->commande->enabled) && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)', 'picto'=>'order'), ); if (! empty($conf->modules_parts['workflow']) && is_array($conf->modules_parts['workflow'])) @@ -110,8 +111,8 @@ foreach($workflowcodes as $key => $params) print ' <td align="center">'.$langs->trans("Status").'</td>'; print "</tr>\n"; $oldfamily = $family; - } - + } + $var = !$var; print "<tr ".$bc[$var].">\n"; print "<td>".img_object('', $picto).$langs->trans('desc'.$key); diff --git a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php index b0b4893d485acb8bd05ddd9b9e8408421b395bcd..1da35108789e7a1b162c1940197f86dbc2b4c9f2 100644 --- a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php +++ b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php @@ -64,7 +64,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers $newobject->context['createfrompropal'] = 'createfrompropal'; $newobject->context['origin'] = $object->element; $newobject->context['origin_id'] = $object->id; - + $ret=$newobject->createFromProposal($object); if ($ret < 0) { $this->error=$newobject->error; $this->errors[]=$newobject->error; } return $ret; @@ -83,7 +83,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers $newobject->context['createfromorder'] = 'createfromorder'; $newobject->context['origin'] = $object->element; $newobject->context['origin_id'] = $object->id; - + $ret=$newobject->createFromOrder($object); if ($ret < 0) { $this->error=$newobject->error; $this->errors[]=$newobject->error; } return $ret; @@ -146,6 +146,59 @@ class InterfaceWorkflowManager extends DolibarrTriggers } } + // classify supplier order delivery status + if ($action == 'ORDER_SUPPLIER_DISPATCH') + { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + + if (! empty($conf->commande->enabled) && ! empty($conf->fournisseur->enabled) && ! empty($conf->global->WORKFLOW_SUPPLIER_ORDER_CLASSIFY_RECEIPT_ORDER)) + { + require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php'; + + $qtydelivered=array(); + $qtywished=array(); + + $supplierorderdispatch = new CommandeFournisseurDispatch($this->db); + $filter=array('t.fk_commande'=>$object->id); + if (!empty($conf->global->SUPPLIER_ORDER_USE_DISPATCH_STATUS)) { + $filter['t.status']=1; + } + $ret=$supplierorderdispatch->fetchAll('','',0,0,$filter); + if ($ret<0) { + $this->error=$supplierorderdispatch->error; $this->errors=$supplierorderdispatch->errors; + return $ret; + } else { + if (is_array($supplierorderdispatch->lines) && count($supplierorderdispatch->lines)>0) { + //Build array with quantity deliverd by product + foreach($supplierorderdispatch->lines as $line) { + $qtydelivered[$line->fk_product]+=$line->qty; + } + foreach($object->lines as $line) { + $qtywished[$line->fk_product]+=$line->qty; + } + //Compare array + $diff_array=array_diff_assoc($qtydelivered,$qtywished); + if (count($diff_array)==0) { + //No diff => mean everythings is received + $ret=$object->setStatus($user,5); + if ($ret<0) { + $this->error=$object->error; $this->errors=$object->errors; + } + } else { + //Diff => received partially + $ret=$object->setStatus($user,4); + if ($ret<0) { + $this->error=$object->error; $this->errors=$object->errors; + } + } + } + } + + + return $ret; + } + } + return 0; } diff --git a/htdocs/fourn/class/fournisseur.commande.dispatch.class.php b/htdocs/fourn/class/fournisseur.commande.dispatch.class.php index 4d6f75444b8f39a2bdee1b1f92f0edb709bfe52f..0464a9fb51f7aed0a25b869950ede616505f9f77 100644 --- a/htdocs/fourn/class/fournisseur.commande.dispatch.class.php +++ b/htdocs/fourn/class/fournisseur.commande.dispatch.class.php @@ -34,27 +34,28 @@ require_once(DOL_DOCUMENT_ROOT."/core/class/commonobject.class.php"); */ class CommandeFournisseurDispatch extends CommonObject { - var $db; //!< To store db handler - var $error; //!< To return error code (or message) - var $errors=array(); //!< To return several error codes (or messages) - var $element='commandefournisseurdispatch'; //!< Id that identify managed objects - var $table_element='commande_fournisseur_dispatch'; //!< Name of table without prefix where object is stored + public $db; //!< To store db handler + public $error; //!< To return error code (or message) + public $errors=array(); //!< To return several error codes (or messages) + public $element='commandefournisseurdispatch'; //!< Id that identify managed objects + public $table_element='commande_fournisseur_dispatch'; //!< Name of table without prefix where object is stored + public $lines=array(); - var $id; + public $id; - var $fk_commande; - var $fk_product; - var $fk_commandefourndet; - var $qty; - var $fk_entrepot; - var $fk_user; - var $datec=''; - var $comment; - var $status; - var $tms=''; - var $batch; - var $eatby=''; - var $sellby=''; + public $fk_commande; + public $fk_product; + public $fk_commandefourndet; + public $qty; + public $fk_entrepot; + public $fk_user; + public $datec=''; + public $comment; + public $status; + public $tms=''; + public $batch; + public $eatby=''; + public $sellby=''; @@ -539,4 +540,100 @@ class CommandeFournisseurDispatch extends CommonObject } + /** + * Load object in memory from the database + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit offset limit + * @param int $offset offset limit + * @param array $filter filter array + * @param string $filtermode filter mode (AND or OR) + * + * @return int <0 if KO, >0 if OK + */ + public function fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter = array(), $filtermode='AND') + { + dol_syslog(__METHOD__, LOG_DEBUG); + + $sql = "SELECT"; + $sql.= " t.rowid,"; + + $sql.= " t.fk_commande,"; + $sql.= " t.fk_product,"; + $sql.= " t.fk_commandefourndet,"; + $sql.= " t.qty,"; + $sql.= " t.fk_entrepot,"; + $sql.= " t.fk_user,"; + $sql.= " t.datec,"; + $sql.= " t.comment,"; + $sql.= " t.status,"; + $sql.= " t.tms,"; + $sql.= " t.batch,"; + $sql.= " t.eatby,"; + $sql.= " t.sellby"; + + $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; + + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key=='t.comment') { + $sqlwhere [] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\''; + } elseif ($key=='t.datec' || $key=='t.tms' || $key=='t.eatby' || $key=='t.sellby' || $key=='t.batch') { + $sqlwhere [] = $key . ' = \'' . $this->db->escape($value) . '\''; + } else { + $sqlwhere [] = $key . ' = ' . $this->db->escape($value); + } + } + } + if (count($sqlwhere) > 0) { + $sql .= ' WHERE ' . implode(' '.$filtermode.' ', $sqlwhere); + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield,$sortorder); + } + if (!empty($limit)) { + $sql .= ' ' . $this->db->plimit($limit + 1, $offset); + } + $this->lines = array(); + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + + while ($obj = $this->db->fetch_object($resql)) { + $line = new self($this->db); + + $line->id = $obj->rowid; + + $line->fk_commande = $obj->fk_commande; + $line->fk_product = $obj->fk_product; + $line->fk_commandefourndet = $obj->fk_commandefourndet; + $line->qty = $obj->qty; + $line->fk_entrepot = $obj->fk_entrepot; + $line->fk_user = $obj->fk_user; + $line->datec = $this->db->jdate($obj->datec); + $line->comment = $obj->comment; + $line->status = $obj->status; + $line->tms = $this->db->jdate($obj->tms); + $line->batch = $obj->batch; + $line->eatby = $this->db->jdate($obj->eatby); + $line->sellby = $this->db->jdate($obj->sellby); + + $this->lines[$line->id] = $line; + } + $this->db->free($resql); + + return $num; + } else { + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); + + return - 1; + } + } + } diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 8ea8ad609d1485d597903ef42ad1ada71e9a2a5a..10c463f71c4a905e500347599be2b7e08dbfa6e5 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -132,3 +132,4 @@ OpenAll=Open for all actions OpenInternal=Open for internal actions OpenShipping=Open for shippings OpenDispatch=Open for dispatch +UseDispatchStatus=Use dispatch status (aprouve/refuse) diff --git a/htdocs/langs/en_US/workflow.lang b/htdocs/langs/en_US/workflow.lang index 1c59a3651ec9fd5352e47e3558c43a670bf45178..f0634d638412896536f394822d20e23463072cf6 100644 --- a/htdocs/langs/en_US/workflow.lang +++ b/htdocs/langs/en_US/workflow.lang @@ -9,3 +9,4 @@ descWORKFLOW_ORDER_AUTOCREATE_INVOICE=Automatically create a customer invoice af descWORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL=Classify linked source proposal to billed when customer order is set to paid descWORKFLOW_INVOICE_CLASSIFY_BILLED_ORDER=Classify linked source customer order(s) to billed when customer invoice is set to paid descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER=Classify linked source customer order(s) to billed when customer invoice is validated +descWORKFLOW_SUPPLIER_ORDER_CLASSIFY_RECEIPT_ORDER=Classify supplier order status to Partially or Totally delivered on manual stock dispatch \ No newline at end of file