diff --git a/htdocs/accountancy/admin/card.php b/htdocs/accountancy/admin/card.php index 15428e356c8..02b95cfd043 100644 --- a/htdocs/accountancy/admin/card.php +++ b/htdocs/accountancy/admin/card.php @@ -220,7 +220,7 @@ llxheader('', $title, $help_url); // Create mode -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans('NewAccountingAccount')); print '
'."\n"; diff --git a/htdocs/accountancy/admin/fiscalyear_card.php b/htdocs/accountancy/admin/fiscalyear_card.php index 96f9d988ebb..2aa33f21645 100644 --- a/htdocs/accountancy/admin/fiscalyear_card.php +++ b/htdocs/accountancy/admin/fiscalyear_card.php @@ -154,7 +154,7 @@ $help_url = "EN:Module_Double_Entry_Accounting"; llxHeader('', $title, $help_url); -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewFiscalYear")); print ''; diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index 5f4ebcc22fc..7c8c0dca547 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -340,7 +340,7 @@ if ($action == 'delete') { print $formconfirm; } -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("CreateMvts")); $object = new BookKeeping($db); diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 4731414f285..0096ba9a285 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -920,7 +920,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // ----------------------------------------- // Create mode - if ($action == 'create' || (empty($action) && empty($id))) { + if ($action == 'create') { $object->canvas = $canvas; $object->state_id = GETPOST('state_id', 'int'); diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index 9f0986ad8f2..ab4f0c7def0 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -253,7 +253,7 @@ $help_url = "EN:Module_EMail_Collector|FR:Module_Collecteur_de_courrier_électro llxHeader('', 'EmailCollector', $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewEmailCollector", $langs->transnoentitiesnoconv("EmailCollector"))); print ''; diff --git a/htdocs/admin/system/perf.php b/htdocs/admin/system/perf.php index 0bdb442863d..f43bc3bf49a 100644 --- a/htdocs/admin/system/perf.php +++ b/htdocs/admin/system/perf.php @@ -51,6 +51,9 @@ print load_fiche_titre($langs->trans("PerfDolibarr"), '', 'title_setup'); print ''.$langs->trans("YouMayFindPerfAdviceHere", 'https://wiki.dolibarr.org/index.php/FAQ_Increase_Performance').' ('.$langs->trans("Reload").')
'; +print '
'; +print '
'; + // Recupere la version de PHP $phpversion = version_php(); print "
PHP - ".$langs->trans("Version").": ".$phpversion."
\n"; diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index d38fe0f6b37..fae91d3ecb4 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -172,7 +172,7 @@ print ''; print ''; -print ''; +print ''; print '
'; print '
'.$langs->trans("ExportMethod").''; @@ -195,7 +195,7 @@ print '
'; print '
'; print ''; -print ''; +print ''; print ''; diff --git a/htdocs/asset/card.php b/htdocs/asset/card.php index be635bb17f6..d94ba613d91 100644 --- a/htdocs/asset/card.php +++ b/htdocs/asset/card.php @@ -166,7 +166,7 @@ $help_url = ''; llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("Asset")), '', 'object_'.$object->picto); print ''; diff --git a/htdocs/asset/model/card.php b/htdocs/asset/model/card.php index c1b5187cd3c..3d3ec2f67d2 100644 --- a/htdocs/asset/model/card.php +++ b/htdocs/asset/model/card.php @@ -138,7 +138,7 @@ $help_url = ''; llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("AssetModel")), '', 'object_' . $object->picto); print ''; diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index bc1bb0c5b11..ee619a589e3 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -268,7 +268,7 @@ $help_url ='EN:Module_BOM'; llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewBOM"), '', 'bom'); print ''; diff --git a/htdocs/bookmarks/card.php b/htdocs/bookmarks/card.php index 5f2e9ab5b81..bbc92a83ef1 100644 --- a/htdocs/bookmarks/card.php +++ b/htdocs/bookmarks/card.php @@ -144,7 +144,7 @@ $h++; $hselected = 'card'; -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { /* * Fact bookmark creation mode */ diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 5cc9d1b2217..351ab9212bc 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -923,7 +923,7 @@ $arrayrecurrulefreq = array( $help_url = 'EN:Module_Agenda_En|FR:Module_Agenda|ES:M&omodulodulo_Agenda'; llxHeader('', $langs->trans("Agenda"), $help_url); -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { $contact = new Contact($db); $socpeopleassigned = GETPOST("socpeopleassigned", 'array'); diff --git a/htdocs/comm/mailing/card.php b/htdocs/comm/mailing/card.php index 5e495d4c530..d46a02132a1 100644 --- a/htdocs/comm/mailing/card.php +++ b/htdocs/comm/mailing/card.php @@ -704,7 +704,7 @@ llxHeader( array() ); -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { // EMailing in creation mode print ''."\n"; print ''; diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 2fca1149cc5..06c36ce517c 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1537,7 +1537,7 @@ llxHeader('', $title, $help_url); $now = dol_now(); // Add new proposal -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { $currency_code = $conf->currency; print load_fiche_titre($langs->trans("NewProp"), '', 'propal'); diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index a07bc4850f0..ee25ea86eff 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -320,6 +320,8 @@ if (empty($reshook)) { $db->begin(); + $nbOrders = is_array($orders) ? count($orders) : 1; + foreach ($orders as $id_order) { $cmd = new Commande($db); if ($cmd->fetch($id_order) <= 0) { @@ -455,10 +457,11 @@ if (empty($reshook)) { $objecttmp->context['createfromclone']; - $rang = $lines[$i]->rang; + $rang = ($nbOrders > 1) ? -1 : $lines[$i]->rang; //there may already be rows from previous orders - if (!empty($createbills_onebythird)) + if (!empty($createbills_onebythird)) { $rang = $TFactThirdNbLines[$cmd->socid]; + } $result = $objecttmp->addline( $desc, diff --git a/htdocs/compta/bank/card.php b/htdocs/compta/bank/card.php index e1270b302b3..2751947c023 100644 --- a/htdocs/compta/bank/card.php +++ b/htdocs/compta/bank/card.php @@ -336,7 +336,7 @@ $help_url = 'EN:Module_Banks_and_Cash|FR:Module_Banques_et_Caisses|ES:Módulo_Ba // Creation -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { $object = new Account($db); $title = $langs->trans("NewFinancialAccount"); diff --git a/htdocs/compta/bank/various_payment/card.php b/htdocs/compta/bank/various_payment/card.php index a35eb091173..601ef04de45 100644 --- a/htdocs/compta/bank/various_payment/card.php +++ b/htdocs/compta/bank/various_payment/card.php @@ -339,7 +339,7 @@ foreach ($bankcateg->fetchAll() as $bankcategory) { } // Create mode -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { // Update fields properties in realtime if (!empty($conf->use_javascript_ajax)) { print "\n".''; // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewEval"), '', 'object_' . $object->picto); print ''; diff --git a/htdocs/hrm/job_card.php b/htdocs/hrm/job_card.php index c90ff0ce9dd..a9ec4f77121 100644 --- a/htdocs/hrm/job_card.php +++ b/htdocs/hrm/job_card.php @@ -180,7 +180,7 @@ llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewObject", $langs->transnoentities('Job')), '', 'object_' . $object->picto); print ''; diff --git a/htdocs/hrm/skill_card.php b/htdocs/hrm/skill_card.php index 795d7fab65f..3a27d5898c0 100644 --- a/htdocs/hrm/skill_card.php +++ b/htdocs/hrm/skill_card.php @@ -187,7 +187,7 @@ llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewSkill"), '', 'object_' . $object->picto); print ''; diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql index 28ae9ea2b7f..8e2b004efda 100644 --- a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql +++ b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql @@ -661,3 +661,5 @@ DELETE FROM llx_cronjob WHERE label = 'PurgeDeleteTemporaryFilesShort' AND param ALTER TABLE llx_cronjob DROP INDEX uk_cronjob; ALTER TABLE llx_cronjob ADD UNIQUE INDEX uk_cronjob (label, entity); + +ALTER TABLE llx_expedition ADD COLUMN billed smallint DEFAULT 0; diff --git a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql index 17414ab41d9..118c2f25124 100644 --- a/htdocs/install/mysql/migration/16.0.0-17.0.0.sql +++ b/htdocs/install/mysql/migration/16.0.0-17.0.0.sql @@ -42,6 +42,8 @@ ALTER TABLE llx_c_email_templates ADD COLUMN email_to varchar(255); ALTER TABLE llx_c_email_templates ADD COLUMN email_tocc varchar(255); ALTER TABLE llx_c_email_templates ADD COLUMN email_tobcc varchar(255); +ALTER TABLE llx_expedition ADD COLUMN billed smallint DEFAULT 0; + -- v17 diff --git a/htdocs/install/mysql/tables/llx_commande_fournisseur_dispatch.sql b/htdocs/install/mysql/tables/llx_commande_fournisseur_dispatch.sql index 974e10c09ff..058a74eea19 100644 --- a/htdocs/install/mysql/tables/llx_commande_fournisseur_dispatch.sql +++ b/htdocs/install/mysql/tables/llx_commande_fournisseur_dispatch.sql @@ -17,6 +17,10 @@ -- This table is just an history table to track all receiving done for a -- particular supplier order. A movement with same information is also done -- into stock_movement so this table may be useless. +-- +-- Detail of each lines of a reception (qty, batch and into wich warehouse is +-- received a purchase order line). +-- This table should be also name llx_receptiondet. -- =================================================================== create table llx_commande_fournisseur_dispatch diff --git a/htdocs/install/mysql/tables/llx_element_tag.key.sql b/htdocs/install/mysql/tables/llx_element_categorie.key.sql similarity index 71% rename from htdocs/install/mysql/tables/llx_element_tag.key.sql rename to htdocs/install/mysql/tables/llx_element_categorie.key.sql index d3a0b38afa9..0367eddc0a1 100644 --- a/htdocs/install/mysql/tables/llx_element_tag.key.sql +++ b/htdocs/install/mysql/tables/llx_element_categorie.key.sql @@ -1,5 +1,5 @@ -- ============================================================================ --- Copyright (C) 2021 Maxime Kohlhaas +-- Copyright (C) 2022 Charlene Benke -- -- 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 @@ -16,6 +16,7 @@ -- -- ============================================================================ -ALTER TABLE llx_element_tag ADD UNIQUE INDEX idx_element_tag_uk (fk_categorie, fk_element); -ALTER TABLE llx_element_tag ADD CONSTRAINT fk_element_tag_categorie_rowid FOREIGN KEY (fk_categorie) REFERENCES llx_categorie (rowid); +ALTER TABLE llx_element_categorie ADD UNIQUE INDEX idx_element_categorie_idx1 (fk_element, fk_categorie); + +ALTER TABLE llx_element_contact ADD CONSTRAINT fk_element_categorie_fk_categorie FOREIGN KEY (fk_categorie) REFERENCES llx_fk_categorie(rowid); diff --git a/htdocs/install/mysql/tables/llx_element_tag.sql b/htdocs/install/mysql/tables/llx_element_categorie.sql similarity index 90% rename from htdocs/install/mysql/tables/llx_element_tag.sql rename to htdocs/install/mysql/tables/llx_element_categorie.sql index d43ced98130..a1c7fddb0eb 100644 --- a/htdocs/install/mysql/tables/llx_element_tag.sql +++ b/htdocs/install/mysql/tables/llx_element_categorie.sql @@ -1,5 +1,5 @@ -- ============================================================================ --- Copyright (C) 2021 Maxime Kohlhaas +-- Copyright (C) 2022 charlene Benke -- -- 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 @@ -16,7 +16,7 @@ -- -- ============================================================================ -create table llx_element_tag +create table llx_element_categorie ( rowid integer AUTO_INCREMENT PRIMARY KEY, fk_categorie integer NOT NULL, diff --git a/htdocs/intracommreport/card.php b/htdocs/intracommreport/card.php index 938b99adf4c..681320e0d75 100644 --- a/htdocs/intracommreport/card.php +++ b/htdocs/intracommreport/card.php @@ -156,7 +156,7 @@ if ($action == 'add' && $permissiontoadd) { */ // Creation mode -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { $title = $langs->trans("IntracommReportTitle"); llxHeader("", $title); print load_fiche_titre($langs->trans("IntracommReportTitle")); diff --git a/htdocs/knowledgemanagement/knowledgerecord_card.php b/htdocs/knowledgemanagement/knowledgerecord_card.php index 74bd23608d0..baddd9e29a5 100644 --- a/htdocs/knowledgemanagement/knowledgerecord_card.php +++ b/htdocs/knowledgemanagement/knowledgerecord_card.php @@ -169,7 +169,7 @@ $help_url = ''; llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewKnowledgeRecord"), '', 'object_'.$object->picto); print ''; diff --git a/htdocs/langs/en_US/cashdesk.lang b/htdocs/langs/en_US/cashdesk.lang index b53eb235c29..07b91316771 100644 --- a/htdocs/langs/en_US/cashdesk.lang +++ b/htdocs/langs/en_US/cashdesk.lang @@ -136,4 +136,10 @@ PrintWithoutDetails=Print without details YearNotDefined=Year is not defined TakeposBarcodeRuleToInsertProduct=Barcode rule to insert product TakeposBarcodeRuleToInsertProductDesc=Rule to extract the product reference + a quantity from a scanned barcode.
If empty (default value), application will use the full barcode scanned to find the product.

If defined, syntax must be:
ref:NB+qu:NB+qd:NB+other:NB
where NB is the number of characters to use to extract data from the scanned barcode with:
  • ref : product reference
  • qu : quantity to set when inserting item (units)
  • qd : quantity to set when inserting item (decimals)
  • other : others characters
-AlreadyPrinted=Already printed \ No newline at end of file +AlreadyPrinted=Already printed +HideCategories=Hide categories +HideStockOnLine=Hide stock on line +ShowOnlyProductInStock=Show the products in stock +ShowCategoryDescription=Show category description +ShowProductReference=Show reference of products +UsePriceHT=Use price excl. taxes and not price incl. taxes \ No newline at end of file diff --git a/htdocs/langs/en_US/languages.lang b/htdocs/langs/en_US/languages.lang index 6de4824ecea..9350efef602 100644 --- a/htdocs/langs/en_US/languages.lang +++ b/htdocs/langs/en_US/languages.lang @@ -40,6 +40,7 @@ Language_es_AR=Spanish (Argentina) Language_es_BO=Spanish (Bolivia) Language_es_CL=Spanish (Chile) Language_es_CO=Spanish (Colombia) +Language_es_CR=Spanish (Costa Rica) Language_es_DO=Spanish (Dominican Republic) Language_es_EC=Spanish (Ecuador) Language_es_GT=Spanish (Guatemala) diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 9241120c9db..bfab238dc27 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -801,6 +801,7 @@ URLPhoto=URL of photo/logo SetLinkToAnotherThirdParty=Link to another third party LinkTo=Link to LinkToProposal=Link to proposal +LinkToExpedition= Link to expedition LinkToOrder=Link to order LinkToInvoice=Link to invoice LinkToTemplateInvoice=Link to template invoice diff --git a/htdocs/langs/fr_FR/cashdesk.lang b/htdocs/langs/fr_FR/cashdesk.lang index 24d35d56a06..5ce6fb98a5d 100644 --- a/htdocs/langs/fr_FR/cashdesk.lang +++ b/htdocs/langs/fr_FR/cashdesk.lang @@ -136,3 +136,9 @@ PrintWithoutDetails=Générer sans les détails YearNotDefined=L'année n'est pas définie TakeposBarcodeRuleToInsertProduct=Règle de lecture du code barre des produits TakeposBarcodeRuleToInsertProductDesc=Règle pour extraire la référence produit + une quantité d'un code barre scanné.
Si vide (valeur par défaut), l'application utilisera le code-barres complet scanné pour trouver le produit.

Si elle est définie, la syntaxe doit être:
ref: NB + Qu: NB + QD: NB + autres: NB
où NB est le nombre de caractères à utiliser pour extraire les données du code à barres scannés avec:
  • ref : référence produit
  • qu : quantité de jeu lors de l'insertion article (unités)
  • qd: quantité de jeu lors de l'insertion article (décimaux)
  • autre : autres caractères
+HideCategories=Masquer les catégories +HideStockOnLine=Masquer le stock en ligne +ShowOnlyProductInStock=Affficher les produits en stock +ShowCategoryDescription=Afficher la description des catégories +ShowProductReference=Afficher la référence des produits +UsePriceHT= Utiliser le prix HT et non en TTC \ No newline at end of file diff --git a/htdocs/langs/fr_FR/main.lang b/htdocs/langs/fr_FR/main.lang index 41b6188e16e..ce61fdbed8c 100644 --- a/htdocs/langs/fr_FR/main.lang +++ b/htdocs/langs/fr_FR/main.lang @@ -801,6 +801,7 @@ URLPhoto=URL de la photo/logo SetLinkToAnotherThirdParty=Lier vers un autre tiers LinkTo=Lier à LinkToProposal=Lier à une proposition commerciale +LinkToExpedition=Lier à une expédition LinkToOrder=Lier à une commande LinkToInvoice=Lier à une facture LinkToTemplateInvoice=Lien vers le modèle de facture diff --git a/htdocs/loan/card.php b/htdocs/loan/card.php index 047a64780b2..3ad898cda98 100644 --- a/htdocs/loan/card.php +++ b/htdocs/loan/card.php @@ -254,7 +254,7 @@ llxHeader("", $title, $help_url); // Create mode -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { //WYSIWYG Editor require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index 0d398fdcf53..b7a051c1bd9 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -242,7 +242,7 @@ llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { if (empty($permissiontoadd)) { accessforbidden($langs->trans('NotEnoughPermissions'), 0, 1); exit; diff --git a/htdocs/mrp/mo_card.php b/htdocs/mrp/mo_card.php index 178b51ec2bd..2c333ff616e 100644 --- a/htdocs/mrp/mo_card.php +++ b/htdocs/mrp/mo_card.php @@ -241,7 +241,7 @@ llxHeader('', $title, ''); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { if (GETPOST('fk_bom', 'int') > 0) { $titlelist = $langs->trans("ToConsume"); if ($objectbom->bomtype == 1) { diff --git a/htdocs/partnership/partnership_card.php b/htdocs/partnership/partnership_card.php index 82d9aa4d56e..08164421f60 100644 --- a/htdocs/partnership/partnership_card.php +++ b/htdocs/partnership/partnership_card.php @@ -259,7 +259,7 @@ $help_url = ''; llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewPartnership"), '', 'object_'.$object->picto); print ''; diff --git a/htdocs/product/inventory/card.php b/htdocs/product/inventory/card.php index daf9d386db7..0a21f9939ee 100644 --- a/htdocs/product/inventory/card.php +++ b/htdocs/product/inventory/card.php @@ -181,7 +181,7 @@ llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewInventory"), '', 'product'); print ''; diff --git a/htdocs/product/price.php b/htdocs/product/price.php index bf85d5dd15b..618e5cc6a78 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -1177,7 +1177,7 @@ if (!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_ if (empty($positiverates)) { $positiverates = '0'; } - echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), '%', $object->tva_npr); + echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), '%', $object->tva_npr, 0, 1); /* if ($object->default_vat_code) { diff --git a/htdocs/product/stock/card.php b/htdocs/product/stock/card.php index e58a15f906a..311b04a4c89 100644 --- a/htdocs/product/stock/card.php +++ b/htdocs/product/stock/card.php @@ -290,7 +290,7 @@ $help_url = 'EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks'; llxHeader("", $title, $help_url); -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewWarehouse"), '', 'stock'); dol_set_focus('input[name="libelle"]'); diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index 6af0e105b47..a0f3e9fa599 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -734,6 +734,15 @@ if ($id > 0 || $ref) { $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) ? '- '.$langs->trans("ReStockOnValidateOrder").'
' : ''); $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) ? '- '.$langs->trans("ReStockOnDispatchOrder").'
' : ''); $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) ? '- '.$langs->trans("StockOnReception").'
' : ''); + $parameters = array(); + $reshook = $hookmanager->executeHooks('physicalStockTextStockOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook > 0) { + $text_stock_options = $hookmanager->resPrint; + } elseif ($reshook == 0) { + $text_stock_options .= $hookmanager->resPrint; + } else { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } print ''; print $form->textwithpicto($langs->trans("PhysicalStock"), $text_stock_options, 1); @@ -820,6 +829,15 @@ if ($id > 0 || $ref) { $helpondiff .= $langs->trans("ProductQtyToConsumeByMO").': '.$object->stats_mrptoconsume['qty'].'
'; $helpondiff .= $langs->trans("ProductQtyToProduceByMO").': '.$object->stats_mrptoproduce['qty']; } + $parameters = array('found' => &$found, 'id' => $object->id, 'includedraftpoforvirtual' => null); + $reshook = $hookmanager->executeHooks('virtualStockHelpOnDiff', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook > 0) { + $helpondiff = $hookmanager->resPrint; + } elseif ($reshook == 0) { + $helpondiff .= $hookmanager->resPrint; + } else { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } // Calculating a theorical value diff --git a/htdocs/product/stock/productlot_card.php b/htdocs/product/stock/productlot_card.php index 8b2c0720c47..6e6f8991e83 100644 --- a/htdocs/product/stock/productlot_card.php +++ b/htdocs/product/stock/productlot_card.php @@ -378,7 +378,7 @@ llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("Batch"), '', 'object_'.$object->picto); print ''; diff --git a/htdocs/product/stock/stocktransfer/stocktransfer_card.php b/htdocs/product/stock/stocktransfer/stocktransfer_card.php index cf8f9fdf572..b009ace7275 100644 --- a/htdocs/product/stock/stocktransfer/stocktransfer_card.php +++ b/htdocs/product/stock/stocktransfer/stocktransfer_card.php @@ -413,7 +413,7 @@ print '}); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("StockTransfer")), '', 'object_'.$object->picto); print ''; diff --git a/htdocs/public/onlinesign/newonlinesign.php b/htdocs/public/onlinesign/newonlinesign.php index d1020dc2c1d..5e920444c35 100644 --- a/htdocs/public/onlinesign/newonlinesign.php +++ b/htdocs/public/onlinesign/newonlinesign.php @@ -328,7 +328,7 @@ if ($source == 'proposal') { // Object $text = ''.$langs->trans("SignatureProposalRef", $proposal->ref).''; - print ''.$langs->trans("Designation"); + print ''.$langs->trans("Designation"); print ''.$text; if ($proposal->status == $proposal::STATUS_VALIDATED) { $directdownloadlink = $proposal->getLastMainDocLink('proposal'); diff --git a/htdocs/reception/card.php b/htdocs/reception/card.php index c8feafb146d..ed4586a7376 100644 --- a/htdocs/reception/card.php +++ b/htdocs/reception/card.php @@ -728,7 +728,7 @@ if ($action == 'create2') { } // Mode creation. -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { $recept = new Reception($db); print load_fiche_titre($langs->trans("CreateReception")); diff --git a/htdocs/reception/class/reception.class.php b/htdocs/reception/class/reception.class.php index 9eec935728e..7244fdcb60b 100644 --- a/htdocs/reception/class/reception.class.php +++ b/htdocs/reception/class/reception.class.php @@ -846,6 +846,21 @@ class Reception extends CommonObject } } + // Check batch is set + $product = new Product($this->db); + $product->fetch($fk_product); + if (!empty($conf->productbatch->enabled)) { + $langs->load("errors"); + if (!empty($product->status_batch) && empty($batch)) { + $this->error = $langs->trans('ErrorProductNeedBatchNumber', $product->ref); + return -1; + } elseif (empty($product->status_batch) && !empty($batch)) { + $this->error = $langs->trans('ErrorProductDoesNotNeedBatchNumber', $product->ref); + return -1; + } + } + unset($product); + // extrafields $line->array_options = $supplierorderline->array_options; if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($array_options) && count($array_options) > 0) { diff --git a/htdocs/recruitment/recruitmentcandidature_card.php b/htdocs/recruitment/recruitmentcandidature_card.php index 076778fd56f..0da5badd7bc 100644 --- a/htdocs/recruitment/recruitmentcandidature_card.php +++ b/htdocs/recruitment/recruitmentcandidature_card.php @@ -283,7 +283,7 @@ llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("RecruitmentCandidature")), '', 'object_'.$object->picto); print ''; diff --git a/htdocs/recruitment/recruitmentjobposition_card.php b/htdocs/recruitment/recruitmentjobposition_card.php index f1567ae0ae4..b2172aca80d 100644 --- a/htdocs/recruitment/recruitmentjobposition_card.php +++ b/htdocs/recruitment/recruitmentjobposition_card.php @@ -202,7 +202,7 @@ $help_url = ''; llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewPositionToBeFilled"), '', 'object_'.$object->picto); print ''; diff --git a/htdocs/resource/card.php b/htdocs/resource/card.php index 40ba3e8b4dc..4ffbe1eb0a7 100644 --- a/htdocs/resource/card.php +++ b/htdocs/resource/card.php @@ -197,7 +197,7 @@ $form = new Form($db); $formresource = new FormResource($db); if ($action == 'create' || $object->fetch($id, $ref) > 0) { - if ($action == 'create' || (empty($action) && empty($id))) { + if ($action == 'create') { print load_fiche_titre($title, '', 'object_resource'); print dol_get_fiche_head(''); } else { diff --git a/htdocs/salaries/card.php b/htdocs/salaries/card.php index 86711022c1e..7d57575dacd 100644 --- a/htdocs/salaries/card.php +++ b/htdocs/salaries/card.php @@ -457,7 +457,7 @@ if ($id > 0) { } // Create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { $year_current = strftime("%Y", dol_now()); $pastmonth = strftime("%m", dol_now()) - 1; $pastmonthyear = $year_current; diff --git a/htdocs/societe/card.php b/htdocs/societe/card.php index c6b1aec4e4c..aa784d8639d 100644 --- a/htdocs/societe/card.php +++ b/htdocs/societe/card.php @@ -981,7 +981,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // ----------------------------------------- // When used in standard mode // ----------------------------------------- - if ($action == 'create' || (empty($action) && empty($id))) { + if ($action == 'create') { /* * Creation */ diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 77c8d9a03b2..d61d03b2be6 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -2,7 +2,7 @@ /* Copyright (C) 2017 Alexandre Spangaro * Copyright (C) 2017 Olivier Geffroy * Copyright (C) 2017 Saasprov - * Copyright (C) 2018-2021 Thibault FOUCART + * Copyright (C) 2018-2022 Thibault FOUCART * Copyright (C) 2018 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -104,6 +104,12 @@ if ($action == 'setvalue' && $user->admin) { if (!$result > 0) { $error++; } + if (GETPOSTISSET('STRIPE_LOCATION')) { + $result = dolibarr_set_const($db, "STRIPE_LOCATION", GETPOST('STRIPE_LOCATION', 'alpha'), 'chaine', 0, '', $conf->entity); + if (!$result > 0) { + $error++; + } + } $result = dolibarr_set_const($db, "ONLINE_PAYMENT_CSS_URL", GETPOST('ONLINE_PAYMENT_CSS_URL', 'alpha'), 'chaine', 0, '', $conf->entity); if (!$result > 0) { $error++; @@ -287,7 +293,7 @@ if (empty($conf->stripeconnect->enabled)) { print '
'; } print ''; - $out = img_picto('', 'globe').' '.$langs->trans("ToOfferALinkForLiveWebhook").' '; + $out = img_picto('', 'globe', 'class="pictofixedwidth"').' '.$langs->trans("ToOfferALinkForLiveWebhook").' '; $url = dol_buildpath('/public/stripe/ipn.php', 3); $out .= ''; $out .= ajax_autoselect("onlinelivewebhookurl", 0); @@ -347,23 +353,73 @@ print ''; print ''; print $langs->trans("StripeUserAccountForActions").''; -print img_picto('', 'user').$form->select_dolusers($conf->global->STRIPE_USER_ACCOUNT_FOR_ACTIONS, 'STRIPE_USER_ACCOUNT_FOR_ACTIONS', 0); +print img_picto('', 'user', 'class="pictofixedwidth"').$form->select_dolusers($conf->global->STRIPE_USER_ACCOUNT_FOR_ACTIONS, 'STRIPE_USER_ACCOUNT_FOR_ACTIONS', 0); print ''; print ''; print $langs->trans("BankAccount").''; -print img_picto('', 'bank_account').' '; +print img_picto('', 'bank_account', 'class="pictofixedwidth"'); $form->select_comptes($conf->global->STRIPE_BANK_ACCOUNT_FOR_PAYMENTS, 'STRIPE_BANK_ACCOUNT_FOR_PAYMENTS', 0, '', 1); print ''; if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { // What is this for ? print ''; print $langs->trans("BankAccountForBankTransfer").''; - print img_picto('', 'bank_account').' '; + print img_picto('', 'bank_account', 'class="pictofixedwidth"'); $form->select_comptes($conf->global->STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS, 'STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS', 0, '', 1); print ''; } +// Card Present for Stripe Terminal +if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code + print ''; + print $langs->trans("STRIPE_CARD_PRESENT").''; + if ($conf->use_javascript_ajax) { + print ajax_constantonoff('STRIPE_CARD_PRESENT'); + } else { + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $form->selectarray("STRIPE_CARD_PRESENT", $arrval, $conf->global->STRIPE_CARD_PRESENT); + } + print ''; +} + +// Locations for Stripe Terminal +if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code + print ''; + print $langs->trans("STRIPE_LOCATION").''; + $service = 'StripeTest'; + $servicestatus = 0; + if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) { + $service = 'StripeLive'; + $servicestatus = 1; + } + global $stripearrayofkeysbyenv; + $site_account = $stripearrayofkeysbyenv[$servicestatus]['secret_key']; + \Stripe\Stripe::setApiKey($site_account); + if (!empty($conf->stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha'))) { + $service = 'StripeTest'; + $servicestatus = '0'; + dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), '', 'warning'); + } else { + $service = 'StripeLive'; + $servicestatus = '1'; + } + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + if ($stripeacc) { + $locations = \Stripe\Terminal\Location::all('', array("stripe_account" => $stripeacc)); + } else { + $locations = \Stripe\Terminal\Location::all(); + } + $location = array(); + $location[""] = $langs->trans("EmptyLocation"); + foreach ($locations as $locations) { + $location[$locations->id] = $locations->display_name; + } + print $form->selectarray("STRIPE_LOCATION", $location, $conf->global->STRIPE_LOCATION); + print ''; +} + // Activate Payment Request API if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code print ''; diff --git a/htdocs/stripe/ajax/ajax.php b/htdocs/stripe/ajax/ajax.php new file mode 100644 index 00000000000..cf6ec53d580 --- /dev/null +++ b/htdocs/stripe/ajax/ajax.php @@ -0,0 +1,124 @@ + + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/stripe/ajax/ajax.php + * \brief Ajax action for Stipe ie: Terminal + */ + +if (!defined('NOCSRFCHECK')) { + define('NOCSRFCHECK', '1'); +} +if (!defined('NOTOKENRENEWAL')) { + define('NOTOKENRENEWAL', '1'); +} +if (!defined('NOREQUIREMENU')) { + define('NOREQUIREMENU', '1'); +} +if (!defined('NOREQUIREHTML')) { + define('NOREQUIREHTML', '1'); +} +if (!defined('NOREQUIREAJAX')) { + define('NOREQUIREAJAX', '1'); +} +if (!defined('NOBROWSERNOTIF')) { + define('NOBROWSERNOTIF', '1'); +} + +require '../../main.inc.php'; // Load $user and permissions +require_once DOL_DOCUMENT_ROOT.'/includes/stripe/stripe-php/init.php'; +require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + +$action = GETPOST('action', 'aZ09'); +$location = GETPOST('location', 'alphanohtml'); +$stripeacc = GETPOST('stripeacc', 'alphanohtml'); +$servicestatus = GETPOST('servicestatus', 'int'); +$amount = GETPOST('amount', 'int'); + +if (empty($user->rights->takepos->run)) { + accessforbidden(); +} + + +/* + * View + */ + +if ($action == 'getConnexionToken') { + try { + // Be sure to authenticate the endpoint for creating connection tokens. + // Force to use the correct API key + global $stripearrayofkeysbyenv; + \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$servicestatus]['secret_key']); + // The ConnectionToken's secret lets you connect to any Stripe Terminal reader + // and take payments with your Stripe account. + $array = array(); + if (isset($location) && !empty($location)) $array['location'] = $location; + if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage + $connectionToken = \Stripe\Terminal\ConnectionToken::create($array); + } else { + $connectionToken = \Stripe\Terminal\ConnectionToken::create($array, array("stripe_account" => $stripeacc)); + } + echo json_encode(array('secret' => $connectionToken->secret)); + } catch (Error $e) { + http_response_code(500); + echo json_encode(['error' => $e->getMessage()]); + } +} elseif ($action == 'createPaymentIntent') { + try { + $json_str = file_get_contents('php://input'); + $json_obj = json_decode($json_str); + + // For Terminal payments, the 'payment_method_types' parameter must include + // 'card_present' and the 'capture_method' must be set to 'manual' + $object = new Facture($db); + $object->fetch($json_obj->invoiceid); + $object->fetch_thirdparty(); + + $fulltag='INV='.$object->id.'.CUS='.$object->thirdparty->id; + $tag=null; + $fulltag=dol_string_unaccent($fulltag); + + $stripe = new Stripe($db); + $customer = $stripe->customerStripe($object->thirdparty, $stripeacc, $servicestatus, 1); + + $intent = $stripe->getPaymentIntent($json_obj->amount, $object->multicurrency_code, null, 'Stripe payment: '.$fulltag.(is_object($object)?' ref='.$object->ref:''), $object, $customer, $stripeacc, $servicestatus, 1, 'terminal', false, null, 0, 1); + + echo json_encode(array('client_secret' => $intent->client_secret)); + } catch (Error $e) { + http_response_code(500); + echo json_encode(['error' => $e->getMessage()]); + } +} elseif ($action == 'capturePaymentIntent') { + try { + // retrieve JSON from POST body + $json_str = file_get_contents('php://input'); + $json_obj = json_decode($json_str); + if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage + $intent = \Stripe\PaymentIntent::retrieve($json_obj->id); + } else { + $intent = \Stripe\PaymentIntent::retrieve($json_obj->id, array("stripe_account" => $stripeacc)); + } + $intent = $intent->capture(); + + echo json_encode($intent); + } catch (Error $e) { + http_response_code(500); + echo json_encode(['error' => $e->getMessage()]); + } +} diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 36e67d2827c..b14ed0e8ca6 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -290,6 +290,34 @@ class Stripe extends CommonObject return $stripepaymentmethod; } + /** + * Get the Stripe reader Object from its ID + * + * @param string $reader Reader ID + * @param string $key ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect + * @param int $status Status (0=test, 1=live) + * @return \Stripe\Terminal\Reader|null Stripe Reader or null if not found + */ + public function getSelectedReader($reader, $key = '', $status = 0) + { + $selectedreader = null; + + try { + // Force to use the correct API key + global $stripearrayofkeysbyenv; + \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']); + if (empty($key)) { // If the Stripe connect account not set, we use common API usage + $selectedreader = \Stripe\Terminal\Reader::retrieve(''.$reader.''); + } else { + $stripepaymentmethod = \Stripe\Terminal\Reader::retrieve(''.$reader.'', array("stripe_account" => $key)); + } + } catch (Exception $e) { + $this->error = $e->getMessage(); + } + + return $selectedreader; + } + /** * Get the Stripe payment intent. Create it with confirmnow=false * Warning. If a payment was tried and failed, a payment intent was created. @@ -350,7 +378,7 @@ class Stripe extends CommonObject $paymentintent = null; - if (is_object($object) && !empty($conf->global->STRIPE_REUSE_EXISTING_INTENT_IF_FOUND)) { + if (is_object($object) && !empty($conf->global->STRIPE_REUSE_EXISTING_INTENT_IF_FOUND) && empty($conf->global->STRIPE_CARD_PRESENT)) { // Warning. If a payment was tried and failed, a payment intent was created. // But if we change something on object to pay (amount or other that does not change the idempotency key), reusing same payment intent is not allowed by Stripe. // Recommended solution is to recreate a new payment intent each time we need one (old one will be automatically closed by Stripe after a delay), Stripe will @@ -424,6 +452,9 @@ class Stripe extends CommonObject if (!empty($conf->global->STRIPE_SOFORT)) { $paymentmethodtypes[] = "sofort"; } + if (!empty($conf->global->STRIPE_CARD_PRESENT) && $mode == 'terminal') { + $paymentmethodtypes = array("card_present"); + } $dataforintent = array( "confirm" => $confirmnow, // Do not confirm immediatly during creation of intent @@ -456,6 +487,11 @@ class Stripe extends CommonObject if (!empty($conf->global->STRIPE_KLARNA)) { unset($dataforintent['setup_future_usage']); } + if (!empty($conf->global->STRIPE_CARD_PRESENT) && $mode == 'terminal') { + unset($dataforintent['setup_future_usage']); + $dataforintent["capture_method"] = "manual"; + $dataforintent["confirmation_method"] = "manual"; + } if (!is_null($payment_method)) { $dataforintent["payment_method"] = $payment_method; $description .= ' - '.$payment_method; @@ -607,6 +643,9 @@ class Stripe extends CommonObject if (!empty($conf->global->STRIPE_BANCONTACT)) { $paymentmethodtypes[] = "bancontact"; } + if (!empty($conf->global->STRIPE_KLARNA)) { + $paymentmethodtypes[] = "klarna"; + } if (!empty($conf->global->STRIPE_IDEAL)) { $paymentmethodtypes[] = "ideal"; } diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index af1288cfa66..6253d9b86b2 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -1141,7 +1141,7 @@ if (!empty($conf->project->enabled)) { $now = dol_now(); // Add new askprice -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { $currency_code = $conf->currency; print load_fiche_titre($langs->trans("SupplierProposalNew"), '', 'supplier_proposal'); diff --git a/htdocs/takepos/admin/appearance.php b/htdocs/takepos/admin/appearance.php index 135a3b2a9e7..9198b03bb63 100644 --- a/htdocs/takepos/admin/appearance.php +++ b/htdocs/takepos/admin/appearance.php @@ -117,6 +117,49 @@ $array = array(1=>"1", 2=>"2", 3=>"3", 4=>"4", 5=>"5", 6=>"6"); print $form->selectarray('TAKEPOS_LINES_TO_SHOW', $array, (empty($conf->global->TAKEPOS_LINES_TO_SHOW) ? '2' : $conf->global->TAKEPOS_LINES_TO_SHOW), 0); print "\n"; +// D'ont display category +print ''; +print $langs->trans('HideCategories'); +print ''; +print ajax_constantonoff("TAKEPOS_HIDE_CATEGORIES", array(), $conf->entity, 0, 0, 1, 0); +print "\n"; + +// Hide stock on line +print ''; +print $langs->trans('HideStockOnLine'); +print ''; +print ajax_constantonoff("TAKEPOS_HIDE_STOCK_ON_LINE", array(), $conf->entity, 0, 0, 1, 0); +print "\n"; + +// Only the products in stock +print ''; +print $langs->trans('ShowOnlyProductInStock'); +print ''; +print ajax_constantonoff("TAKEPOS_PRODUCT_IN_STOCK", array(), $conf->entity, 0, 0, 1, 0); +print "\n"; + +// View description of the categories +print ''; +print $langs->trans('ShowCategoryDescription'); +print ''; +print ajax_constantonoff("TAKEPOS_SHOW_CATEGORY_DESCRIPTION", array(), $conf->entity, 0, 0, 1, 0); +print "\n"; + +// View reference of products +print ''; +print $langs->trans('ShowProductReference'); +print ''; +print ajax_constantonoff("TAKEPOS_SHOW_PRODUCT_REFERENCE", array(), $conf->entity, 0, 0, 1, 0); +print "\n"; + +// Use price excl. taxes (HT) and not price incl. taxes (TTC) +print ''; +print $langs->trans('UsePriceHT'); +print ''; +print ajax_constantonoff("TAKEPOS_CHANGE_PRICE_HT", array(), $conf->entity, 0, 0, 1, 0); +print "\n"; + + print ''; print $form->buttonsSaveCancel("Save", ''); diff --git a/htdocs/takepos/admin/terminal.php b/htdocs/takepos/admin/terminal.php index f6562d81693..64ce74b6022 100644 --- a/htdocs/takepos/admin/terminal.php +++ b/htdocs/takepos/admin/terminal.php @@ -1,6 +1,7 @@ * Copyright (C) 2011-2017 Juanjo Menent + * Copyright (C) 2021 Thibault FOUCART * * 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 @@ -28,6 +29,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; require_once DOL_DOCUMENT_ROOT."/core/lib/takepos.lib.php"; +require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; $terminal = GETPOST('terminal', 'int'); // If socid provided by ajax company selector @@ -73,6 +75,9 @@ if (GETPOST('action', 'alpha') == 'set') { $res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_CASH".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_CASH'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_CASH'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_CHEQUE".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_CHEQUE'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_CHEQUE'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_CB".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_CB'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_CB'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity); + if (!empty($conf->stripe->enabled) && !empty($conf->global->STRIPE_CARD_PRESENT)) { + $res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".$terminaltouse, GETPOST('CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL'.$terminaltouse, 'alpha'), 'chaine', 0, '', $conf->entity); + } if (!empty($conf->global->TAKEPOS_ENABLE_SUMUP)) { $res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_SUMUP".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_SUMUP'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_SUMUP'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity); } @@ -174,6 +179,44 @@ if (!empty($conf->banque->enabled)) { $atleastonefound++; } print ''; + + if (!empty($conf->stripe->enabled) && !empty($conf->global->STRIPE_CARD_PRESENT)) { + print ''.$langs->trans("CashDeskBankAccountForStripeTerminal").''; // Force Stripe Terminal + print ''; + $service = 'StripeTest'; + $servicestatus = 0; + if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) { + $service = 'StripeLive'; + $servicestatus = 1; + } + global $stripearrayofkeysbyenv; + $site_account = $stripearrayofkeysbyenv[$servicestatus]['secret_key']; + \Stripe\Stripe::setApiKey($site_account); + if (!empty($conf->stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha'))) { + $service = 'StripeTest'; + $servicestatus = '0'; + dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), '', 'warning'); + } else { + $service = 'StripeLive'; + $servicestatus = '1'; + } + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); + if ($stripeacc) { + $readers = \Stripe\Terminal\Reader::all('', array("location" => $conf->global->STRIPE_LOCATION, "stripe_account" => $stripeacc)); + } else { + $readers = \Stripe\Terminal\Reader::all('', array("location" => $conf->global->STRIPE_LOCATION)); + } + + $reader = array(); + $reader[""] = $langs->trans("NoReader"); + foreach ($readers as $readers) { + $reader[$reader->id] = $readers->label.' ('.$readers->status.')'; + } + print $form->selectarray('CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL'.$terminaltouse, $reader, $conf->global->{'CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL'.$terminaltouse}); + print ''; + } + if ($conf->global->TAKEPOS_ENABLE_SUMUP) { print ''.$langs->trans("CashDeskBankAccountForSumup").''; print ''; diff --git a/htdocs/takepos/pay.php b/htdocs/takepos/pay.php index 40d873654c6..f487862e895 100644 --- a/htdocs/takepos/pay.php +++ b/htdocs/takepos/pay.php @@ -1,5 +1,6 @@ + * Copyright (C) 2021 Thibault FOUCART * * 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 @@ -40,6 +41,7 @@ if (!defined('NOREQUIREHTML')) { require '../main.inc.php'; // Load $user and permissions require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; +require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; $langs->loadLangs(array("main", "bills", "cashdesk", "banks")); @@ -51,11 +53,60 @@ if (empty($user->rights->takepos->run)) { accessforbidden(); } +if (!empty($conf->stripe->enabled)) { + $service = 'StripeTest'; + $servicestatus = 0; + if (!empty($conf->global->STRIPE_LIVE) && !GETPOST('forcesandbox', 'alpha')) { + $service = 'StripeLive'; + $servicestatus = 1; + } + + // Force to use the correct API key + global $stripearrayofkeysbyenv; + $site_account = $stripearrayofkeysbyenv[$servicestatus]['publishable_key']; + + $stripe = new Stripe($db); + $stripeacc = $stripe->getStripeAccount($service); // Get Stripe OAuth connect account (no remote access to Stripe here) + $stripecu = $stripe->getStripeCustomerAccount($object->id, $servicestatus, $site_account); // Get remote Stripe customer 'cus_...' (no remote access to Stripe here) + $keyforstripeterminalbank = "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".$_SESSION["takeposterminal"]; + ?> + + +stripe->enabled) && isset($keyforstripeterminalbank) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha'))) { + dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), '', 'warning', 1); +} + $invoice = new Facture($db); if ($invoiceid > 0) { $invoice->fetch($invoiceid); @@ -73,6 +124,57 @@ if ($invoiceid > 0) { } } +?> + +global->TAKEPOS_NUMPAD == 0) { }); } + function fetchPaymentIntentClientSecret(amount, invoiceid) { + const bodyContent = JSON.stringify({ amount : amount, invoiceid : invoiceid }); + + return fetch('', { + method: "POST", + headers: { + 'Content-Type': 'application/json' + }, + body: bodyContent + }) + .then(function(response) { + return response.json(); + }) + .then(function(data) { + return data.client_secret; + }); + } + + + function capturePaymentIntent(paymentIntentId) { + const bodyContent = JSON.stringify({"id": paymentIntentId}) + + return fetch('', { + method: "POST", + headers: { + 'Content-Type': 'application/json' + }, + body: bodyContent + }) + .then(function(response) { + return response.json(); + }) + .then(function(data) { + return data.client_secret; + }); + } + + + function ValidateStripeTerminal() { + console.log("Launch ValidateStripeTerminal"); + var invoiceid = 0 ? $invoiceid : 0); ?>; + var accountid = $("#selectaccountid").val(); + var amountpayed = $("#change1").val(); + var excess = $("#change2").val(); + if (amountpayed > getRemainToPay(); ?>) { + amountpayed = getRemainToPay(); ?>; + } + if (amountpayed == 0) { + amountpayed = getRemainToPay(); ?>; + } + + console.log("Pay with terminal ", amountpayed); + + fetchPaymentIntentClientSecret(amountpayed, invoiceid).then(function(client_secret) { + global->STRIPE_TERMINAL_SIMULATED)) { ?> + terminal.setSimulatorConfiguration({testCardNumber: 'global->STRIPE_TERMINAL_SIMULATED; ?>'}); + + document.getElementById("card-present-alert").innerHTML = '
trans('PaymentSendToStripeTerminal'); ?>
'; + terminal.collectPaymentMethod(client_secret).then(function(result) { + if (result.error) { + // Placeholder for handling result.error + document.getElementById("card-present-alert").innerHTML = '
'+result.error.message+'
'; + } else { + document.getElementById("card-present-alert").innerHTML = '
trans('PaymentBeingProcessed'); ?>
'; + console.log('terminal.collectPaymentMethod', result.paymentIntent); + terminal.processPayment(result.paymentIntent).then(function(result) { + if (result.error) { + document.getElementById("card-present-alert").innerHTML = '
'+result.error.message+'
'; + console.log(result.error) + } else if (result.paymentIntent) { + paymentIntentId = result.paymentIntent.id; + console.log('terminal.processPayment', result.paymentIntent); + capturePaymentIntent(paymentIntentId).then(function(client_secret) { + if (result.error) { + // Placeholder for handling result.error + document.getElementById("card-present-alert").innerHTML = '
'+result.error.message+'
'; + console.log("error when capturing paymentIntent", result.error); + } else { + document.getElementById("card-present-alert").innerHTML = '
trans('PaymentValidated'); ?>
'; + console.log("Capture paymentIntent successfull "+paymentIntentId); + parent.$("#poslines").load("invoice.php?place=&action=valid&pay=CB&amount="+amountpayed+"&excess="+excess+"&invoiceid="+invoiceid+"&accountid="+accountid, function() { + if (amountpayed > || amountpayed == || amountpayed==0 ) { + console.log("Close popup"); + parent.$.colorbox.close(); + } + else { + console.log("Amount is not comple, so we do NOT close popup and reload it."); + location.reload(); + } + }); + + } + }); + } + }); + } + }); + }); + } + function ValidateSumup() { console.log("Launch ValidateSumup"); @@ -271,7 +479,7 @@ if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) { ?> -
+
trans('TotalTTC'); ?>: total_ttc, 1, '', 1, -1, -1, $invoice->multicurrency_code); ?>
@@ -299,7 +507,6 @@ if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) { } ?>
-
global->TAKEPOS_NUMPAD; - +if (!empty($conf->stripe->enabled) && isset($keyforstripeterminalbank) && !empty($conf->global->STRIPE_CARD_PRESENT)) { + print ''; + dol_htmloutput_mesg($langs->trans('ConnectingToStripeTerminal', 'Stripe'), '', 'warning', 1); + print ''; +} print ''; print ''; print ''; @@ -424,8 +635,18 @@ while ($i < count($arrayOfValidPaymentModes)) { $i = $i + 1; } -$keyforsumupbank = "CASHDESK_ID_BANKACCOUNT_SUMUP".$_SESSION["takeposterminal"]; +if (!empty($conf->stripe->enabled) && isset($keyforstripeterminalbank) && !empty($conf->global->STRIPE_CARD_PRESENT)) { + $keyforstripeterminalbank = "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".$_SESSION["takeposterminal"]; + print ''; + if (!empty($conf->global->$keyforstripeterminalbank)) { + } else { + $langs->loadLangs(array("errors", "admin")); + //print ''; + } +} + if ($conf->global->TAKEPOS_ENABLE_SUMUP) { + $keyforsumupbank = "CASHDESK_ID_BANKACCOUNT_SUMUP".$_SESSION["takeposterminal"]; if (!empty($conf->global->$keyforsumupbank)) { print ''; } else { diff --git a/htdocs/user/group/card.php b/htdocs/user/group/card.php index 61bcdc7cc57..92d309e554b 100644 --- a/htdocs/user/group/card.php +++ b/htdocs/user/group/card.php @@ -259,7 +259,7 @@ $fuserstatic = new User($db); $form = new Form($db); $formfile = new FormFile($db); -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewGroup"), '', 'object_group'); dol_set_focus('#nom'); diff --git a/htdocs/user/notify/card.php b/htdocs/user/notify/card.php index 56c6d2d01f7..3337d846f0b 100644 --- a/htdocs/user/notify/card.php +++ b/htdocs/user/notify/card.php @@ -272,7 +272,7 @@ if ($result > 0) { print ''; - if ($action == 'create' || (empty($action) && empty($id))) { + if ($action == 'create') { // $listofemails=$object->thirdparty_and_contact_email_array(); if ($object->email) { $actions = array(); diff --git a/htdocs/variants/card.php b/htdocs/variants/card.php index 470e3fd96f8..68bb8d60998 100644 --- a/htdocs/variants/card.php +++ b/htdocs/variants/card.php @@ -158,7 +158,7 @@ $help_url = 'EN:Module_Products#Variants'; llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("ProductAttribute")), '', 'object_' . $object->picto); print ''; diff --git a/htdocs/variants/class/ProductCombination.class.php b/htdocs/variants/class/ProductCombination.class.php index 7f9227fee88..0e8f69958dc 100644 --- a/htdocs/variants/class/ProductCombination.class.php +++ b/htdocs/variants/class/ProductCombination.class.php @@ -608,6 +608,10 @@ class ProductCombination $prodcomb2val = new ProductCombination2ValuePair($this->db); $prodcomb = new ProductCombination($this->db); + $features = array_filter($features, function ($v) { + return !empty($v); + }); + foreach ($features as $attr => $attr_val) { $actual_comp[$attr] = $attr_val; } diff --git a/htdocs/webhook/target_card.php b/htdocs/webhook/target_card.php index 3ffd381f3aa..dd0d5e171e8 100644 --- a/htdocs/webhook/target_card.php +++ b/htdocs/webhook/target_card.php @@ -240,7 +240,7 @@ llxHeader('', $title, $help_url); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { if (empty($permissiontoadd)) { accessforbidden($langs->trans('NotEnoughPermissions'), 0, 1); exit; diff --git a/htdocs/website/websiteaccount_card.php b/htdocs/website/websiteaccount_card.php index 7a075eb8734..249398c322e 100644 --- a/htdocs/website/websiteaccount_card.php +++ b/htdocs/website/websiteaccount_card.php @@ -118,7 +118,7 @@ $formfile = new FormFile($db); llxHeader('', 'WebsiteAccount', ''); // Part to create -if ($action == 'create' || (empty($action) && empty($id))) { +if ($action == 'create') { print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("WebsiteAccount"))); print ''; diff --git a/htdocs/workstation/workstation_card.php b/htdocs/workstation/workstation_card.php index a2409802024..9e859dcc2d0 100644 --- a/htdocs/workstation/workstation_card.php +++ b/htdocs/workstation/workstation_card.php @@ -186,7 +186,7 @@ llxHeader('', $title, $help_url); trans("NewObject", $langs->transnoentitiesnoconv("Workstation")), '', 'object_'.$object->picto); print '';