This commit is contained in:
Laurent Destailleur 2020-01-03 15:01:14 +01:00
parent 68d7195964
commit 15ad41ee6d
5 changed files with 166 additions and 24 deletions

View File

@ -223,6 +223,7 @@ ErrorSearchCriteriaTooSmall=Search criteria too small.
ErrorObjectMustHaveStatusActiveToBeDisabled=Objects must have status 'Active' to be disabled
ErrorObjectMustHaveStatusDraftOrDisabledToBeActivated=Objects must have status 'Draft' or 'Disabled' to be enabled
ErrorNoFieldWithAttributeShowoncombobox=No fields has property 'showoncombobox' into definition of object '%s'. No way to show the combolist.
ErrorFieldRequiredForProduct=Field '%s' is required for product %s
# Warnings
WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup.
WarningPasswordSetWithNoAccount=A password was set for this member. However, no user account was created. So this password is stored but can't be used to login to Dolibarr. It may be used by an external module/interface but if you don't need to define any login nor password for a member, you can disable option "Manage a login for each member" from Member module setup. If you need to manage a login but don't need any password, you can keep this field empty to avoid this warning. Note: Email can also be used as a login if the member is linked to a user.

View File

@ -44,8 +44,8 @@ StatusMOProduced=Produced
QtyFrozen=Frozen Qty
QuantityFrozen=Frozen Quantity
QuantityConsumedInvariable=When this flag is set, the quantity consumed is always the value defined and is not relative to the quantity produced.
DisableStockChange=Disable stock change
DisableStockChangeHelp=When this flag is set, there is no stock change on this product, whatever is the quantity produced
DisableStockChange=Stock change disabled
DisableStockChangeHelp=When this flag is set, there is no stock change on this product, whatever is the quantity consumed
BomAndBomLines=Bills Of Material and lines
BOMLine=Line of BOM
WarehouseForProduction=Warehouse for production
@ -61,3 +61,5 @@ ForAQuantityOf1=For a quantity to produce of 1
ConfirmValidateMo=Are you sure you want to validate this Manufacturing Order?
ConfirmProductionDesc=By clicking on '%s', you will validate the consumption and/or production for the quantities set. This will also update the stock and record stock movements.
ProductionForRefAndDate=Production %s - %s
AutoCloseMO=Close automatically the Manufacturing Order if quantities to consume and to produce are reached
NoStockChangeOnServices=No stock change on services

View File

@ -505,7 +505,7 @@ class Mo extends CommonObject
}
/**
* Erase and update the line to produce
* Erase and update the line to produce.
*
* @param User $user User that modifies
* @return int <0 if KO, >0 if OK
@ -557,7 +557,11 @@ class Mo extends CommonObject
$moline = new MoLine($this->db);
$moline->fk_mo = $this->id;
$moline->qty = round($line->qty * $this->qty / $bom->efficiency, 2);
if ($line->qty_frozen) {
$moline->qty = $line->qty; // Qty to consume does not depends on quantity to produce
} else {
$moline->qty = round($line->qty * $this->qty / $bom->efficiency, 2);
}
if ($moline->qty <= 0) {
$error++;
$this->error = "BadValueForquantityToConsume";
@ -980,10 +984,16 @@ class Mo extends CommonObject
global $langs;
//$langs->load("mrp");
$this->labelStatus[self::STATUS_DRAFT] = $langs->trans('Draft');
$this->labelStatus[self::STATUS_VALIDATED] = $langs->trans('Validated');
$this->labelStatus[self::STATUS_VALIDATED] = $langs->trans('Validated').' ('.$langs->trans("ToProduce").')';
$this->labelStatus[self::STATUS_INPROGRESS] = $langs->trans('InProgress');
$this->labelStatus[self::STATUS_PRODUCED] = $langs->trans('StatusMOProduced');
$this->labelStatus[self::STATUS_CANCELED] = $langs->trans('Canceled');
$this->labelStatusShort[self::STATUS_DRAFT] = $langs->trans('Draft');
$this->labelStatusShort[self::STATUS_VALIDATED] = $langs->trans('Validated');
$this->labelStatusShort[self::STATUS_INPROGRESS] = $langs->trans('InProgress');
$this->labelStatusShort[self::STATUS_PRODUCED] = $langs->trans('StatusMOProduced');
$this->labelStatusShort[self::STATUS_CANCELED] = $langs->trans('Canceled');
}
$statusType = 'status'.$status;
@ -992,7 +1002,7 @@ class Mo extends CommonObject
if ($status == self::STATUS_PRODUCED) $statusType = 'status5';
if ($status == self::STATUS_CANCELED) $statusType = 'status6';
return dolGetStatus($this->labelStatus[$status], $this->labelStatus[$status], '', $statusType, $mode);
return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
}
/**
@ -1448,6 +1458,24 @@ class MoLine extends CommonObjectLine
}
}
/**
* Get list of lines linked to current line for a defined role
*
* @param string $role Get lines linked to current line with the selected role ('consumed', 'produced', ...)
* @return array Array of lines
*/
public function fetchLinesLinked($role) {
$array = array();
$sql = 'SELECT rowid, qty ';
$sql .= $this->getFieldList();
$sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')';
else $sql .= ' WHERE 1 = 1';
return $array;
}
/**
* Update object into database
*

View File

@ -117,8 +117,6 @@ $upload_dir = $conf->mrp->multidir_output[isset($object->entity) ? $object->enti
/*
* Actions
*
* Put here all code to do according to value of "action" parameter
*/
$parameters = array();

View File

@ -47,6 +47,7 @@ require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
dol_include_once('/mrp/class/mo.class.php');
dol_include_once('/mrp/lib/mrp_mo.lib.php');
@ -149,6 +150,89 @@ if (empty($reshook))
{
$object->setProject(GETPOST('projectid', 'int'));
}
if ($action == 'confirm_consumeandproduceall') {
$db->begin();
// Process line to consume
foreach($object->lines as $line) {
if ($line->role == 'toconsume') {
$tmpproduct = new Product($db);
$tmpproduct->fetch($line->fk_product);
$i=1;
while (GETPOSTISSET('qty-'.$line->id.'-'.$i)) {
// Check warehouse is set if we should have to
if (GETPOST('idwarehouse-'.$line->id.'-'.$i)) {
if (! (GETPOST('idwarehouse-'.$line->id.'-'.$i) > 0)) {
$langs->load("errors");
setEventMessages($langs->trans("ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv("Warehouse"), $tmpproduct->ref), null, 'errors');
$error++;
}
if ($tmpproduct->status_batch && (! GETPOST('batch-'.$line->id.'-'.$i))) {
$langs->load("errors");
setEventMessages($langs->trans("ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv("Batch"), $tmpproduct->ref), null, 'errors');
$error++;
}
}
if (! $error) {
}
$i++;
}
}
}
// Process line to produce
foreach($object->lines as $line) {
if ($line->role == 'toproduce') {
$tmpproduct = new Product($db);
$tmpproduct->fetch($line->fk_product);
$i=1;
while (GETPOSTISSET('qtytoproduce-'.$line->id.'-'.$i)) {
// Check warehouse is set if we should have to
if (GETPOST('idwarehousetoproduce-'.$line->id.'-'.$i)) {
if (! (GETPOST('idwarehousetoproduce-'.$line->id.'-'.$i) > 0)) {
$langs->load("errors");
setEventMessages($langs->trans("ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv("Warehouse"), $tmpproduct->ref), null, 'errors');
$error++;
}
if ($tmpproduct->status_batch && (! GETPOST('batchtoproduce-'.$line->id.'-'.$i))) {
$langs->load("errors");
setEventMessages($langs->trans("ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv("Batch"), $tmpproduct->ref), null, 'errors');
$error++;
}
}
if (! $error) {
}
$i++;
}
}
}
if (! $error) {
// Update status of MO
}
if ($error) {
$action = str_replace('confirm_', '', $action);
$db->rollback();
} else {
$db->commit();
}
}
}
@ -357,7 +441,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
{
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="add">';
print '<input type="hidden" name="action" value="confirm_'.$action.'">';
print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
print '<input type="hidden" name="id" value="'.$id.'">';
@ -375,9 +459,10 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
$defaultstockmovementcode = $object->ref.'_'.dol_print_date(dol_now(), 'dayhourlog');
print '<div class="center">';
print '<span class="opacitymedium hideonsmartphone">'.$langs->trans("ConfirmProductionDesc", $langs->transnoentitiesnoconv("Confirm")).'<br><br></span>';
print '<span class="opacitymedium hideonsmartphone">'.$langs->trans("ConfirmProductionDesc", $langs->transnoentitiesnoconv("Confirm")).'<br></span>';
print $langs->trans("MovementLabel").': <input type="text" class="minwidth300" name="label" value="'.$defaultstockmovementlabel.'"> &nbsp; ';
print $langs->trans("InventoryCode").': <input type="text" class="maxwidth150" name="inventorycode" value="'.$defaultstockmovementcode.'"> &nbsp; ';
print $langs->trans("InventoryCode").': <input type="text" class="minwidth200" name="inventorycode" value="'.$defaultstockmovementcode.'"><br><br>';
print '<input type="checkbox" name="autoclose" value="1" checked="checked"> '.$langs->trans("AutoCloseMO").'<br>';
print '<input class="button" type="submit" value="'.$langs->trans("Confirm").'" name="confirm">';
print ' &nbsp; ';
print '<input class="button" type="submit" value="'.$langs->trans("Cancel").'" name="cancel">';
@ -425,10 +510,24 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
$tmpproduct = new Product($db);
$tmpproduct->fetch($line->fk_product);
$arrayoflines = $line->fetchLinesLinked('consumed');
$alreadyconsumed = 0;
foreach($arrayoflines as $line2) {
$alreadyconsumed += $line2->qty;
}
print '<tr>';
print '<td>'.$tmpproduct->getNomUrl(1).'</td>';
print '<td>'.$line->qty.'</td>';
$alreadyconsumed = 0;
print '<td>';
$help = '';
if ($line->qty_frozen) $help.=($help ? '<br>' : '').'<strong>'.$langs->trans("QuantityFrozen").'</strong>: '.yn(1).' ('.$langs->trans("QuantityConsumedInvariable").')';
if ($line->disable_stock_change) $help.=($help ? '<br>' : '').'<strong>'.$langs->trans("DisableStockChange").'</strong>: '.yn(1).' ('.(($tmpproduct->type == Product::TYPE_SERVICE && empty($conf->global->STOCK_SUPPORTS_SERVICES)) ? $langs->trans("NoStockChangeOnServices") : $langs->trans("DisableStockChangeHelp")).')';
if ($help) {
print $form->textwithpicto($line->qty, $help);
} else {
print $line->qty;
}
print '</td>';
print '<td>'.$alreadyconsumed.'</td>';
print '<td></td>'; // Warehouse
if ($conf->productbatch->enabled) {
@ -440,19 +539,28 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
//$arrayoflines = $line->fetchLinesLinked('consumed');
if ($action == 'consumeandproduceall') {
$i = 1;
print '<tr>';
print '<td>'.$langs->trans("ToConsume").'</td>';
print '<td><input type="text" class="width50" name="qty-'.$line->id.'" value="'.max(0, $line->qty - $alreadyconsumed).'"></td>';
print '<td><input type="text" class="width50" name="qty-'.$line->id.'-'.$i.'" value="'.(GETPOSTISSET('qty-'.$line->id.'-'.$i) ? GETPOST('qty-'.$line->id.'-'.$i) : max(0, $line->qty - $alreadyconsumed)).'"></td>';
print '<td></td>';
print '<td>';
if ($tmpproduct->type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
print $formproduct->selectWarehouses('ifone', 'idwarehouse-'.$line->id, '', 1, 0, $line->fk_product, '', 1);
if (empty($line->disable_stock_change)) {
$preselected = (GETPOSTISSET('idwarehouse-'.$line->id.'-'.$i) ? GETPOST('idwarehouse-'.$line->id.'-'.$i) : 'ifone');
print $formproduct->selectWarehouses($preselected, 'idwarehouse-'.$line->id.'-'.$i, '', 1, 0, $line->fk_product, '', 1);
} else {
print '<span class="opacitymedium">'.$langs->trans("DisableStockChange").'</span>';
}
} else {
print '<span class="opacitymedium">'.$langs->trans("NoStockChangeOnServices").'</span>';
}
print '</td>';
if ($conf->productbatch->enabled) {
print '<td>';
if ($tmpproduct->status_batch) {
print '<input type="text" class="width50" name="batch-'.$line->id.'" value="">';
$preselected = (GETPOSTISSET('batch-'.$line->id.'-'.$i) ? GETPOST('batch-'.$line->id.'-'.$i) : '');
print '<input type="text" class="width50" name="batch-'.$line->id.'-'.$i.'" value="'.$preselected.'">';
}
print '</td>';
}
@ -508,12 +616,18 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
{
foreach($object->lines as $line) {
if ($line->role == 'toproduce') {
print '<tr>';
$tmpproduct = new Product($db);
$tmpproduct->fetch($line->fk_product);
$arrayoflines = $line->fetchLinesLinked('produced');
$alreadyproduced = 0;
foreach($arrayoflines as $line2) {
$alreadyproduced += $line2->qty;
}
print '<tr>';
print '<td>'.$tmpproduct->getNomUrl(1).'</td>';
print '<td>'.$line->qty.'</td>';
$alreadyproduced = 0;
print '<td>'.$alreadyproduced.'</td>';
print '<td></td>'; // Warehouse
if ($conf->productbatch->enabled) {
@ -521,23 +635,22 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
}
print '</tr>';
// Show detailed of already produced
//$arrayoflines = $line->fetchLinesLinked('produced');
if ($action == 'consumeandproduceall') {
print '<tr>';
print '<td>'.$langs->trans("ToProduce").'</td>';
print '<td><input type="text" class="width50" name="qty-'.$line->id.'" value="'.max(0, $line->qty - $alreadyproduced).'"></td>';
print '<td><input type="text" class="width50" name="qtytoproduce-'.$line->id.'-'.$i.'" value="'.(GETPOSTISSET('qtytoproduce-'.$line->id.'-'.$i) ? GETPOST('qtytoproduce-'.$line->id.'-'.$i) : max(0, $line->qty - $alreadyproduced)).'"></td>';
print '<td></td>';
print '<td>';
if ($tmpproduct->type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
print $formproduct->selectWarehouses('ifone', 'idwarehouse-'.$line->id, '', 1, 0, $line->fk_product, '', 1);
$preselected = (GETPOSTISSET('idwarehousetoproduce-'.$line->id.'-'.$i) ? GETPOST('idwarehousetoproduce-'.$line->id.'-'.$i) : ($object->fk_warehouse > 0 ? $object->fk_warehouse : 'ifone'));
print $formproduct->selectWarehouses($preselected, 'idwarehousetoproduce-'.$line->id.'-'.$i, '', 1, 0, $line->fk_product, '', 1);
}
print '</td>';
if ($conf->productbatch->enabled) {
print '<td>';
if ($tmpproduct->status_batch) {
print '<input type="text" class="width50" name="batch-'.$line->id.'" value="">';
$preselected = (GETPOSTISSET('batchtoproduce-'.$line->id.'-'.$i) ? GETPOST('batchtoproduce-'.$line->id.'-'.$i) : '');
print '<input type="text" class="width50" name="batchtoproduce-'.$line->id.'-'.$i.'" value="'.$preselected.'">';
}
print '</td>';
}