';
diff --git a/htdocs/install/mysql/migration/11.0.0-12.0.0.sql b/htdocs/install/mysql/migration/11.0.0-12.0.0.sql
index fa8cb0197cc..b9a5e535d21 100644
--- a/htdocs/install/mysql/migration/11.0.0-12.0.0.sql
+++ b/htdocs/install/mysql/migration/11.0.0-12.0.0.sql
@@ -43,6 +43,8 @@ create table llx_commande_fournisseur_dispatch_extrafields
ALTER TABLE llx_commande_fournisseur_dispatch_extrafields ADD INDEX idx_commande_fournisseur_dispatch_extrafields (fk_object);
+ALTER TABLE llx_product_fournisseur_price ADD COLUMN packaging double(24,8) DEFAULT 1;
+
UPDATE llx_accounting_system SET fk_country = NULL, active = 0 WHERE pcg_version = 'SYSCOHADA';
create table llx_c_shipment_package_type
diff --git a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql
index a9f1a669e52..4ba3eae2554 100644
--- a/htdocs/install/mysql/migration/12.0.0-13.0.0.sql
+++ b/htdocs/install/mysql/migration/12.0.0-13.0.0.sql
@@ -566,7 +566,8 @@ INSERT INTO llx_c_socialnetworks (entity, code, label, url, icon, active) VALUES
-- VMYSQL4.1 INSERT INTO llx_boxes_def (file, entity) SELECT 'box_customers_outstanding_bill_reached.php', 1 FROM DUAL WHERE NOT EXISTS (SELECT * FROM llx_boxes_def WHERE file = 'box_customers_outstanding_bill_reached.php' AND entity = 1);
-- VMYSQL4.1 INSERT INTO llx_boxes_def (file, entity) SELECT 'box_scheduled_jobs.php', 1 FROM DUAL WHERE NOT EXISTS (SELECT * FROM llx_boxes_def WHERE file = 'box_scheduled_jobs.php' AND entity = 1);
-ALTER TABLE llx_product_fournisseur_price ADD COLUMN packaging varchar(64);
+ALTER TABLE llx_product_fournisseur_price ADD COLUMN packaging varchar(64) DEFAULT NULL;
+ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging varchar(64) DEFAULT NULL;
ALTER TABLE llx_projet ADD COLUMN fk_opp_status_end integer DEFAULT NULL;
diff --git a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql
index d03d6b1f75c..0b6d36d6743 100644
--- a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql
+++ b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql
@@ -84,6 +84,9 @@ UPDATE llx_const set value = __ENCRYPT('eldy')__ WHERE __DECRYPT('value')__ = 'a
UPDATE llx_const set value = __ENCRYPT('eldy')__ WHERE __DECRYPT('value')__ = 'cameleo';
DELETE FROM llx_user_param where param = 'MAIN_THEME' and value in ('auguria', 'amarok', 'cameleo');
+ALTER TABLE llx_product_fournisseur_price ADD COLUMN packaging real DEFAULT NULL;
+ALTER TABLE llx_product_fournisseur_price MODIFY COLUMN packaging real DEFAULT NULL;
+
-- For v14
diff --git a/htdocs/install/mysql/tables/llx_product_fournisseur_price.sql b/htdocs/install/mysql/tables/llx_product_fournisseur_price.sql
index 4e1d75dd1dd..e5a0865ef68 100644
--- a/htdocs/install/mysql/tables/llx_product_fournisseur_price.sql
+++ b/htdocs/install/mysql/tables/llx_product_fournisseur_price.sql
@@ -50,8 +50,7 @@ create table llx_product_fournisseur_price
import_key varchar(14), -- Import key
delivery_time_days integer,
supplier_reputation varchar(10),
- packaging varchar(64),
-
+ packaging real DEFAULT NULL,
fk_multicurrency integer,
multicurrency_code varchar(255),
multicurrency_tx double(24,8) DEFAULT 1,
diff --git a/htdocs/langs/en_US/compta.lang b/htdocs/langs/en_US/compta.lang
index c5e1a58d243..efe1e51482b 100644
--- a/htdocs/langs/en_US/compta.lang
+++ b/htdocs/langs/en_US/compta.lang
@@ -146,9 +146,11 @@ ConfirmPaySalary=Are you sure you want to classify this salary card as paid?
DeleteSocialContribution=Delete a social or fiscal tax payment
DeleteVAT=Delete a VAT declaration
DeleteSalary=Delete a salary card
+DeleteVariousPayment=Delete a various payment
ConfirmDeleteSocialContribution=Are you sure you want to delete this social/fiscal tax payment ?
ConfirmDeleteVAT=Are you sure you want to delete this VAT declaration ?
-ConfirmDeleteSalary=Are you sure you want to delete this salary?
+ConfirmDeleteSalary=Are you sure you want to delete this salary ?
+ConfirmDeleteVariousPayment=Are you sure you want to delete this various payment ?
ExportDataset_tax_1=Social and fiscal taxes and payments
CalcModeVATDebt=Mode %sVAT on commitment accounting%s.
CalcModeVATEngagement=Mode %sVAT on incomes-expenses%s.
diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang
index 15043ce047e..37cc7a1b6fd 100644
--- a/htdocs/langs/en_US/errors.lang
+++ b/htdocs/langs/en_US/errors.lang
@@ -272,6 +272,8 @@ ErrorWrongFileName=Name of the file cannot have __SOMETHING__ in it
ErrorNotInDictionaryPaymentConditions=Not in Payment Terms Dictionary, please modify.
ErrorExecIdFailed=Can't execute command "id"
ErrorBadCharIntoLoginName=Unauthorized character in the login name
+ErrorInvoiceLoadThirdParty=Can't load third-party object for invoice "%s"
+ErrorInvoiceLoadThirdPartyKey=Third-party key "%s" no set for invoice "%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.
@@ -305,5 +307,8 @@ WarningTheHiddenOptionIsOn=Warning, the hidden option %s is on.
WarningCreateSubAccounts=Warning, you can't create directly a sub account, you must create a third party or an user and assign them an accounting code to find them in this list
WarningAvailableOnlyForHTTPSServers=Available only if using HTTPS secured connection.
WarningModuleXDisabledSoYouMayMissEventHere=Module %s has not been enabled. So you may miss a lot of event here.
+<<<<<<< HEAD
WarningPaypalPaymentNotCompatibleWithStrict=The value 'Strict' makes the online payment features not working correctly. Use 'Lax' instead.
+=======
+>>>>>>> branch '13.0' of git@github.com:Dolibarr/dolibarr.git
diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang
index 9018db40a5b..cbe9cca4d7a 100644
--- a/htdocs/langs/en_US/orders.lang
+++ b/htdocs/langs/en_US/orders.lang
@@ -102,6 +102,9 @@ ConfirmCancelOrder=Are you sure you want to cancel this order?
ConfirmMakeOrder=Are you sure you want to confirm you made this order on %s?
GenerateBill=Generate invoice
ClassifyShipped=Classify delivered
+PassedInShippedStatus=classified delivered
+YouCantShipThis=I can't classify this. Please check user permissions
+MustBeValidatedBefore=must be Validated or In process in order to be classified as shipped
DraftOrders=Draft orders
DraftSuppliersOrders=Draft purchase orders
OnProcessOrders=In process orders
diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang
index fecbe7450c2..7173d465ff2 100644
--- a/htdocs/langs/en_US/products.lang
+++ b/htdocs/langs/en_US/products.lang
@@ -345,7 +345,7 @@ UseProductFournDesc=Add a feature to define the descriptions of products defined
ProductSupplierDescription=Vendor description for the product
UseProductSupplierPackaging=Use packaging on supplier prices (recalculate quantities according to packaging set on supplier price when adding/updating line in supplier documents)
PackagingForThisProduct=Packaging
-PackagingForThisProductDesc=On supplier order, you will automaticly order this quantity (or a multiple of this quantity). Cannot be less than minimum buying quantity
+PackagingForThisProductDesc=You will automaticaly purchase a multiple of this quantity.
QtyRecalculatedWithPackaging=The quantity of the line were recalculated according to supplier packaging
#Attributes
diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang
index 2fda7e1df0e..1b3211e252c 100644
--- a/htdocs/langs/en_US/projects.lang
+++ b/htdocs/langs/en_US/projects.lang
@@ -274,4 +274,5 @@ AddPersonToTask=Add also to tasks
UsageOrganizeEvent=Usage: Event Organization
PROJECT_CLASSIFY_CLOSED_WHEN_ALL_TASKS_DONE=Classify project as closed when all its tasks are completed (100%% progress)
PROJECT_CLASSIFY_CLOSED_WHEN_ALL_TASKS_DONE_help=Note: existing projects with all tasks at 100 %% progress won't be affected: you will have to close them manually. This option only affects open projects.
-SelectLinesOfTimeSpentToInvoice=Select lines of time spent that are unbilled, then bulk action "Generate Invoice" to bill them
\ No newline at end of file
+SelectLinesOfTimeSpentToInvoice=Select lines of time spent that are unbilled, then bulk action "Generate Invoice" to bill them
+ErrorPROJECTLEADERRoleMissingRestoreIt=The "PROJECTLEADER" role is missing or has been de-activited, please restore in the dictionary of contact types
diff --git a/htdocs/langs/en_US/propal.lang b/htdocs/langs/en_US/propal.lang
index edbc08236d3..6acb50fe7bc 100644
--- a/htdocs/langs/en_US/propal.lang
+++ b/htdocs/langs/en_US/propal.lang
@@ -85,6 +85,22 @@ ProposalCustomerSignature=Written acceptance, company stamp, date and signature
ProposalsStatisticsSuppliers=Vendor proposals statistics
CaseFollowedBy=Case followed by
SignedOnly=Signed only
+NoSign=Set not signed
+NoSigned=set not signed
+CantBeNoSign=cannot be set not signed
+ConfirmMassNoSignature=Bulk Not signed confirmation
+ConfirmMassNoSignatureQuestion=Are you sure you want to set not signed the selected records ?
+IsNotADraft=is not a draft
+PassedInOpenStatus=has been validated
+CantBeSign=cannot be signed
+Sign=Sign
+Signed=signed
+CantBeSign=cannot be signed
+CantBeValidated=cannot be validated
+ConfirmMassValidation=Bulk Validate confirmation
+ConfirmMassSignature=Bulk Signature confirmation
+ConfirmMassValidationQuestion=Are you sure you want to validate the selected records ?
+ConfirmMassSignatureQuestion=Are you sure you want to sign the selected records ?
IdProposal=Proposal ID
IdProduct=Product ID
PrParentLine=Proposal Parent Line
diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang
index 16917384460..17ccbc35f83 100644
--- a/htdocs/langs/en_US/stocks.lang
+++ b/htdocs/langs/en_US/stocks.lang
@@ -176,7 +176,7 @@ ProductStockWarehouseCreated=Stock limit for alert and desired optimal stock cor
ProductStockWarehouseUpdated=Stock limit for alert and desired optimal stock correctly updated
ProductStockWarehouseDeleted=Stock limit for alert and desired optimal stock correctly deleted
AddNewProductStockWarehouse=Set new limit for alert and desired optimal stock
-AddStockLocationLine=Decrease quantity then click to add another warehouse for this product
+AddStockLocationLine=Decrease quantity then click to split the line
InventoryDate=Inventory date
Inventories=Inventories
NewInventory=New inventory
diff --git a/htdocs/langs/fr_FR/compta.lang b/htdocs/langs/fr_FR/compta.lang
index 280069f5cf9..be7a5f464ff 100644
--- a/htdocs/langs/fr_FR/compta.lang
+++ b/htdocs/langs/fr_FR/compta.lang
@@ -146,9 +146,11 @@ ConfirmPaySalary=Voulez-vous vraiment classer ce salaire comme payé ?
DeleteSocialContribution=Effacer une charge fiscale ou sociale
DeleteVAT=Supprimer une déclaration de TVA
DeleteSalary=Supprimer un salaire
+DeleteVariousPayment=Supprimer un paiement divers
ConfirmDeleteSocialContribution=Voulez-vous vraiment supprimer ce paiement de taxe sociale / fiscale?
ConfirmDeleteVAT=Voulez-vous vraiment supprimer cette déclaration de TVA ?
ConfirmDeleteSalary=Êtes-vous sûr de vouloir supprimer ce salaire ?
+ConfirmDeleteVariousPayment=Voulez-vous vraiment supprimer ce paiement divers ?
ExportDataset_tax_1=Taxes sociales et fiscales et paiements
CalcModeVATDebt=Mode %sTVA sur débit%s.
CalcModeVATEngagement=Mode %sTVA sur encaissement%s.
diff --git a/htdocs/langs/fr_FR/orders.lang b/htdocs/langs/fr_FR/orders.lang
index 16d1ecc2b27..3b0a3e38a7d 100644
--- a/htdocs/langs/fr_FR/orders.lang
+++ b/htdocs/langs/fr_FR/orders.lang
@@ -102,6 +102,9 @@ ConfirmCancelOrder=Êtes-vous sûr de vouloir annuler cette commande ?
ConfirmMakeOrder=Êtes-vous sûr de vouloir confirmer cette commande en date du %s ?
GenerateBill=Facturer
ClassifyShipped=Classer livrée
+PassedInShippedStatus=classée livrée
+YouCantShipThis=Classement impossible : veuillez vérifier les droits utilisateur
+MustBeValidatedBefore=doit être Validée ou En cours de livraison pour pouvoir être classée livrée
DraftOrders=Commandes brouillons
DraftSuppliersOrders=Commandes fournisseurs brouillons
OnProcessOrders=Commandes en cours de traitement
diff --git a/htdocs/langs/fr_FR/products.lang b/htdocs/langs/fr_FR/products.lang
index cec5c583ac9..54540b14109 100644
--- a/htdocs/langs/fr_FR/products.lang
+++ b/htdocs/langs/fr_FR/products.lang
@@ -346,7 +346,7 @@ UseProductFournDesc=Ajouter une fonctionnalité pour définir la description pro
ProductSupplierDescription=Description du fournisseur du produit
UseProductSupplierPackaging=Utiliser le conditionnement/emballage sur les prix fournisseur (recalculer les quantités en fonction de l'emballage défini sur le prix fournisseur lors de l'ajout / mise à jour de la ligne dans les documents fournisseurs)
PackagingForThisProduct=Emballage
-PackagingForThisProductDesc=Sur une commande fournisseur, vous commanderez automatiquement cette quantité ou un multiple. Vous ne pourrez pas saisir un montant inférieur
+PackagingForThisProductDesc=Sur une commande fournisseur, vous commanderez automatiquement cette quantité ou un multiple.
QtyRecalculatedWithPackaging=La quantité de la ligne a été recalculée en fonction de l'emballage du fournisseur
#Attributes
diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php
index d4abe482a88..97ac9adb6a3 100644
--- a/htdocs/mrp/class/mo.class.php
+++ b/htdocs/mrp/class/mo.class.php
@@ -112,8 +112,8 @@ class Mo extends CommonObject
'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'position'=>500, 'notnull'=>1,),
'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'position'=>501, 'notnull'=>1,),
'date_valid' => array('type'=>'datetime', 'label'=>'DateValidation', 'enabled'=>1, 'visible'=>-2, 'position'=>502,),
- 'fk_user_creat' => array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'position'=>510, 'notnull'=>1, 'foreignkey'=>'user.rowid', 'csslist'=>'tdoverflowmax100'),
- 'fk_user_modif' => array('type'=>'integer', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'position'=>511, 'notnull'=>-1, 'csslist'=>'tdoverflowmax100'),
+ 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'position'=>510, 'notnull'=>1, 'foreignkey'=>'user.rowid', 'csslist'=>'tdoverflowmax100'),
+ 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'position'=>511, 'notnull'=>-1, 'csslist'=>'tdoverflowmax100'),
'date_start_planned' => array('type'=>'datetime', 'label'=>'DateStartPlannedMo', 'enabled'=>1, 'visible'=>1, 'position'=>55, 'notnull'=>-1, 'index'=>1, 'help'=>'KeepEmptyForAsap'),
'date_end_planned' => array('type'=>'datetime', 'label'=>'DateEndPlannedMo', 'enabled'=>1, 'visible'=>1, 'position'=>56, 'notnull'=>-1, 'index'=>1,),
'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>1000, 'notnull'=>-1,),
diff --git a/htdocs/product/admin/product.php b/htdocs/product/admin/product.php
index fa75a20277f..ab54e292215 100644
--- a/htdocs/product/admin/product.php
+++ b/htdocs/product/admin/product.php
@@ -148,25 +148,8 @@ if ($action == 'other') {
$value = GETPOST('activate_FillProductDescAuto', 'alpha');
$res = dolibarr_set_const($db, "PRODUIT_AUTOFILL_DESC", $value, 'chaine', 0, '', $conf->entity);
- if ($value) {
- $sql_test = "SELECT count(desc_fourn) as cpt FROM ".MAIN_DB_PREFIX."product_fournisseur_price WHERE 1";
- $resql = $db->query($sql_test);
- if (!$resql && $db->lasterrno == 'DB_ERROR_NOSUCHFIELD') { // if the field does not exist, we create it
- $sql_new = "ALTER TABLE ".MAIN_DB_PREFIX."product_fournisseur_price ADD COLUMN desc_fourn text";
- $resql_new = $db->query($sql_new);
- }
- }
-
$value = GETPOST('activate_useProdSupplierPackaging', 'alpha');
$res = dolibarr_set_const($db, "PRODUCT_USE_SUPPLIER_PACKAGING", $value, 'chaine', 0, '', $conf->entity);
- if ($value) {
- $sql_test = "SELECT count(packaging) as cpt FROM ".MAIN_DB_PREFIX."product_fournisseur_price WHERE 1";
- $resql = $db->query($sql_test);
- if (!$resql && $db->lasterrno == 'DB_ERROR_NOSUCHFIELD') { // if the field does not exist, we create it
- $sql_new = "ALTER TABLE ".MAIN_DB_PREFIX."product_fournisseur_price ADD COLUMN packaging double(24,8) DEFAULT 1";
- $resql_new = $db->query($sql_new);
- }
- }
}
if ($action == 'specimen') { // For products
diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php
index 9b36c67643d..f77cd00ac8f 100644
--- a/htdocs/product/class/product.class.php
+++ b/htdocs/product/class/product.class.php
@@ -1947,7 +1947,10 @@ class Product extends CommonObject
$sql .= " pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code,";
$sql .= " pfp.packaging";
$sql .= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp";
- $sql .= " WHERE pfp.fk_product = ".((int) $product_id);
+ $sql .= " WHERE 1 = 1";
+ if ($product_id > 0) {
+ $sql .= " AND pfp.fk_product = ".((int) $product_id);
+ }
if ($fourn_ref != 'none') {
$sql .= " AND pfp.ref_fourn = '".$this->db->escape($fourn_ref)."'";
}
@@ -2189,7 +2192,8 @@ class Product extends CommonObject
$this->db->commit();
} else {
$this->db->rollback();
- dol_print_error($this->db);
+ $this->error = $this->db->lasterror();
+ return -1;
}
}
diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php
index 9aaa0aa2c8c..ea11843b625 100644
--- a/htdocs/product/fournisseurs.php
+++ b/htdocs/product/fournisseurs.php
@@ -320,9 +320,10 @@ if (empty($reshook)) {
if (empty($packaging)) {
$packaging = 1;
}
+ /* We can have a puchase ref that need to buy 100 min for a given price and with a packaging of 50.
if ($packaging < $quantity) {
$packaging = $quantity;
- }
+ }*/
$object->packaging = $packaging;
if (!empty($conf->multicurrency->enabled)) {
diff --git a/htdocs/product/price.php b/htdocs/product/price.php
index cef401bcc45..674b0a19cab 100644
--- a/htdocs/product/price.php
+++ b/htdocs/product/price.php
@@ -171,10 +171,15 @@ if (empty($reshook)) {
setEventMessages($object->error, $object->errors, 'errors');
}
- if ($error) {
+ if (!$error) {
//$localtaxarray=array('0'=>$localtax1_type,'1'=>$localtax1,'2'=>$localtax2_type,'3'=>$localtax2);
$localtaxarray = array(); // We do not store localtaxes into product, we will use instead the "vat code" to retrieve them.
- $object->updatePrice(0, $object->price_base_type, $user, $tva_tx, '', 0, $npr, 0, 0, $localtaxarray, $vatratecode);
+ $ret = $object->updatePrice(0, $object->price_base_type, $user, $tva_tx, '', 0, $npr, 0, 0, $localtaxarray, $vatratecode);
+
+ if ($ret < 0) {
+ $error++;
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
}
if (!$error) {
@@ -394,13 +399,21 @@ if (empty($reshook)) {
if ($action == 'activate_price_by_qty') {
// Activating product price by quantity add a new price line with price_by_qty set to 1
$level = GETPOST('level', 'int');
- $object->updatePrice(0, $object->price_base_type, $user, $object->tva_tx, 0, $level, $object->tva_npr, 1);
+ $ret = $object->updatePrice(0, $object->price_base_type, $user, $object->tva_tx, 0, $level, $object->tva_npr, 1);
+
+ if ($ret < 0) {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
}
// Unset Price by quantity
if ($action == 'disable_price_by_qty') {
// Disabling product price by quantity add a new price line with price_by_qty set to 0
$level = GETPOST('level', 'int');
- $object->updatePrice(0, $object->price_base_type, $user, $object->tva_tx, 0, $level, $object->tva_npr, 0);
+ $ret = $object->updatePrice(0, $object->price_base_type, $user, $object->tva_tx, 0, $level, $object->tva_npr, 0);
+
+ if ($ret < 0) {
+ setEventMessages($object->error, $object->errors, 'errors');
+ }
}
if ($action == 'edit_price_by_qty') { // Edition d'un prix par quantité
@@ -1483,13 +1496,17 @@ if ((empty($conf->global->PRODUIT_CUSTOMER_PRICES) || $action == 'showlog_defaul
// On l'ajoute donc pour remettre a niveau (pb vieilles versions)
// We emulate the change of the price from interface with the same value than the one into table llx_product
if (!empty($conf->global->PRODUIT_MULTIPRICES)) {
- $object->updatePrice(($object->multiprices_base_type[1] == 'TTC' ? $object->multiprices_ttc[1] : $object->multiprices[1]), $object->multiprices_base_type[1], $user, (empty($object->multiprices_tva_tx[1]) ? 0 : $object->multiprices_tva_tx[1]), ($object->multiprices_base_type[1] == 'TTC' ? $object->multiprices_min_ttc[1] : $object->multiprices_min[1]), 1);
+ $ret = $object->updatePrice(($object->multiprices_base_type[1] == 'TTC' ? $object->multiprices_ttc[1] : $object->multiprices[1]), $object->multiprices_base_type[1], $user, (empty($object->multiprices_tva_tx[1]) ? 0 : $object->multiprices_tva_tx[1]), ($object->multiprices_base_type[1] == 'TTC' ? $object->multiprices_min_ttc[1] : $object->multiprices_min[1]), 1);
} else {
- $object->updatePrice(($object->price_base_type == 'TTC' ? $object->price_ttc : $object->price), $object->price_base_type, $user, $object->tva_tx, ($object->price_base_type == 'TTC' ? $object->price_min_ttc : $object->price_min));
+ $ret = $object->updatePrice(($object->price_base_type == 'TTC' ? $object->price_ttc : $object->price), $object->price_base_type, $user, $object->tva_tx, ($object->price_base_type == 'TTC' ? $object->price_min_ttc : $object->price_min));
}
- $result = $db->query($sql);
- $num = $db->num_rows($result);
+ if ($ret < 0) {
+ dol_print_error($db, $object->error, $object->errors);
+ } else {
+ $result = $db->query($sql);
+ $num = $db->num_rows($result);
+ }
}
if ($num > 0) {
diff --git a/htdocs/projet/card.php b/htdocs/projet/card.php
index 89bdb013a32..93344b39cd0 100644
--- a/htdocs/projet/card.php
+++ b/htdocs/projet/card.php
@@ -180,9 +180,14 @@ if (empty($reshook)) {
$result = $object->create($user);
if (!$error && $result > 0) {
// Add myself as project leader
- $typeofcontact = 'PROJECTLEADER'; // TODO If use rename this code in dictionary, the add_contact will generate an error.
+ $typeofcontact = 'PROJECTLEADER';
$result = $object->add_contact($user->id, $typeofcontact, 'internal');
- if ($result < 0) {
+
+ // -3 means type not found (PROJECTLEADER renamed, de-activated or deleted), so don't prevent creation if it has been the case
+ if ($result == -3) {
+ setEventMessage('ErrorPROJECTLEADERRoleMissingRestoreIt', 'errors');
+ $error++;
+ } elseif ($result < 0) {
$langs->load("errors");
setEventMessages($object->error, $object->errors, 'errors');
$error++;
@@ -615,11 +620,11 @@ if ($action == 'create' && $user->rights->projet->creer) {
}
if (count($array) > 0) {
- print $form->selectarray('public', $array, GETPOSTISSET('public') ? GETPOST('public') : $object->public, 0, 0, 0, '', 0, 0, 0, '', '', 1);
+ print $form->selectarray('public', $array, GETPOST('public'), 0, 0, 0, '', 0, 0, 0, '', '', 1);
} else {
- print '';
+ print '';
- if ( (GETPOSTISSET('public') ? GETPOST('public') : $object->public)==0) {
+ if (GETPOST('public') == 0) {
print $langs->trans("PrivateProject");
} else {
print $langs->trans("SharedProject");
diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php
index 87ef51daefd..8d9f91afaca 100644
--- a/htdocs/projet/class/task.class.php
+++ b/htdocs/projet/class/task.class.php
@@ -1604,23 +1604,23 @@ class Task extends CommonObject
$this->db->begin();
- $sql = "DELETE FROM ".MAIN_DB_PREFIX."projet_task_time";
- $sql .= " WHERE rowid = ".$this->timespent_id;
-
- dol_syslog(get_class($this)."::delTimeSpent", LOG_DEBUG);
- $resql = $this->db->query($sql);
- if (!$resql) {
- $error++; $this->errors[] = "Error ".$this->db->lasterror();
+ if (!$notrigger) {
+ // Call trigger
+ $result = $this->call_trigger('TASK_TIMESPENT_DELETE', $user);
+ if ($result < 0) {
+ $error++;
+ }
+ // End call triggers
}
if (!$error) {
- if (!$notrigger) {
- // Call trigger
- $result = $this->call_trigger('TASK_TIMESPENT_DELETE', $user);
- if ($result < 0) {
- $error++;
- }
- // End call triggers
+ $sql = "DELETE FROM ".MAIN_DB_PREFIX."projet_task_time";
+ $sql .= " WHERE rowid = ".$this->timespent_id;
+
+ dol_syslog(get_class($this)."::delTimeSpent", LOG_DEBUG);
+ $resql = $this->db->query($sql);
+ if (!$resql) {
+ $error++; $this->errors[] = "Error ".$this->db->lasterror();
}
}
diff --git a/htdocs/reception/card.php b/htdocs/reception/card.php
index e5f5fccffad..fda5a3910b7 100644
--- a/htdocs/reception/card.php
+++ b/htdocs/reception/card.php
@@ -254,10 +254,10 @@ if (empty($reshook)) {
$object->origin = $origin;
$object->origin_id = $origin_id;
$object->fk_project = GETPOST('projectid', 'int');
- $object->weight = GETPOST('weight', 'int') == '' ? "NULL" : GETPOST('weight', 'int');
- $object->sizeH = GETPOST('sizeH', 'int') == '' ? "NULL" : GETPOST('sizeH', 'int');
- $object->sizeW = GETPOST('sizeW', 'int') == '' ? "NULL" : GETPOST('sizeW', 'int');
- $object->sizeS = GETPOST('sizeS', 'int') == '' ? "NULL" : GETPOST('sizeS', 'int');
+ $object->weight = GETPOST('weight', 'int') == '' ? null : GETPOST('weight', 'int');
+ $object->sizeH = GETPOST('sizeH', 'int') == '' ? null : GETPOST('sizeH', 'int');
+ $object->sizeW = GETPOST('sizeW', 'int') == '' ? null : GETPOST('sizeW', 'int');
+ $object->sizeS = GETPOST('sizeS', 'int') == '' ? null : GETPOST('sizeS', 'int');
$object->size_units = GETPOST('size_units', 'int');
$object->weight_units = GETPOST('weight_units', 'int');
@@ -679,7 +679,7 @@ if (empty($reshook)) {
$triggersendname = 'RECEPTION_SENTBYMAIL';
$paramname = 'id';
$mode = 'emailfromreception';
- $trackid = 'shi'.$object->id;
+ $trackid = 'rec'.$object->id;
include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
}
@@ -1921,15 +1921,16 @@ if ($action == 'create') {
// Warehouse source
if (!empty($conf->stock->enabled)) {
- print '
';
-
if ($lines[$i]->fk_entrepot > 0) {
$entrepot = new Entrepot($db);
$entrepot->fetch($lines[$i]->fk_entrepot);
- print $entrepot->getNomUrl(1);
- }
- print '
';
+ print '
';
+ print $entrepot->getNomUrl(1);
+ print '
';
+ } else {
+ print '
';
+ }
}
// Batch number managment
diff --git a/htdocs/reception/class/reception.class.php b/htdocs/reception/class/reception.class.php
index 5fb8e3b8af0..0be0ea7ba37 100644
--- a/htdocs/reception/class/reception.class.php
+++ b/htdocs/reception/class/reception.class.php
@@ -236,7 +236,6 @@ class Reception extends CommonObject
$this->user = $user;
-
$this->db->begin();
$sql = "INSERT INTO ".MAIN_DB_PREFIX."reception (";
@@ -273,12 +272,12 @@ class Reception extends CommonObject
$sql .= ", ".$this->fk_project;
$sql .= ", ".($this->shipping_method_id > 0 ? $this->shipping_method_id : "null");
$sql .= ", '".$this->db->escape($this->tracking_number)."'";
- $sql .= ", ".$this->weight;
- $sql .= ", ".$this->sizeS; // TODO Should use this->trueDepth
- $sql .= ", ".$this->sizeW; // TODO Should use this->trueWidth
- $sql .= ", ".$this->sizeH; // TODO Should use this->trueHeight
- $sql .= ", ".$this->weight_units;
- $sql .= ", ".$this->size_units;
+ $sql .= ", ".(is_null($this->weight) ? "NULL" : ((double) $this->weight));
+ $sql .= ", ".(is_null($this->sizeS) ? "NULL" : ((double) $this->sizeS)); // TODO Should use this->trueDepth
+ $sql .= ", ".(is_null($this->sizeW) ? "NULL" : ((double) $this->sizeW)); // TODO Should use this->trueWidth
+ $sql .= ", ".(is_null($this->sizeH) ? "NULL" : ((double) $this->sizeH)); // TODO Should use this->trueHeight
+ $sql .= ", ".(is_null($this->weight_units) ? "NULL" : ((double) $this->weight_units));
+ $sql .= ", ".(is_null($this->size_units) ? "NULL" : ((double) $this->size_units));
$sql .= ", ".(!empty($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null");
$sql .= ", ".(!empty($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : "null");
$sql .= ", ".(!empty($this->model_pdf) ? "'".$this->db->escape($this->model_pdf)."'" : "null");
@@ -566,7 +565,7 @@ class Reception extends CommonObject
// Loop on each product line to add a stock movement
// TODO in future, reception lines may not be linked to order line
- $sql = "SELECT cd.fk_product, cd.subprice,";
+ $sql = "SELECT cd.fk_product, cd.subprice, cd.remise_percent,";
$sql .= " ed.rowid, ed.qty, ed.fk_entrepot,";
$sql .= " ed.eatby, ed.sellby, ed.batch";
$sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as cd,";
@@ -592,12 +591,19 @@ class Reception extends CommonObject
$mouvS = new MouvementStock($this->db);
$mouvS->origin = &$this;
+ // get unit price with discount
+ $up_ht_disc = $obj->subprice;
+ if (!empty($obj->remise_percent) && empty($conf->global->STOCK_EXCLUDE_DISCOUNT_FOR_PMP)) {
+ $up_ht_disc = price2num($up_ht_disc * (100 - $obj->remise_percent) / 100, 'MU');
+ }
+
if (empty($obj->batch)) {
// line without batch detail
// We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record.
$inventorycode = '';
- $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ReceptionValidatedInDolibarr", $numref), '', '', '', '', 0, $inventorycode);
+ $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $qty, $up_ht_disc, $langs->trans("ReceptionValidatedInDolibarr", $numref), '', '', '', '', 0, $inventorycode);
+
if ($result < 0) {
$error++;
$this->errors[] = $mouvS->error;
@@ -610,7 +616,8 @@ class Reception extends CommonObject
// We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record.
// Note: ->fk_origin_stock = id into table llx_product_batch (may be rename into llx_product_stock_batch in another version)
$inventorycode = '';
- $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $qty, $obj->subprice, $langs->trans("ReceptionValidatedInDolibarr", $numref), $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, '', 0, $inventorycode);
+ $result = $mouvS->reception($user, $obj->fk_product, $obj->fk_entrepot, $qty, $up_ht_disc, $langs->trans("ReceptionValidatedInDolibarr", $numref), $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, '', 0, $inventorycode);
+
if ($result < 0) {
$error++;
$this->errors[] = $mouvS->error;
@@ -727,8 +734,14 @@ class Reception extends CommonObject
$line->qty = $qty;
$supplierorderline = new CommandeFournisseurLigne($this->db);
- $supplierorderline->fetch($id);
+ $result = $supplierorderline->fetch($id);
+ if ($result <= 0) {
+ $this->error = $supplierorderline->error;
+ $this->errors = $supplierorderline->errors;
+ return -1;
+ }
+ $fk_product = 0;
if (!empty($conf->stock->enabled) && !empty($supplierorderline->fk_product)) {
$fk_product = $supplierorderline->fk_product;
diff --git a/htdocs/reception/list.php b/htdocs/reception/list.php
index 8f07d1bede7..9f98202099a 100644
--- a/htdocs/reception/list.php
+++ b/htdocs/reception/list.php
@@ -491,6 +491,9 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."delivery as l ON l.rowid = ee.fk_target";
if (!$user->rights->societe->client->voir && !$socid) { // Internal user with no permission to see all
$sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
}
+$parameters = array();
+$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook
+$sql .= $hookmanager->resPrint;
$sql .= " WHERE e.entity IN (".getEntity('reception').")";
if (!$user->rights->societe->client->voir && !$socid) { // Internal user with no permission to see all
$sql .= " AND e.fk_soc = sc.fk_soc";
@@ -976,6 +979,9 @@ while ($i < min($num, $limit)) {
{
}*/
print "\n";
+ if (!$i) {
+ $totalarray['nbfield']++;
+ }
}
if (!empty($arrayfields['l.ref']['checked']) || !empty($arrayfields['l.date_delivery']['checked'])) {
@@ -1071,6 +1077,13 @@ if ($num == 0) {
print '
'.$langs->trans("NoRecordFound").'
';
}
+// Show total line
+include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php';
+
+$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
+$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook
+print $hookmanager->resPrint;
+
print "";
print "
";
print '';
diff --git a/htdocs/societe/admin/societe.php b/htdocs/societe/admin/societe.php
index c87289da390..ab6c6bd063d 100644
--- a/htdocs/societe/admin/societe.php
+++ b/htdocs/societe/admin/societe.php
@@ -1,9 +1,9 @@
- * Copyright (C) 2004 Eric Seigne
- * Copyright (C) 2005-2011 Laurent Destailleur
- * Copyright (C) 2005-2012 Regis Houssin
- * Copyright (C) 2011-2012 Juanjo Menent
+/* Copyright (C) 2004 Rodolphe Quiedeville
+ * Copyright (C) 2004 Eric Seigne
+ * Copyright (C) 2005-2011 Laurent Destailleur
+ * Copyright (C) 2005-2012 Regis Houssin
+ * Copyright (C) 2011-2012 Juanjo Menent
*
* 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
@@ -225,7 +225,7 @@ if ($action == "setaskforshippingmet") {
}
}
-//Activate "Disable prospect/customer type"
+// Activate "Disable prospect/customer type"
if ($action == "setdisableprospectcustomer") {
$setdisableprospectcustomer = GETPOST('value', 'int');
$res = dolibarr_set_const($db, "SOCIETE_DISABLE_PROSPECTSCUSTOMERS", $setdisableprospectcustomer, 'yesno', 0, '', $conf->entity);
diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php
index 668d8199b16..a88aec05618 100644
--- a/htdocs/societe/card.php
+++ b/htdocs/societe/card.php
@@ -6,7 +6,7 @@
* Copyright (C) 2005-2017 Regis Houssin
* Copyright (C) 2008 Patrick Raguin
* Copyright (C) 2010-2020 Juanjo Menent
- * Copyright (C) 2011-2013 Alexandre Spangaro
+ * Copyright (C) 2011-2022 Alexandre Spangaro
* Copyright (C) 2015 Jean-François Ferry
* Copyright (C) 2015 Marcos García
* Copyright (C) 2015 Raphaël Doursenaud
@@ -986,21 +986,24 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
$modCodeFournisseur = new $module;
// Define if customer/prospect or supplier status is set or not
- if (GETPOST("type") != 'f') {
+ if (GETPOST("type", 'aZ') != 'f') {
$object->client = -1;
if (!empty($conf->global->THIRDPARTY_CUSTOMERPROSPECT_BY_DEFAULT)) {
$object->client = 3;
}
}
// Prospect / Customer
- if (GETPOST("type") == 'c') {
+ if (GETPOST("type", 'aZ') == 'c') {
if (!empty($conf->global->THIRDPARTY_CUSTOMERTYPE_BY_DEFAULT)) {
$object->client = $conf->global->THIRDPARTY_CUSTOMERTYPE_BY_DEFAULT;
} else {
$object->client = 3;
}
}
- if (GETPOST("type") == 'p') {
+ if (!empty($conf->global->SOCIETE_DISABLE_PROSPECTSCUSTOMERS) && $object->client == 3) {
+ $object->client = 1;
+ }
+ if (GETPOST("type", 'aZ') == 'p') {
$object->client = 2;
}
if (((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && (GETPOST("type") == 'f' || (GETPOST("type") == '' && !empty($conf->global->THIRDPARTY_SUPPLIER_BY_DEFAULT)))) {
@@ -1757,21 +1760,21 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
if (GETPOSTISSET('name')) {
// We overwrite with values if posted
- $object->name = GETPOST('name', 'alphanohtml');
- $object->prefix_comm = GETPOST('prefix_comm', 'alphanohtml');
- $object->client = GETPOST('client', 'int');
- $object->code_client = GETPOST('customer_code', 'alpha');
- $object->fournisseur = GETPOST('fournisseur', 'int');
- $object->code_fournisseur = GETPOST('supplier_code', 'alpha');
- $object->address = GETPOST('address', 'alphanohtml');
- $object->zip = GETPOST('zipcode', 'alphanohtml');
- $object->town = GETPOST('town', 'alphanohtml');
- $object->country_id = GETPOST('country_id') ?GETPOST('country_id', 'int') : $mysoc->country_id;
- $object->state_id = GETPOST('state_id', 'int');
- //$object->skype = GETPOST('skype', 'alpha');
- //$object->twitter = GETPOST('twitter', 'alpha');
- //$object->facebook = GETPOST('facebook', 'alpha');
- //$object->linkedin = GETPOST('linkedin', 'alpha');
+ $object->name = GETPOST('name', 'alphanohtml');
+ $object->prefix_comm = GETPOST('prefix_comm', 'alphanohtml');
+ $object->client = GETPOST('client', 'int');
+ $object->code_client = GETPOST('customer_code', 'alpha');
+ $object->fournisseur = GETPOST('fournisseur', 'int');
+ $object->code_fournisseur = GETPOST('supplier_code', 'alpha');
+ $object->address = GETPOST('address', 'alphanohtml');
+ $object->zip = GETPOST('zipcode', 'alphanohtml');
+ $object->town = GETPOST('town', 'alphanohtml');
+ $object->country_id = GETPOST('country_id') ?GETPOST('country_id', 'int') : $mysoc->country_id;
+ $object->state_id = GETPOST('state_id', 'int');
+ //$object->skype = GETPOST('skype', 'alpha');
+ //$object->twitter = GETPOST('twitter', 'alpha');
+ //$object->facebook = GETPOST('facebook', 'alpha');
+ //$object->linkedin = GETPOST('linkedin', 'alpha');
$object->socialnetworks = array();
if (!empty($conf->socialnetworks->enabled)) {
foreach ($socialnetworks as $key => $value) {
diff --git a/htdocs/takepos/receipt.php b/htdocs/takepos/receipt.php
index 627a6c99565..b834ff64d0a 100644
--- a/htdocs/takepos/receipt.php
+++ b/htdocs/takepos/receipt.php
@@ -48,7 +48,7 @@ if (!isset($action)) {
}
include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
-$langs->loadLangs(array("main", "cashdesk", "companies"));
+$langs->loadLangs(array("main", "bills", "cashdesk", "companies"));
$place = (GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : 0); // $place is id of table for Bar or Restaurant
@@ -68,7 +68,7 @@ if (empty($user->rights->takepos->run)) {
top_httphead('text/html');
if ($place > 0) {
- $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture where ref='(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")'";
+ $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture where ref='(PROV-POS".$db->escape($_SESSION["takeposterminal"]."-".$place).")'";
$resql = $db->query($sql);
$obj = $db->fetch_object($resql);
if ($obj) {
@@ -79,6 +79,7 @@ $object = new Facture($db);
$object->fetch($facid);
// Call to external receipt modules if exist
+$parameters = array();
$hookmanager->initHooks(array('takeposfrontend'), $facid);
$reshook = $hookmanager->executeHooks('TakeposReceipt', $parameters, $object);
if (!empty($hookmanager->resPrint)) {
diff --git a/htdocs/variants/class/ProductCombination.class.php b/htdocs/variants/class/ProductCombination.class.php
index 6eb17a9bffb..ac9d5403671 100644
--- a/htdocs/variants/class/ProductCombination.class.php
+++ b/htdocs/variants/class/ProductCombination.class.php
@@ -536,7 +536,14 @@ class ProductCombination
$new_price += $variation_price;
}
- $child->updatePrice($new_price, $new_type, $user, $new_vat, $new_min_price, $i, $new_npr, $new_psq, 0, array(), $parent->default_vat_code);
+ $ret = $child->updatePrice($new_price, $new_type, $user, $new_vat, $new_min_price, $i, $new_npr, $new_psq, 0, array(), $parent->default_vat_code);
+
+ if ($ret < 0) {
+ $this->db->rollback();
+ $this->error = $child->error;
+ $this->errors = $child->errors;
+ return $ret;
+ }
}
}
} else {
@@ -558,7 +565,14 @@ class ProductCombination
$new_price += $this->variation_price;
}
- $child->updatePrice($new_price, $new_type, $user, $new_vat, $new_min_price, 1, $new_npr, $new_psq);
+ $ret = $child->updatePrice($new_price, $new_type, $user, $new_vat, $new_min_price, 1, $new_npr, $new_psq);
+
+ if ($ret < 0) {
+ $this->db->rollback();
+ $this->error = $child->error;
+ $this->errors = $child->errors;
+ return $ret;
+ }
}
$this->db->commit();
@@ -567,6 +581,8 @@ class ProductCombination
}
$this->db->rollback();
+ $this->error = $child->error;
+ $this->errors = $child->errors;
return -1;
}
diff --git a/htdocs/viewimage.php b/htdocs/viewimage.php
index 0e91bd5bc9f..feec8acf254 100644
--- a/htdocs/viewimage.php
+++ b/htdocs/viewimage.php
@@ -234,7 +234,14 @@ if (empty($modulepart)) {
accessforbidden('Bad value for parameter modulepart', 0, 0, 1);
}
-$check_access = dol_check_secure_access_document($modulepart, $original_file, $entity, $refname);
+// When logged in a different entity, medias cannot be accessed because $conf->$module->multidir_output
+// is not set on the requested entity, but they are public documents, so reset entity
+if ($modulepart === 'medias' && $entity != $conf->entity) {
+ $conf->entity = $entity;
+ $conf->setValues($db);
+}
+
+$check_access = dol_check_secure_access_document($modulepart, $original_file, $entity, $user, $refname);
$accessallowed = $check_access['accessallowed'];
$sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals'];
$fullpath_original_file = $check_access['original_file']; // $fullpath_original_file is now a full path name