FIXME that are not bug are replaced with TODO

Add control on batch movement (lot/serial is mandatory, and control
eatby and sellby are same for each lot/serial)
This commit is contained in:
Laurent Destailleur 2015-04-12 04:01:28 +02:00
parent d76c1a9f42
commit 56a14da5d4
39 changed files with 338 additions and 199 deletions

View File

@ -270,28 +270,20 @@ class Skeleton_Class extends CommonObject
$resql = $this->db->query($sql);
if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
if (! $error)
if (! $error && ! $notrigger)
{
if (! $notrigger)
{
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
//// Call triggers
//$result=$this->call_trigger('MYOBJECT_MODIFY',$user);
//if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
//// End call triggers
}
//// Call triggers
//$result=$this->call_trigger('MYOBJECT_MODIFY',$user);
//if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
//// End call triggers
}
// Commit or rollback
if ($error)
{
foreach($this->errors as $errmsg)
{
dol_syslog(__METHOD__." ".$errmsg, LOG_ERR);
$this->error.=($this->error?', '.$errmsg:$errmsg);
}
$this->db->rollback();
return -1*$error;
}
@ -344,11 +336,6 @@ class Skeleton_Class extends CommonObject
// Commit or rollback
if ($error)
{
foreach($this->errors as $errmsg)
{
dol_syslog(__METHOD__." ".$errmsg, LOG_ERR);
$this->error.=($this->error?', '.$errmsg:$errmsg);
}
$this->db->rollback();
return -1*$error;
}

View File

@ -178,7 +178,7 @@ if ($result) {
/*
* Action
* FIXME Action must be set before any view part
* FIXME Action must be set before any view part to respect MVC
*/
// Bookkeeping Write

View File

@ -476,7 +476,7 @@ class Adherent extends CommonObject
$action='update';
// Actions on extra fields (by external module)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('memberdao'));
$parameters=array('id'=>$this->id);
$action='';

View File

@ -201,7 +201,7 @@ class Categorie extends CommonObject
$action='create';
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('HookModuleNamedao'));
$parameters=array('socid'=>$this->id);
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
@ -294,7 +294,7 @@ class Categorie extends CommonObject
$action='update';
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('HookCategorydao'));
$parameters=array();
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks

View File

@ -333,7 +333,7 @@ class ActionComm extends CommonObject
$action='create';
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('actioncommdao'));
$parameters=array('actcomm'=>$this->id);
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
@ -657,7 +657,7 @@ class ActionComm extends CommonObject
$action='update';
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('actioncommdao'));
$parameters=array('actcomm'=>$this->id);
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks

View File

@ -1144,7 +1144,7 @@ if (empty($reshook))
if (! $error)
{
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('propaldao'));
$parameters = array('id' => $object->id);
$reshook = $hookmanager->executeHooks('insertExtraFields', $parameters, $object, $action); // Note that $action and $object may have been

View File

@ -173,7 +173,7 @@ class Propal extends CommonObject
var $labelstatut_short=array();
var $specimen;
//Incorterms
var $fk_incoterms;
var $location_incoterms;
@ -958,7 +958,7 @@ class Propal extends CommonObject
$action='update';
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('propaldao'));
$parameters=array('socid'=>$this->id);
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
@ -1262,9 +1262,9 @@ class Propal extends CommonObject
//Incoterms
$this->fk_incoterms = $obj->fk_incoterms;
$this->location_incoterms = $obj->location_incoterms;
$this->location_incoterms = $obj->location_incoterms;
$this->libelle_incoterms = $obj->libelle_incoterms;
if ($obj->fk_statut == self::STATUS_DRAFT)
{
$this->brouillon = 1;
@ -1300,7 +1300,7 @@ class Propal extends CommonObject
$extrafieldsline=new ExtraFields($this->db);
$line = new PropaleLigne($this->db);
$extralabelsline=$extrafieldsline->fetch_name_optionals_label($line->table_element,true);
$num = $this->db->num_rows($result);
$i = 0;
@ -1353,7 +1353,7 @@ class Propal extends CommonObject
$line->date_end = $objp->date_end;
$line->fetch_optionals($line->id,$extralabelsline);
$this->lines[$i] = $line;
//dol_syslog("1 ".$line->fk_product);
//print "xx $i ".$this->lines[$i]->fk_product;
@ -1392,7 +1392,7 @@ class Propal extends CommonObject
$action='update';
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('propaldao'));
$parameters=array('id'=>$this->id);
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks

View File

@ -1117,7 +1117,7 @@ if (empty($reshook))
if (! $error)
{
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('orderdao'));
$parameters = array('id' => $object->id);
$reshook = $hookmanager->executeHooks('insertExtraFields', $parameters, $object, $action); // Note that $action and $object may have been modified by

View File

@ -877,7 +877,7 @@ class Commande extends CommonOrder
//$action='create';
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
/*$hookmanager->initHooks(array('orderdao'));
$parameters=array('socid'=>$this->id);
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
@ -2663,7 +2663,7 @@ class Commande extends CommonOrder
$action='create';
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('orderdao'));
$parameters=array('id'=>$this->id);
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks

View File

@ -1809,7 +1809,7 @@ if (empty($reshook))
if (! $error) {
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('invoicedao'));
$parameters = array('id' => $object->id);
$reshook = $hookmanager->executeHooks('insertExtraFields', $parameters, $object, $action); // Note that $action and $object may have been modified by

View File

@ -109,13 +109,21 @@ class Localtax extends CommonObject
if ($result < 0) $error++;
// End call triggers
//FIXME: Add rollback if trigger fail
return $this->id;
if (! $error)
{
$this->db->commit();
return $this->id;
}
else
{
$this->db->rollback();
return -1;
}
}
else
{
{
$this->error="Error ".$this->db->lasterror();
$this->db->rollback();
return -1;
}
}
@ -141,7 +149,9 @@ class Localtax extends CommonObject
$this->fk_user_creat=trim($this->fk_user_creat);
$this->fk_user_modif=trim($this->fk_user_modif);
// Update request
$this->db->begin();
// Update request
$sql = "UPDATE ".MAIN_DB_PREFIX."localtax SET";
$sql.= " localtaxtype=".$this->ltt.",";
$sql.= " tms=".$this->db->idate($this->tms).",";
@ -160,20 +170,27 @@ class Localtax extends CommonObject
if (! $resql)
{
$this->error="Error ".$this->db->lasterror();
return -1;
$error++;
}
if (! $notrigger)
if (! $error && ! $notrigger)
{
// Call trigger
$result=$this->call_trigger('LOCALTAX_MODIFY',$user);
if ($result < 0) $error++;
// End call triggers
//FIXME: Add rollback if trigger fail
}
return 1;
if (! $error)
{
$this->db->commit();
return 1;
}
else
{
$this->db->rollback();
return -1;
}
}

View File

@ -95,6 +95,8 @@ class PaymentSalary extends CommonObject
return -1;
}
$this->db->begin();
// Update request
$sql = "UPDATE ".MAIN_DB_PREFIX."payment_salary SET";
@ -129,11 +131,18 @@ class PaymentSalary extends CommonObject
$result=$this->call_trigger('PAYMENT_SALARY_MODIFY',$user);
if ($result < 0) $error++;
// End call triggers
//FIXME: Add rollback if trigger fail
}
return 1;
if (! $error)
{
$this->db->commit();
return 1;
}
else
{
$this->db->rollback();
return -1;
}
}

View File

@ -89,7 +89,9 @@ class Tva extends CommonObject
// Check parameters
// Put here code to add control on parameters values
// Insert request
$this->db->begin();
// Insert request
$sql = "INSERT INTO ".MAIN_DB_PREFIX."tva(";
$sql.= "tms,";
$sql.= "datep,";
@ -126,13 +128,22 @@ class Tva extends CommonObject
if ($result < 0) $error++;
// End call triggers
//FIXME: Add rollback if trigger fail
return $this->id;
if (! $error)
{
$this->db->commit();
return $this->id;
}
else
{
$this->db->rollback();
return -1;
}
}
else
{
$this->error="Error ".$this->db->lasterror();
return -1;
{
$this->error="Error ".$this->db->lasterror();
$this->db->rollback();
return -1;
}
}
@ -160,7 +171,9 @@ class Tva extends CommonObject
// Check parameters
// Put here code to add control on parameters values
// Update request
$this->db->begin();
// Update request
$sql = "UPDATE ".MAIN_DB_PREFIX."tva SET";
$sql.= " tms=".$this->db->idate($this->tms).",";
@ -181,20 +194,27 @@ class Tva extends CommonObject
if (! $resql)
{
$this->error="Error ".$this->db->lasterror();
return -1;
$error++;
}
if (! $notrigger)
if (! $error && ! $notrigger)
{
// Call trigger
$result=$this->call_trigger('TVA_MODIFY',$user);
if ($result < 0) $error++;
// End call triggers
//FIXME: Add rollback if trigger fail
}
return 1;
if (! $error)
{
$this->db->commit();
return 1;
}
else
{
$this->db->rollback();
return -1;
}
}

View File

@ -3215,7 +3215,7 @@ abstract class CommonObject
$marginInfo = $this->getMarginInfos($force_price);
if (! empty($conf->global->MARGIN_ADD_SHOWHIDE_BUTTON)) // FIXME Warning this feature rely on an external js file that may be removed. Using native js function document.cookie should be better
if (! empty($conf->global->MARGIN_ADD_SHOWHIDE_BUTTON)) // TODO Warning this feature rely on an external js file that may be removed. Using native js function document.cookie should be better
{
print $langs->trans('ShowMarginInfos').' : ';
$hidemargininfos = $_COOKIE['DOLUSER_MARGININFO_HIDE_SHOW'];

View File

@ -437,10 +437,7 @@ class DoliDBPgsql extends DoliDB
*/
function getDriverInfo()
{
// FIXME: Dummy method
// TODO: Implement
return '';
return 'pgsql php driver';
}
/**

View File

@ -345,10 +345,7 @@ class DoliDBSqlite extends DoliDB
*/
function getDriverInfo()
{
// FIXME: Dummy method
// TODO: Implement
return '';
return 'sqlite php driver';
}

View File

@ -365,10 +365,7 @@ class DoliDBSqlite3 extends DoliDB
*/
function getDriverInfo()
{
// FIXME: Dummy method
// TODO: Implement
return '';
return 'sqlite3 php driver';
}

View File

@ -1,4 +1,3 @@
//FIXME total not working
/* Copyright (C) 2014 delcroip <delcroip@gmail.com>
* Laurent Destailleur 2015 <eldy@users.sourceforge.net>
*

View File

@ -847,7 +847,7 @@ else if ($action == 'update_extras')
if (! $error)
{
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('interventiondao'));
$parameters=array('id'=>$object->id);
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks

View File

@ -1413,40 +1413,6 @@ class CommandeFournisseur extends CommonOrder
$now=dol_now();
// If a serial number is provided, we check that sellby and eatby match already existing serial
if ($batch)
{
$sql = "SELECT rowid, batch, eatby, sellby FROM ".MAIN_DB_PREFIX."product_batch WHERE batch = '".$this->db->escape($batch)."'";
dol_syslog(get_class($this)."::dispatchProduct scan serial to check if eatby and sellby match", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql)
{
$num = $this->db->num_rows($resql);
$i=0;
while ($i < $num)
{
$obj = $this->db->fetch_object($resql);
if ($obj->eatby != $eatby)
{
$this->error=$langs->trans("ThisSerialAlreadyExistWithDifferentDate", $batch, $obj->eatby);
return -1;
}
if ($obj->sellby != $sellby)
{
$this->error=$langs->trans("ThisSerialAlreadyExistWithDifferentDate", $batch, $obj->sellby);
return -1;
}
$i++;
}
}
else
{
dol_print_error($this->db);
return -1;
}
}
if (($this->statut == 3 || $this->statut == 4 || $this->statut == 5))
{
$this->db->begin();
@ -1468,13 +1434,11 @@ class CommandeFournisseur extends CommonOrder
$result=$this->call_trigger('LINEORDER_SUPPLIER_DISPATCH',$user);
if ($result < 0)
{
$this->db->rollback();
$error++;
return -1;
}
// End call triggers
}
$this->db->commit();
}
else
{
@ -1483,7 +1447,7 @@ class CommandeFournisseur extends CommonOrder
}
// Si module stock gere et que incrementation faite depuis un dispatching en stock
if (!$error && $entrepot > 0 && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER))
if (! $error && $entrepot > 0 && ! empty($conf->stock->enabled) && ! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER))
{
$mouv = new MouvementStock($this->db);
@ -1495,13 +1459,13 @@ class CommandeFournisseur extends CommonOrder
if ($result < 0)
{
$this->error=$mouv->error;
dol_syslog(get_class($this)."::dispatchProduct ".$this->error, LOG_ERR);
$this->errors=$mouv->errors;
dol_syslog(get_class($this)."::dispatchProduct ".$this->error." ".join(',',$this->errors), LOG_ERR);
$error++;
}
}
}
//TODO: Check if there is a current transaction in DB but seems not.
if ($error == 0)
{
$this->db->commit();

View File

@ -253,7 +253,7 @@ class FactureFournisseur extends CommonInvoice
$action='create';
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('supplierinvoicedao'));
$parameters=array('socid'=>$this->id);
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks

View File

@ -360,7 +360,7 @@ class ProductFournisseur extends Product
$this->fk_product = $obj->fk_product;
$this->fk_availability = $obj->fk_availability;
$this->delivery_time_days = $obj->delivery_time_days;
//$this->fourn_tva_npr = $obj->fourn_tva_npr; // FIXME this field not exist in llx_product_fournisseur_price
//$this->fourn_tva_npr = $obj->fourn_tva_npr; // TODO this field not exist in llx_product_fournisseur_price. We should add it ?
$this->fk_supplier_price_expression = $obj->fk_supplier_price_expression;
if (empty($ignore_expression) && !empty($this->fk_supplier_price_expression)) {

View File

@ -835,7 +835,7 @@ if (empty($reshook))
if (! $error)
{
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('supplierorderdao'));
$parameters=array('id'=>$object->id);

View File

@ -1139,7 +1139,7 @@ if (empty($reshook))
if (!$error)
{
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('supplierinvoicedao'));
$parameters=array('id'=>$object->id);

View File

@ -181,6 +181,8 @@ ALTER TABLE llx_stock_mouvement ADD COLUMN batch varchar(30) DEFAULT NULL;
ALTER TABLE llx_stock_mouvement ADD COLUMN eatby date DEFAULT NULL;
ALTER TABLE llx_stock_mouvement ADD COLUMN sellby date DEFAULT NULL;
UPDATE llx_product_batch SET batch = 'unknown' WHERE batch IS NULL;
ALTER TABLE llx_product_batch MODIFY COLUMN batch varchar(30) NOT NULL;
CREATE TABLE llx_expensereport (

View File

@ -16,5 +16,6 @@
--
-- ============================================================================
ALTER TABLE llx_product_batch ADD INDEX idx_fk_product_stock (fk_product_stock);
ALTER TABLE llx_product_batch ADD INDEX idx_fk_product_stock(fk_product_stock);
ALTER TABLE llx_product_batch ADD INDEX idx_batch(batch);
ALTER TABLE llx_product_batch ADD CONSTRAINT fk_product_batch_fk_product_stock FOREIGN KEY (fk_product_stock) REFERENCES llx_product_stock (rowid);

View File

@ -21,7 +21,7 @@ CREATE TABLE llx_product_batch (
fk_product_stock integer NOT NULL,
eatby datetime DEFAULT NULL,
sellby datetime DEFAULT NULL,
batch varchar(30) DEFAULT NULL,
batch varchar(30) NOT NULL,
qty double NOT NULL DEFAULT 0,
import_key varchar(14) DEFAULT NULL
) ENGINE=InnoDB;

View File

@ -3391,7 +3391,7 @@ function migrate_mode_reglement($db,$langs,$conf)
if ($resqla && $resql)
{
foreach($elements['tables'] as $table) // FIXME We must not update tables if oldid is not renamed
foreach($elements['tables'] as $table)
{
$sql = "UPDATE ".MAIN_DB_PREFIX.$table." SET ";
$sql.= "fk_mode_reglement = ".$elements['new_id'][$key];

View File

@ -541,8 +541,8 @@ Module6000Name=Workflow
Module6000Desc=Workflow management
Module20000Name=Leave Requests management
Module20000Desc=Declare and follow employees leaves requests
Module39000Name=Product batch
Module39000Desc=Batch or serial number, eat-by and sell-by date management on products
Module39000Name=Product lot
Module39000Desc=Lot or serial number, eat-by and sell-by date management on products
Module50000Name=PayBox
Module50000Desc=Module to offer an online payment page by credit card with PayBox
Module50100Name=Point of sales
@ -559,8 +559,6 @@ Module59000Name=Margins
Module59000Desc=Module to manage margins
Module60000Name=Commissions
Module60000Desc=Module to manage commissions
Module150010Name=Batch number, eat-by date and sell-by date
Module150010Desc=batch number, eat-by date and sell-by date management for product
Permission11=Read customer invoices
Permission12=Create/modify customer invoices
Permission13=Unvalidate customer invoices
@ -1543,7 +1541,7 @@ CashDeskBankAccountForCB= Default account to use to receive payments by credit c
CashDeskDoNotDecreaseStock=Disable stock decrease when a sell is done from Point of Sale (if "no", stock decrease is done for each sell done from POS, whatever is option set into module Stock).
CashDeskIdWareHouse=Force and restrict warehouse to use for stock decrease
StockDecreaseForPointOfSaleDisabled=Stock decrease from Point Of Sale disabled
StockDecreaseForPointOfSaleDisabledbyBatch=Stock decrease in POS is not compatible with batch management
StockDecreaseForPointOfSaleDisabledbyBatch=Stock decrease in POS is not compatible with lot management
CashDeskYouDidNotDisableStockDecease=You did not disable stock decrease when making a sell from Point Of Sale. So a warehouse is required.
##### Bookmark #####
BookmarkSetup=Bookmark module setup

View File

@ -159,7 +159,7 @@ ErrorPriceExpression22=Negative result '%s'
ErrorPriceExpressionInternal=Internal error '%s'
ErrorPriceExpressionUnknown=Unknown error '%s'
ErrorSrcAndTargetWarehouseMustDiffers=Source and target warehouses must differs
ErrorTryToMakeMoveOnProductRequiringBatchData=Error, trying to make a stock movement without batch/serial information, on a product requiring batch/serial information
ErrorTryToMakeMoveOnProductRequiringBatchData=Error, trying to make a stock movement without lot/serial information, on a product requiring lot/serial information
ErrorCantSetReceptionToTotalDoneWithReceptionToApprove=All recorded receptions must first be verified (approved or denied) before being allowed to do this action
ErrorCantSetReceptionToTotalDoneWithReceptionDenied=All recorded receptions must first be verified (approved) before being allowed to do this action
ErrorGlobalVariableUpdater0=HTTP request failed with error '%s'

View File

@ -1,22 +1,22 @@
# ProductBATCH language file - en_US - ProductBATCH
ManageLotSerial=Use batch/serial number
ProductStatusOnBatch=Yes (Batch/serial required)
ProductStatusNotOnBatch=No (Batch/serial not used)
ManageLotSerial=Use lot/serial number
ProductStatusOnBatch=Yes (lot/serial required)
ProductStatusNotOnBatch=No (lot/serial not used)
ProductStatusOnBatchShort=Yes
ProductStatusNotOnBatchShort=No
Batch=Batch/Serial
atleast1batchfield=Eat-by date or Sell-by date or Batch number
batch_number=Batch/Serial number
BatchNumberShort=Batch/Serial
Batch=Lot/Serial
atleast1batchfield=Eat-by date or Sell-by date or Lot/Serial number
batch_number=Lot/Serial number
BatchNumberShort=Lot/Serial
l_eatby=Eat-by date
l_sellby=Sell-by date
DetailBatchNumber=Batch/Serial details
DetailBatchFormat=Batch/Serial: %s - Eat by: %s - Sell by: %s (Qty : %d)
printBatch=Batch: %s
DetailBatchNumber=Lot/Serial details
DetailBatchFormat=Lot/Serial: %s - Eat by: %s - Sell by: %s (Qty : %d)
printBatch=Lot/Serial: %s
printEatby=Eat-by: %s
printSellby=Sell-by: %s
printQty=Qty: %d
AddDispatchBatchLine=Add a line for Shelf Life dispatching
BatchDefaultNumber=Undefined
WhenProductBatchModuleOnOptionAreForced=When module Batch/Serial is on, increase/decrease stock mode is forced to last choice and can't be edited. Other options can be defined as you want.
WhenProductBatchModuleOnOptionAreForced=When module Lot/Serial is on, increase/decrease stock mode is forced to last choice and can't be edited. Other options can be defined as you want.
ProductDoesNotUseBatchSerial=This product does not use batch/serial number

View File

@ -78,7 +78,7 @@ IdWarehouse=Id warehouse
DescWareHouse=Description warehouse
LieuWareHouse=Localisation warehouse
WarehousesAndProducts=Warehouses and products
WarehousesAndProductsBatchDetail=Warehouses and products (with detail per batch/serial)
WarehousesAndProductsBatchDetail=Warehouses and products (with detail per lot/serial)
AverageUnitPricePMPShort=Weighted average input price
AverageUnitPricePMP=Weighted average input price
SellPriceMin=Selling Unit Price
@ -132,5 +132,7 @@ IsInPackage=Contained into package
ShowWarehouse=Show warehouse
MovementCorrectStock=Stock content correction for product %s
MovementTransferStock=Stock transfer of product %s into another warehouse
WarehouseMustBeSelectedAtFirstStepWhenProductBatchModuleOn=Source warehouse must be defined here when batch module is on. It will be used to list wich lot/serial is available for product that required lot/serial data for movement. If you want to send products from different warehouses, just make the shipment into several steps.
WarehouseMustBeSelectedAtFirstStepWhenProductBatchModuleOn=Source warehouse must be defined here when "product lot" module is on. It will be used to list wich lot/serial is available for product that required lot/serial data for movement. If you want to send products from different warehouses, just make the shipment into several steps.
InventoryCodeShort=Inv./Mov. code
NoPendingReceptionOnSupplierOrder=No pending reception due to opened supplier order
ThisSerialAlreadyExistWithDifferentDate=This lot/serial number (<strong>%s</strong>) already exists but with different eatby or sellby date (found <strong>%s</strong> but you enter <strong>%s</strong>).

View File

@ -3146,6 +3146,8 @@ class Product extends CommonObject
else
{
$this->error=$movementstock->error;
$this->errors=$movementstock->errors;
$this->db->rollback();
return -1;
}
@ -3198,7 +3200,7 @@ class Product extends CommonObject
}
/**
* Load information about stock of a product into stock_warehouse[] and stock_reel
* Load information about stock of a product into stock_reel, stock_warehouse[] (including stock_warehouse[idwarehouse]->detail_batch for batch products)
*
* @return int < 0 if KO, > 0 if OK
*/

View File

@ -383,7 +383,6 @@ function activitytrim($product_type)
$result = $db->query($sql);
if ($result)
{
//$tmpyear=$beginyear; // FIXME $beginyear is not defined
$tmpyear=0;
$trim1=0;
$trim2=0;

View File

@ -67,10 +67,10 @@ class MouvementStock extends CommonObject
* @param date $eatby eat-by date
* @param date $sellby sell-by date
* @param string $batch batch number
* @param boolean $skip_sellby If set to true, stock mouvement is done without impacting batch record
* @param boolean $skip_batch If set to true, stock movement is done without impacting batch record
* @return int <0 if KO, 0 if fk_product is null, >0 if OK
*/
function _create($user, $fk_product, $entrepot_id, $qty, $type, $price=0, $label='', $inventorycode='', $datem='',$eatby='',$sellby='',$batch='',$skip_sellby=false)
function _create($user, $fk_product, $entrepot_id, $qty, $type, $price=0, $label='', $inventorycode='', $datem='',$eatby='',$sellby='',$batch='',$skip_batch=false)
{
global $conf, $langs;
@ -84,6 +84,16 @@ class MouvementStock extends CommonObject
// Check parameters
if (empty($fk_product)) return 0;
if ($eatby < 0)
{
$this->errors[]='ErrorBadValueForParameterEatBy';
return -1;
}
if ($sellby < 0)
{
$this->errors[]='ErrorBadValueForParameterEatBy';
return -1;
}
// Set properties of movement
$this->product_id = $fk_product;
@ -103,16 +113,53 @@ class MouvementStock extends CommonObject
$product->load_stock();
// Test if product require batch data. If yes, and there is not, we throw an error.
if ($product->hasbatch() && ! $skip_sellby)
if (! empty($conf->productbatch->enabled) && $product->hasbatch() && ! $skip_batch)
{
if (empty($batch) && empty($eatby) && empty($sellby))
//if (empty($batch) && empty($eatby) && empty($sellby))
if (empty($batch))
{
$this->errors[]="ErrorTryToMakeMoveOnProductRequiringBatchData";
$this->errors[]=$langs->trans("ErrorTryToMakeMoveOnProductRequiringBatchData", $product->name);
dol_syslog("Try to make a movement of a product with status_batch on without any batch data");
$this->db->rollback();
return -2;
}
// If a serial number is provided, we check that sellby and eatby match already existing serial
$sql = "SELECT pb.rowid, pb.batch, pb.eatby, pb.sellby FROM ".MAIN_DB_PREFIX."product_batch as pb, ".MAIN_DB_PREFIX."product_stock as ps";
$sql.= " WHERE pb.fk_product_stock = ps.rowid AND ps.fk_product = ".$fk_product." AND pb.batch = '".$this->db->escape($batch)."'";
dol_syslog(get_class($this)."::_create scan serial for this product to check if eatby and sellby match", LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql)
{
$num = $this->db->num_rows($resql);
$i=0;
while ($i < $num)
{
$obj = $this->db->fetch_object($resql);
if ($obj->eatby != $eatby)
{
$this->errors[]=$langs->trans("ThisSerialAlreadyExistWithDifferentDate", $batch, $obj->eatby, $eatby);
dol_syslog($langs->trans("ThisSerialAlreadyExistWithDifferentDate", $batch, $obj->eatby, $eatby));
$this->db->rollback();
return -3;
}
if ($obj->sellby != $sellby)
{
$this->errors[]=$langs->trans("ThisSerialAlreadyExistWithDifferentDate", $batch, $obj->sellby, $sellby);
dol_syslog($langs->trans("ThisSerialAlreadyExistWithDifferentDate", $batch, $obj->sellby, $sellby));
$this->db->rollback();
return -3;
}
$i++;
}
}
else
{
dol_print_error($this->db);
$this->db->rollback();
return -1;
}
}
// Define if we must make the stock change (If product type is a service or if stock is used also for services)
@ -157,7 +204,7 @@ class MouvementStock extends CommonObject
}
else
{
$this->error=$this->db->lasterror();
$this->errors[]=$this->db->lasterror();
$error = -1;
}
@ -190,7 +237,7 @@ class MouvementStock extends CommonObject
}
else
{
$this->error=$this->db->lasterror();
$this->errors[]=$this->db->lasterror();
$error = -2;
}
}
@ -212,7 +259,7 @@ class MouvementStock extends CommonObject
$resql=$this->db->query($sql);
if (! $resql)
{
$this->error=$this->db->lasterror();
$this->errors[]=$this->db->lasterror();
$error = -4;
}
*/
@ -266,7 +313,7 @@ class MouvementStock extends CommonObject
$resql=$this->db->query($sql);
if (! $resql)
{
$this->error=$this->db->lasterror();
$this->errors[]=$this->db->lasterror();
$error = -3;
}
else if(empty($fk_product_stock))
@ -276,8 +323,8 @@ class MouvementStock extends CommonObject
}
// Update detail stock for sell-by date
if (($product->hasbatch()) && (! $error) && (! $skip_sellby))
// Update detail stock for batch product
if (! $error && ! empty($conf->productbatch->enabled) && $product->hasbatch() && ! $skip_batch)
{
$param_batch=array('fk_product_stock' =>$fk_product_stock, 'eatby'=>$eatby, 'sellby'=>$sellby, 'batchnumber'=>$batch);
$result=$this->_create_batch($param_batch, $qty);
@ -296,7 +343,7 @@ class MouvementStock extends CommonObject
$resql=$this->db->query($sql);
if (! $resql)
{
$this->error=$this->db->lasterror();
$this->errors[]=$this->db->lasterror();
$error = -4;
}
}

View File

@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2013 Laurent Destaileur <ely@users.sourceforge.net>
* Copyright (C) 2014 Regis Houssin <regis.houssin@capnetworks.com>
/* Copyright (C) 2013-2015 Laurent Destaileur <ely@users.sourceforge.net>
* Copyright (C) 2014 Regis Houssin <regis.houssin@capnetworks.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -47,6 +47,7 @@ $action = GETPOST('action','alpha');
$id_product = GETPOST('productid', 'int');
$id_sw = GETPOST('id_sw', 'int');
$id_tw = GETPOST('id_tw', 'int');
$batch = GETPOST('batch');
$qty = GETPOST('qty');
$idline = GETPOST('idline');
@ -79,11 +80,6 @@ if ($action == 'addline')
$error++;
setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Product")),'errors');
}
if (! $qty)
{
$error++;
setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Qty")),'errors');
}
if (! ($id_sw > 0))
{
$error++;
@ -100,12 +96,32 @@ if ($action == 'addline')
$langs->load("errors");
setEventMessage($langs->trans("ErrorWarehouseMustDiffers"),'errors');
}
if (! $qty)
{
$error++;
setEventMessage($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("Qty")),'errors');
}
// Check a batch number is provided if product need it
if (! $error)
{
$producttmp=new Product($db);
$producttmp->fetch($id_product);
if ($producttmp->status_batch)
{
if (empty($batch))
{
$error++;
setEventMessage($langs->trans("ErrorTryToMakeMoveOnProductRequiringBatchData"), 'errors');
}
}
}
if (! $error)
{
if (count(array_keys($listofdata)) > 0) $id=max(array_keys($listofdata)) + 1;
else $id=1;
$listofdata[$id]=array('id'=>$id, 'id_product'=>$id_product, 'qty'=>$qty, 'id_sw'=>$id_sw, 'id_tw'=>$id_tw);
$listofdata[$id]=array('id'=>$id, 'id_product'=>$id_product, 'qty'=>$qty, 'id_sw'=>$id_sw, 'id_tw'=>$id_tw, 'batch'=>$batch);
$_SESSION['massstockmove']=json_encode($listofdata);
unset($id_product);
@ -145,6 +161,9 @@ if ($action == 'createmovements')
$id_sw=$val['id_sw'];
$id_tw=$val['id_tw'];
$qty=price2num($val['qty']);
$batch=$val['batch'];
$dlc=-1; // They are loaded later from serial
$dluo=-1; // They are loaded later from serial
if (! $error && $id_sw <> $id_tw && is_numeric($qty) && $id_product)
{
@ -154,39 +173,91 @@ if ($action == 'createmovements')
// Define value of products moved
$pricesrc=0;
if (isset($product->stock_warehouse[$id_sw]->pmp)) $pricesrc=$product->stock_warehouse[$id_sw]->pmp;
if (! empty($product->pmp)) $pricesrc=$product->pmp;
$pricedest=$pricesrc;
//print 'price src='.$pricesrc.', price dest='.$pricedest;exit;
// Remove stock
$result1=$product->correct_stock(
$user,
$id_sw,
$qty,
1,
GETPOST("label"),
$pricesrc
);
if ($result1 < 0)
if (empty($conf->productbatch->enabled) || ! $product->hasbatch()) // If product does not need lot/serial
{
$error++;
setEventMessage($product->errors,'errors');
}
// Remove stock
$result1=$product->correct_stock(
$user,
$id_sw,
$qty,
1,
GETPOST("label"),
$pricesrc,
GETPOST("codemove")
);
if ($result1 < 0)
{
$error++;
setEventMessage($product->errors,'errors');
}
// Add stock
$result2=$product->correct_stock(
$user,
$id_tw,
$qty,
0,
GETPOST("label"),
$pricedest
);
if ($result2 < 0)
// Add stock
$result2=$product->correct_stock(
$user,
$id_tw,
$qty,
0,
GETPOST("label"),
$pricedest,
GETPOST("codemove")
);
if ($result2 < 0)
{
$error++;
setEventMessage($product->errors,'errors');
}
}
else
{
$error++;
setEventMessage($product->errors,'errors');
// FIXME Seach record into product_batch table from serial to use same value for dlc and dluo
// FIXME MAke field batch lot required.
/*var_dump($batch);
var_dump($product->stock_warehouse);
exit;*/
// Remove stock
$result1=$product->correct_stock_batch(
$user,
$id_sw,
$qty,
1,
GETPOST("label"),
$pricesrc,
$dlc,
$dluo,
$batch,
GETPOST("codemove")
);
if ($result1 < 0)
{
$error++;
setEventMessage($product->errors,'errors');
}
// Add stock
$result2=$product->correct_stock_batch(
$user,
$id_tw,
$qty,
0,
GETPOST("label"),
$pricedest,
$dlc,
$dluo,
$batch,
GETPOST("codemove")
);
if ($result2 < 0)
{
$error++;
setEventMessage($product->errors,'errors');
}
}
}
else
@ -254,6 +325,11 @@ $param='';
print '<tr class="liste_titre">';
print getTitleFieldOfList($langs->trans('ProductRef'),0,$_SERVER["PHP_SELF"],'',$param,'','class="tagtd"',$sortfield,$sortorder);
print getTitleFieldOfList('');
if ($conf->productbatch->enabled)
{
print getTitleFieldOfList($langs->trans('Batch'),0,$_SERVER["PHP_SELF"],'',$param,'','class="tagtd"',$sortfield,$sortorder);
}
print getTitleFieldOfList($langs->trans('WarehouseSource'),0,$_SERVER["PHP_SELF"],'',$param,'','class="tagtd"',$sortfield,$sortorder);
print getTitleFieldOfList($langs->trans('WarehouseTarget'),0,$_SERVER["PHP_SELF"],'',$param,'','class="tagtd"',$sortfield,$sortorder);
print getTitleFieldOfList($langs->trans('Qty'),0,$_SERVER["PHP_SELF"],'',$param,'','align="center" class="tagtd"',$sortfield,$sortorder);
@ -276,6 +352,15 @@ else
}
print $form->select_produits($id_product,'productid',$filtertype,$limit);
print '</td>';
print '<td>';
print '</td>';
// Batch number
if ($conf->productbatch->enabled)
{
print '<td>';
print '<input type="text" name="batch" value="'.$batch.'">';
print '</td>';
}
// In warehouse
print '<td>';
print $formproduct->selectWarehouses($id_sw,'id_sw','',1);
@ -308,6 +393,12 @@ foreach($listofdata as $key => $val)
print $productstatic->getNomUrl(1);
$productstatic->ref=$oldref;
print '</td>';
if ($conf->productbatch->enabled)
{
print '<td>';
print $val['batch'];
print '</td>';
}
print '<td>';
print $warehousestatics->getNomUrl(1);
print '</td>';
@ -333,9 +424,16 @@ print '<input type="hidden" name="token" value="' .$_SESSION['newtoken'] . '">';
print '<input type="hidden" name="action" value="createmovements">';
// Button to record mass movement
$codemove=GETPOST('codemove');
$labelmovement=GETPOST("label")?GETPOST('label'):$langs->trans("StockTransfer").' '.dol_print_date($now,'%Y-%m-%d %H:%M');
print '<table class="border" width="100%">';
print '<tr>';
print '<td width="20%">'.$langs->trans("InventoryCode").'</td>';
print '<td colspan="5">';
print '<input type="text" name="codemove" size="10" value="'.dol_escape_htmltag($codemove).'">';
print '</td>';
print '</tr>';
print '<tr>';
print '<td width="20%">'.$langs->trans("LabelMovement").'</td>';
print '<td colspan="5">';

View File

@ -536,9 +536,11 @@ while ($i < ($limit ? min($num, $limit) : $num))
//virtual stock to compute the stock to buy value
$stocktobuy = max(max($objp->desiredstock, $objp->alertstock) - $stock - $ordered, 0);
$disabled = '';
if($ordered > 0) {
$compare = $usevirtualstock ? $stock : $stock + $ordered;
if($compare >= $objp->desiredstock) {
if ($ordered > 0)
{
$stockforcompare = $usevirtualstock ? $stock : $stock + $ordered;
if ($stockforcompare >= $objp->desiredstock)
{
$picto = img_picto('', './img/yes', '', 1);
$disabled = 'disabled="disabled"';
}
@ -546,7 +548,8 @@ while ($i < ($limit ? min($num, $limit) : $num))
$picto = img_picto('', './img/no', '', 1);
}
} else {
$picto = img_picto('', './img/no', '', 1);
//$picto = img_help('',$langs->trans("NoPendingReceptionOnSupplierOrder"));
$picto = img_picto($langs->trans("NoPendingReceptionOnSupplierOrder"), './img/no', '', 1);
}
print '<tr '.$bc[$var].'>';

View File

@ -895,7 +895,7 @@ class Societe extends CommonObject
$action='update';
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('thirdpartydao'));
$parameters=array('socid'=>$this->id);
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks

View File

@ -623,7 +623,7 @@ class UserGroup extends CommonObject
$action='create';
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('groupdao'));
$parameters=array();
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks
@ -694,7 +694,7 @@ class UserGroup extends CommonObject
$action='update';
// Actions on extra fields (by external module or standard code)
// FIXME le hook fait double emploi avec le trigger !!
// TODO le hook fait double emploi avec le trigger !!
$hookmanager->initHooks(array('groupdao'));
$parameters=array();
$reshook=$hookmanager->executeHooks('insertExtraFields',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks