diff --git a/.travis.yml b/.travis.yml index c1bed319447..733e997bdf3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,8 +38,8 @@ env: jobs: fast_finish: true - allow_failures: - - php: nightly + #allow_failures: + #- php: nightly include: - if: type = push php: '5.6' @@ -73,13 +73,6 @@ before_install: phpenv config-rm xdebug.ini echo -- | - if [ "$DB" = 'postgresql' ]; then - echo "Check pgloader version" - pgloader --version - echo - fi - install: - | echo "Updating Composer" @@ -178,6 +171,10 @@ before_script: mysql --version | head - mysql -e "SELECT VERSION();" | head - psql --version + if [ "$DB" = 'postgresql' ]; then + echo "Check pgloader version" + pgloader --version + fi echo - | diff --git a/ChangeLog b/ChangeLog index c5cc42fd2f3..c35ca9ba9b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,7 +7,8 @@ English Dolibarr ChangeLog For users: ---------- -NEW: Add module "Credit transfer SEPA" to manage payment of vendors using bank credit transfer SEPA files. +NEW: Module "Credit transfer SEPA" to manage payment of vendors using bank credit transfer SEPA files. +NEW: Module Intracomm report NEW: Module Reception (for a more accurate management of your receptions) moved from experimental to stable. NEW: Module Recruitment to manage Job position and applications. NEW: Several security issues after a private bug bounty campaign. @@ -22,7 +23,6 @@ NEW: Solve blocking feature. Can increase stock of a Kit without changing subpro NEW: add a widget to show the customers with outstanding limits reached NEW: add 2 rules for emailcollector: Message send/not sent from Dolibarr NEW: add a counter of number of words for pages in website module -NEW: add alert before changing thirdparty in TakePOS NEW: add a page to list Stock at a given date in the past NEW: add a start date to begin binding in accountancy NEW: add a statistics page to list popularity of products on invoices @@ -34,12 +34,12 @@ NEW: add column vat rate in page to define accounting account on product/service NEW: add costprice in fields of products list NEW: add an import profile for CUSTOMER ORDER, PO, PROPOSAL MODULE, SUPPLIER INVOICE NEW: add employee link in expense report binding page -NEW: add EORI No. as ProfID5 +NEW: add EORI No. as ProfID5 #15382 NEW: add export for various payments NEW: add Extrafields labels and values in mail on create ticket NEW: add Extrafields support on ECM module NEW: add filter rules "is answer" and "is not answer" in email collector -NEW: add focus when editing on product/stock/product.php Close #14548 +NEW: add focus when editing on product/stock/product.php -> close #14548 NEW: add free text on each terminal of cash desk NEW: add global search for customer payments and vendor payments NEW: add global search for miscellaneous payments @@ -74,7 +74,6 @@ NEW: Algeria data (VAT and forme_juridique) NEW: allow click on all header numbers on commerce area NEW: allow to reopen interventions (green button) NEW: allow zero quantity on supplier/vendor order line -NEW: appearance tab in TakePOS with more visual parameters NEW: better currency rate editor NEW: can build vendor invoice from vendor orders NEW: can change a product in lines of a recurring invoice or contract @@ -121,29 +120,24 @@ NEW: link on balance to the ledger NEW: MAIN_EMAILCOLLECTOR_MAIL_WITHOUT_HEADER const in email collector NEW: manage errors on update extra fields in ticket card NEW: mass-actions for the event list view -NEW: Module Intracomm report NEW: more filter for "View change logs" -NEW: multicurrency total in TakePOS NEW: multiselect type and date to date filter -NEW: Nature of product is now a dictionay NEW: new line template: hidden conf to fill service dates from the last service line NEW: PDF model storm for delivery NEW: possibilty to group payments by mode and show their subtotal -NEW: Print payment method and change in TakePOS NEW: Priority and transparency from external calendar events +NEW: Products - Nature of product is now a dictionary #13287 NEW: Products Import/Export 'default warehouse' and 'use batch number' fields NEW: Purchase price table: added filterable table columns NEW: rate editor for multicurrency NEW: ref_ext field for Commande lines, order lines, Attributes and Combinations, Invoice lines, payments, order lines NEW: remove new lines in mail on add ticket message -NEW: restrict thirdparty to customer in TakePOS NEW: Rule "email to" accept wildcard * -NEW: Save filter of the project homepage +NEW: save filter of the project homepage NEW: select-able columns on customer and supplier invoice paymnet list NEW: select-able columns on miscellaneous payments + more data columns NEW: select-able columns on social taxes list NEW: send context and remove new lines on create ticket -NEW: show available stock in TakePOS NEW: show category filter on lists only when user have rights to read categories NEW: show header number and make it clickable in warehouse area, payment area, shipment area NEW: show image of user in the combo select of users @@ -156,18 +150,24 @@ NEW: show tags and status in search list of website pages NEW: show user on external calender events (when found) NEW: subject title with company name instead of application title in ticket message NEW: Support for Samba4 AD +NEW: TakePOS appearance tab with more visual parameters +NEW: TakePOS add alert before changing thirdparty NEW: TakePOS add third order printer NEW: TakePOS can change thirdparty with barcode scan NEW: TakePOS can create a thirdparty customer from TakePOS frontend NEW: TakePOS connector compatibility with RECEIPT PRINTERS module NEW: TakePOS Gift Receipt -NEW: TakePOS Multicurrency compatibility +NEW: TakePOS multicurrency compatibility +NEW: TakePOS multicurrency total +NEW: TakePOS print payment method and change +NEW: TakePOS restrict thirdparty to customer +NEW: TakePOS show available stock NEW: TakePOS Weighing Scale compatibility with TakePOS connector #14725 -NEW: Third-Party Import new fields: mother company,outstanding debt limit,bank account,incoterms +NEW: Thirdparty Import new fields: mother company,outstanding debt limit,bank account,incoterms NEW: Thirdparty module : box on customer/supplier tab for invoice outsantding amount late -NEW: ticket classification on create from email collector +NEW: Ticket classification on create from email collector NEW: Ticket message notifications when edited from public interface -NEW: translate classification labels in ticket +NEW: Ticket translate classification labels in ticket NEW: VAT rate for Angola #15606 NEW: VAT and juridical status for Algeria NEW: VAT report - Invert constant to show by default zero VAT in reports diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index d211444b4ee..59ffdf2e899 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -661,7 +661,7 @@ if (empty($reshook)) { } $newcardbutton .= ''.$langs->trans("IncludeDocsAlreadyExported").''; - $newcardbutton .= dolGetButtonTitle($buttonLabel, $langs->trans("ExportFilteredList").' ('.$listofformat[$formatexportset].')', 'fa fa-file-export paddingleft', $_SERVER["PHP_SELF"].'?action=export_file'.($param ? '&'.$param : ''), $user->rights->accounting->mouvements->export); + if (!empty($user->rights->accounting->mouvements->export)) $newcardbutton .= dolGetButtonTitle($buttonLabel, $langs->trans("ExportFilteredList").' ('.$listofformat[$formatexportset].')', 'fa fa-file-export paddingleft', $_SERVER["PHP_SELF"].'?action=export_file'.($param ? '&'.$param : ''), $user->rights->accounting->mouvements->export); $newcardbutton .= dolGetButtonTitle($langs->trans('ViewFlatList'), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/list.php?'.$param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?'.$param, '', 1, array('morecss' => 'marginleftonly')); diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index 1a5098bda38..3634fba2e79 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -1,7 +1,7 @@ * Copyright (C) 2013-2014 Florian Henry - * Copyright (C) 2013-2017 Alexandre Spangaro + * Copyright (C) 2013-2020 Alexandre Spangaro * Copyright (C) 2014 Juanjo Menent * Copyright (C) 2015 Jean-François Ferry * @@ -123,9 +123,9 @@ if ($action == 'validatehistory') { $sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, l.vat_src_code,"; $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type, p.tva_tx as tva_tx_prod,"; $sql .= " p.accountancy_code_sell as code_sell, p.accountancy_code_sell_intra as code_sell_intra, p.accountancy_code_sell_export as code_sell_export,"; - $sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export,"; + $sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export, aa4.rowid as aarowid_thirdparty,"; $sql .= " co.code as country_code, co.label as country_label,"; - $sql .= " s.tva_intra"; + $sql .= " s.tva_intra, s.accountancy_code_sell as company_code_sell"; $sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as co ON co.rowid = s.fk_pays "; @@ -134,6 +134,7 @@ if ($action == 'validatehistory') { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON p.accountancy_code_sell = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON p.accountancy_code_sell_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON p.accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON s.accountancy_code_sell = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND l.product_type <= 2"; @@ -153,7 +154,7 @@ if ($action == 'validatehistory') { $isBuyerInEEC = isInEEC($objp); - // Search suggested account for product/service (similar code exists in page list.php to make manual binding) + // Level 2: Search suggested account for product/service (similar code exists in page list.php to make manual binding) $suggestedaccountingaccountfor = ''; if (($objp->country_code == $mysoc->country_code) || empty($objp->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country) $objp->code_sell_p = $objp->code_sell; @@ -179,6 +180,13 @@ if ($action == 'validatehistory') { } } + // Level 3: Search suggested account for this thirdparty (similar code exists in page index.php to make automatic binding) + if (!empty($objp->company_code_sell)) { + $objp->code_sell_t = $objp->company_code_sell; + $objp->aarowid_suggest = $objp->aarowid_thirdparty; + $suggestedaccountingaccountfor = ''; + } + if ($objp->aarowid_suggest > 0) { $sqlupdate = "UPDATE ".MAIN_DB_PREFIX."facturedet"; diff --git a/htdocs/accountancy/customer/list.php b/htdocs/accountancy/customer/list.php index eb2743258d7..cb47e436cbd 100644 --- a/htdocs/accountancy/customer/list.php +++ b/htdocs/accountancy/customer/list.php @@ -211,9 +211,9 @@ $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, $sql .= " p.accountancy_code_sell as code_sell, p.accountancy_code_sell_intra as code_sell_intra, p.accountancy_code_sell_export as code_sell_export,"; $sql .= " p.accountancy_code_buy as code_buy, p.accountancy_code_buy_intra as code_buy_intra, p.accountancy_code_buy_export as code_buy_export,"; $sql .= " p.tosell as status, p.tobuy as status_buy,"; -$sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export,"; +$sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export, aa4.rowid as aarowid_thirdparty,"; $sql .= " co.code as country_code, co.label as country_label,"; -$sql .= " s.rowid as socid, s.nom as name, s.tva_intra, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur"; +$sql .= " s.rowid as socid, s.nom as name, s.tva_intra, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur, s.accountancy_code_sell as company_code_sell"; $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; @@ -225,6 +225,7 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = l.fk_product"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON p.accountancy_code_sell = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON p.accountancy_code_sell_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON p.accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON s.accountancy_code_sell = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND l.product_type <= 2"; // Define begin binding date @@ -456,11 +457,12 @@ if ($result) { $facture_static->type = $objp->ftype; $code_sell_p_notset = ''; + $code_sell_t_notset = ''; $objp->aarowid_suggest = ''; // Will be set later $isBuyerInEEC = isInEEC($objp); - // Search suggested default account for product/service + // Level 1: Search suggested default account for product/service $suggestedaccountingaccountbydefaultfor = ''; if ($objp->type_l == 1) { if ($objp->country_code == $mysoc->country_code || empty($objp->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country) @@ -503,7 +505,7 @@ if ($result) { } if ($objp->code_sell_l == -1) $objp->code_sell_l = ''; - // Search suggested account for product/service (similar code exists in page index.php to make automatic binding) + // Level 2: Search suggested account for product/service (similar code exists in page index.php to make automatic binding) $suggestedaccountingaccountfor = ''; if (($objp->country_code == $mysoc->country_code) || empty($objp->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country) $objp->code_sell_p = $objp->code_sell; @@ -529,6 +531,13 @@ if ($result) { } } + // Level 3: Search suggested account for this thirdparty (similar code exists in page index.php to make automatic binding) + if (!empty($objp->company_code_sell)) { + $objp->code_sell_t = $objp->company_code_sell; + $objp->aarowid_suggest = $objp->aarowid_thirdparty; + $suggestedaccountingaccountfor = ''; + } + // Manage Deposit if ($objp->description == "(DEPOSIT)") { $accountdeposittoventilated = new AccountingAccount($db); @@ -547,6 +556,7 @@ if ($result) { // $objp->code_sell_l is now default code of product/service // $objp->code_sell_p is now code of product/service + // $objp->code_sell_t is now code of thirdparty print ''; @@ -596,7 +606,7 @@ if ($result) { // Found accounts print ''; - $s = ''.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; + $s = '1. '.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; $shelp = ''; if ($suggestedaccountingaccountbydefaultfor == 'eec') $shelp .= $langs->trans("SaleEEC"); elseif ($suggestedaccountingaccountbydefaultfor == 'export') $shelp .= $langs->trans("SaleExport"); @@ -605,7 +615,7 @@ if ($result) { if ($objp->product_id > 0) { print '
'; - $s = ''.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; + $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; $shelp = ''; if ($suggestedaccountingaccountfor == 'eec') $shelp = $langs->trans("SaleEEC"); elseif ($suggestedaccountingaccountfor == 'eecwithvat') $shelp = $langs->trans("SaleEECWithVAT"); @@ -613,16 +623,23 @@ if ($result) { elseif ($suggestedaccountingaccountfor == 'export') $shelp = $langs->trans("SaleExport"); $s .= (empty($objp->code_sell_p) ? ''.$langs->trans("NotDefined").'' : length_accountg($objp->code_sell_p)); print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); + } else { + print '
'; + $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; + $shelp = ''; + $s .= $langs->trans("NotDefined"); + print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); } + print '
'; + $s = '3. '.(($objp->type_l == 1) ? $langs->trans("ServiceForThisThirdparty") : $langs->trans("ProductForThisThirdparty")).': '; + $shelp = ''; + $s .= ($objp->code_sell_t > 0 ? length_accountg($objp->code_sell_t) : ''.$langs->trans("NotDefined").''); + print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); print ''; // Suggested accounting account - // $objp->code_sell_l = default (it takes the country into consideration), $objp->code_sell_p is value for product (it takes the country into consideration too) print ''; $suggestedid = $objp->aarowid_suggest; - /*var_dump($suggestedid); - var_dump($objp->code_sell_p); - var_dump($objp->code_sell_l);*/ if (empty($suggestedid) && empty($objp->code_sell_p) && !empty($objp->code_sell_l) && empty($conf->global->ACCOUNTANCY_DO_NOT_AUTOFILL_ACCOUNT_WITH_GENERIC)) { if (empty($accountingaccount_codetotid_cache[$objp->code_sell_l])) @@ -642,7 +659,6 @@ if ($result) { // Column with checkbox print ''; - //var_dump($objp->aarowid);var_dump($objp->aarowid_intra);var_dump($objp->aarowid_export);var_dump($objp->aarowid_suggest); $ischecked = $objp->aarowid_suggest; if ($suggestedaccountingaccountfor == 'eecwithoutvatnumber') $ischecked = 0; print ''; diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index 0dbe09fa468..9dd097f3d0c 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -120,9 +120,9 @@ if ($action == 'validatehistory') { $sql .= " l.rowid, l.fk_product, l.description, l.total_ht, l.fk_code_ventilation, l.product_type as type_l, l.tva_tx as tva_tx_line, l.vat_src_code,"; $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, p.fk_product_type as type,"; $sql .= " p.accountancy_code_buy as code_buy, p.accountancy_code_buy_intra as code_buy_intra, p.accountancy_code_buy_export as code_buy_export, p.tva_tx as tva_tx_prod,"; - $sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export,"; + $sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export, aa4.rowid as aarowid_thirdparty,"; $sql .= " co.code as country_code, co.label as country_label,"; - $sql .= " s.tva_intra"; + $sql .= " s.tva_intra, s.accountancy_code_buy as company_code_buy"; $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; $sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as co ON co.rowid = s.fk_pays "; @@ -131,6 +131,7 @@ if ($action == 'validatehistory') { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON p.accountancy_code_buy = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON p.accountancy_code_buy_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON p.accountancy_code_buy_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON s.accountancy_code_buy = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND l.product_type <= 2"; @@ -151,7 +152,7 @@ if ($action == 'validatehistory') { $isSellerInEEC = isInEEC($objp); - // Search suggested account for product/service + // Level 2: Search suggested account for product/service (similar code exists in page list.php to make manual binding) $suggestedaccountingaccountfor = ''; if (($objp->country_code == $mysoc->country_code) || empty($objp->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country) $objp->code_buy_p = $objp->code_buy; @@ -169,6 +170,13 @@ if ($action == 'validatehistory') { } } + // Level 3: Search suggested account for this thirdparty (similar code exists in page index.php to make automatic binding) + if (!empty($objp->company_code_buy)) { + $objp->code_buy_t = $objp->company_code_buy; + $objp->aarowid_suggest = $objp->aarowid_thirdparty; + $suggestedaccountingaccountfor = ''; + } + if ($objp->aarowid_suggest > 0) { $sqlupdate = "UPDATE ".MAIN_DB_PREFIX."facture_fourn_det"; diff --git a/htdocs/accountancy/supplier/list.php b/htdocs/accountancy/supplier/list.php index cbdecd2e85e..919130e80d3 100644 --- a/htdocs/accountancy/supplier/list.php +++ b/htdocs/accountancy/supplier/list.php @@ -215,9 +215,9 @@ $sql .= " p.rowid as product_id, p.ref as product_ref, p.label as product_label, $sql .= " p.accountancy_code_sell as code_sell, p.accountancy_code_sell_intra as code_sell_intra, p.accountancy_code_sell_export as code_sell_export,"; $sql .= " p.accountancy_code_buy as code_buy, p.accountancy_code_buy_intra as code_buy_intra, p.accountancy_code_buy_export as code_buy_export,"; $sql .= " p.tosell as status, p.tobuy as status_buy,"; -$sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export,"; +$sql .= " aa.rowid as aarowid, aa2.rowid as aarowid_intra, aa3.rowid as aarowid_export, aa4.rowid as aarowid_thirdparty,"; $sql .= " co.code as country_code, co.label as country_label,"; -$sql .= " s.rowid as socid, s.nom as name, s.tva_intra, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur"; +$sql .= " s.rowid as socid, s.nom as name, s.tva_intra, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur, s.accountancy_code_buy as company_code_buy"; $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook $sql .= $hookmanager->resPrint; @@ -229,6 +229,7 @@ $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = l.fk_product"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON p.accountancy_code_buy = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa2 ON p.accountancy_code_buy_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa3 ON p.accountancy_code_buy_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; +$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa4 ON s.accountancy_code_buy = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND l.product_type <= 2"; // Define begin binding date @@ -460,10 +461,12 @@ if ($result) { $facturefourn_static->label = $objp->invoice_label; $code_buy_p_notset = ''; + $code_buy_t_notset = ''; $objp->aarowid_suggest = ''; // Will be set later $isSellerInEEC = isInEEC($objp); + // Level 1: Search suggested default account for product/service $suggestedaccountingaccountbydefaultfor = ''; if ($objp->type_l == 1) { if ($objp->country_code == $mysoc->country_code || empty($objp->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country) @@ -494,7 +497,7 @@ if ($result) { } if ($objp->code_sell_l == -1) $objp->code_sell_l = ''; - // Search suggested account for product/service + // Level 2: Search suggested account for product/service (similar code exists in page index.php to make automatic binding) $suggestedaccountingaccountfor = ''; if (($objp->country_code == $mysoc->country_code) || empty($objp->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country) $objp->code_buy_p = $objp->code_buy; @@ -512,6 +515,13 @@ if ($result) { } } + // Level 3: Search suggested account for this thirdparty (similar code exists in page index.php to make automatic binding) + if (!empty($objp->company_code_buy)) { + $objp->code_buy_t = $objp->company_code_buy; + $objp->aarowid_suggest = $objp->aarowid_thirdparty; + $suggestedaccountingaccountfor = ''; + } + if (!empty($objp->code_buy_p)) { // Value was defined previously } else { @@ -521,6 +531,7 @@ if ($result) { // $objp->code_buy_l is now default code of product/service // $objp->code_buy_p is now code of product/service + // $objp->code_buy_t is now code of thirdparty print ''; @@ -576,7 +587,7 @@ if ($result) { // Found accounts print ''; - $s = ''.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; + $s = '1. '.(($objp->type_l == 1) ? $langs->trans("DefaultForService") : $langs->trans("DefaultForProduct")).': '; $shelp = ''; if ($suggestedaccountingaccountbydefaultfor == 'eec') $shelp .= $langs->trans("SaleEEC"); elseif ($suggestedaccountingaccountbydefaultfor == 'export') $shelp .= $langs->trans("SaleExport"); @@ -585,13 +596,24 @@ if ($result) { if ($objp->product_id > 0) { print '
'; - $s = ''.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; + $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; $shelp = ''; if ($suggestedaccountingaccountfor == 'eec') $shelp = $langs->trans("SaleEEC"); elseif ($suggestedaccountingaccountfor == 'export') $shelp = $langs->trans("SaleExport"); $s .= (empty($objp->code_buy_p) ? ''.$langs->trans("NotDefined").'' : length_accountg($objp->code_buy_p)); print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); + } else { + print '
'; + $s = '2. '.(($objp->type_l == 1) ? $langs->trans("ThisService") : $langs->trans("ThisProduct")).': '; + $shelp = ''; + $s .= $langs->trans("NotDefined"); + print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); } + print '
'; + $s = '3. '.(($objp->type_l == 1) ? $langs->trans("ServiceForThisThirdparty") : $langs->trans("ProductForThisThirdparty")).': '; + $shelp = ''; + $s .= ($objp->code_buy_t > 0 ? length_accountg($objp->code_buy_t) : ''.$langs->trans("NotDefined").''); + print $form->textwithpicto($s, $shelp, 1, 'help', '', 0, 2, '', 1); print ''; // Suggested accounting account diff --git a/htdocs/admin/company.php b/htdocs/admin/company.php index 16f72ef6911..bb4f142cc2a 100644 --- a/htdocs/admin/company.php +++ b/htdocs/admin/company.php @@ -393,7 +393,7 @@ print ''.$langs->trans( // Name print ''; -print 'global->MAIN_INFO_SOCIETE_NOM) ? ' autofocus="autofocus"' : '')).'>'."\n"; +print 'global->MAIN_INFO_SOCIETE_NOM) ? ' autofocus="autofocus"' : '').'>'."\n"; // Address print ''; diff --git a/htdocs/admin/mailing.php b/htdocs/admin/mailing.php index 1c96ce68780..32aa7accfcf 100644 --- a/htdocs/admin/mailing.php +++ b/htdocs/admin/mailing.php @@ -34,7 +34,7 @@ if (!$user->admin) accessforbidden(); $action = GETPOST('action', 'aZ09'); - +$form = new Form($db); /* * Actions @@ -49,6 +49,7 @@ if ($action == 'setvalue') $checkread = GETPOST('value', 'alpha'); $checkread_key = GETPOST('MAILING_EMAIL_UNSUBSCRIBE_KEY', 'alpha'); $mailingdelay = GETPOST('MAILING_DELAY', 'int'); + $contactbulkdefault = GETPOST('MAILING_CONTACT_DEFAULT_BULK_STATUS', 'int'); $res = dolibarr_set_const($db, "MAILING_EMAIL_FROM", $mailfrom, 'chaine', 0, '', $conf->entity); if (!$res > 0) $error++; @@ -56,11 +57,14 @@ if ($action == 'setvalue') if (!$res > 0) $error++; $res = dolibarr_set_const($db, "MAILING_DELAY", $mailingdelay, 'chaine', 0, '', $conf->entity); if (!$res > 0) $error++; + $res = dolibarr_set_const($db, "MAILING_CONTACT_DEFAULT_BULK_STATUS", $contactbulkdefault, 'chaine', 0, '', $conf->entity); + if (!$res > 0) $error++; // Create temporary encryption key if nedded $res = dolibarr_set_const($db, "MAILING_EMAIL_UNSUBSCRIBE_KEY", $checkread_key, 'chaine', 0, '', $conf->entity); if (!$res > 0) $error++; + if (!$error) { $db->commit(); @@ -70,7 +74,17 @@ if ($action == 'setvalue') setEventMessages($langs->trans("Error"), null, 'errors'); } } - +if ($action == 'setonsearchandlistgooncustomerorsuppliercard') { + $setonsearchandlistgooncustomerorsuppliercard = GETPOST('value', 'int'); + $res = dolibarr_set_const($db, "SOCIETE_ON_SEARCH_AND_LIST_GO_ON_CUSTOMER_OR_SUPPLIER_CARD", $setonsearchandlistgooncustomerorsuppliercard, 'yesno', 0, '', $conf->entity); + if (!$res > 0) $error++; + if (!$error) + { + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } else { + setEventMessages($langs->trans("Error"), null, 'errors'); + } +} /* * View @@ -136,6 +150,16 @@ print ''; +// default blacklist from mailing +print ''; +print '' . $langs->trans("DefaultBlacklistMailingStatus") . ''; +print ''; +$blacklist_setting=array(0=>$langs->trans('No'),1=>$langs->trans('Yes'),-1=>$langs->trans('DefaultStatusEmptyMandatory')); +print $form->selectarray("MAILING_CONTACT_DEFAULT_BULK_STATUS", $blacklist_setting, $conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS); +print ''; +print ''; + + if (!empty($conf->use_javascript_ajax) && $conf->global->MAIN_FEATURES_LEVEL >= 1) { print ''; print $langs->trans("MailAdvTargetRecipients").''; diff --git a/htdocs/admin/stock.php b/htdocs/admin/stock.php index 031b0ef102f..db7f005284f 100644 --- a/htdocs/admin/stock.php +++ b/htdocs/admin/stock.php @@ -707,7 +707,15 @@ if (!empty($conf->global->MAIN_DEFAULT_WAREHOUSE_USER)) { print "\n"; print "\n"; } - +print ''; +print ''.$langs->trans("WarehouseAskWarehouseDuringPropal").''; +print ''; +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL'); +} else { + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $form->selectarray("WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL", $arrval, $conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL); +} print ''; print ''.$langs->trans("WarehouseAskWarehouseDuringOrder").''; print ''; diff --git a/htdocs/admin/system/filecheck.php b/htdocs/admin/system/filecheck.php index a94a78a9794..4ed21144346 100644 --- a/htdocs/admin/system/filecheck.php +++ b/htdocs/admin/system/filecheck.php @@ -264,7 +264,7 @@ if (!$error && $xml) $out .= "\n"; } } else { - $out .= ''.$langs->trans("None").''; + $out .= ''.$langs->trans("None").''; } $out .= ''; $out .= ''; @@ -317,7 +317,7 @@ if (!$error && $xml) $out .= ''."\n"; $out .= "\n"; } else { - $out .= ''.$langs->trans("None").''; + $out .= ''.$langs->trans("None").''; } $out .= ''; $out .= ''; @@ -370,12 +370,11 @@ if (!$error && $xml) $out .= ''."\n"; $out .= "\n"; } else { - $out .= ''.$langs->trans("None").''; + $out .= ''.$langs->trans("None").''; } $out .= ''; $out .= ''; - // Show warning if (empty($tmpfilelist) && empty($tmpfilelist2) && empty($tmpfilelist3)) { diff --git a/htdocs/admin/workflow.php b/htdocs/admin/workflow.php index 6bd3edca2b8..c1e099362ad 100644 --- a/htdocs/admin/workflow.php +++ b/htdocs/admin/workflow.php @@ -31,7 +31,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; if (!$user->admin) accessforbidden(); // Load translation files required by the page -$langs->loadLangs(array("admin", "workflow", "propal", "workflow", "orders", "supplier_proposal", "receptions", "errors")); +$langs->loadLangs(array("admin", "workflow", "propal", "workflow", "orders", "supplier_proposal", "receptions", "errors", 'sendings')); $action = GETPOST('action', 'aZ09'); @@ -130,6 +130,14 @@ $workflowcodes = array( 'enabled'=>(!empty($conf->reception->enabled) && (!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled))), 'picto'=>'bill' ), + + // Automatic classification shipping + 'WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE' => array( + 'family' => 'classify_shipping', + 'position' => 66, + 'enabled' => ! empty($conf->expedition->enabled) && ! empty($conf->facture->enabled), + 'picto' => 'shipment' + ) ); if (!empty($conf->modules_parts['workflow']) && is_array($conf->modules_parts['workflow'])) { @@ -190,6 +198,7 @@ foreach ($workflowcodes as $key => $params) { if ($reg[1] == 'supplier_proposal') $header .= ' - '.$langs->trans('SupplierProposal'); if ($reg[1] == 'supplier_order') $header .= ' - '.$langs->trans('SupplierOrder'); if ($reg[1] == 'reception') $header .= ' - '.$langs->trans('Reception'); + if ($reg[1] == 'shipping') $header .= ' - '.$langs->trans('Shipment'); } else { $header = $langs->trans("Description"); } diff --git a/htdocs/admin/workstation.php b/htdocs/admin/workstation.php new file mode 100755 index 00000000000..502a573e98b --- /dev/null +++ b/htdocs/admin/workstation.php @@ -0,0 +1,513 @@ + + * Copyright (C) 2020 Gauthier VERDOL + * + * 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 workstation/admin/setup.php + * \ingroup workstation + * \brief Workstation setup page. + */ + +// Load Dolibarr environment +require "../main.inc.php"; + +// Libraries +require_once DOL_DOCUMENT_ROOT . "/core/lib/admin.lib.php"; +require_once DOL_DOCUMENT_ROOT . '/workstation/lib/workstation.lib.php'; +//require_once "../class/myclass.class.php"; + +// Translations +$langs->loadLangs(array("admin", "workstation@workstation")); + +// Access control +if (!$user->admin) accessforbidden(); + +// Parameters +$action = GETPOST('action', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +$value = GETPOST('value', 'alpha'); + +/*$arrayofparameters = array( + 'WORKSTATION_MYPARAM1'=>array('css'=>'minwidth200', 'enabled'=>1), + 'WORKSTATION_MYPARAM2'=>array('css'=>'minwidth500', 'enabled'=>1) +);*/ + +$error = 0; +$setupnotempty = 0; + + +/* + * Actions + */ + +if ((float) DOL_VERSION >= 6) +{ + include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; +} + +if ($action == 'updateMask') +{ + $maskconstorder = GETPOST('maskconstWorkstation', 'alpha'); + $maskorder = GETPOST('maskWorkstation', 'alpha'); + + if ($maskconstorder) $res = dolibarr_set_const($db, $maskconstorder, $maskorder, 'chaine', 0, '', $conf->entity); + + if (!$res > 0) $error++; + + if (!$error) + { + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } else { + setEventMessages($langs->trans("Error"), null, 'errors'); + } +} elseif ($action == 'specimen') +{ + $modele = GETPOST('module', 'alpha'); + $tmpobjectkey = GETPOST('object'); + + $tmpobject = new $tmpobjectkey($db); + $tmpobject->initAsSpecimen(); + + // Search template files + $file = ''; $classname = ''; $filefound = 0; + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) + { + $file = dol_buildpath($reldir."core/modules/workstation/doc/pdf_".$modele."_".strtolower($tmpobjectkey).".modules.php", 0); + if (file_exists($file)) + { + $filefound = 1; + $classname = "pdf_".$modele; + break; + } + } + + if ($filefound) + { + require_once $file; + + $module = new $classname($db); + + if ($module->write_file($tmpobject, $langs) > 0) + { + header("Location: ".DOL_URL_ROOT."/document.php?modulepart=".strtolower($tmpobjectkey)."&file=SPECIMEN.pdf"); + return; + } else { + setEventMessages($module->error, null, 'errors'); + dol_syslog($module->error, LOG_ERR); + } + } else { + setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors'); + dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR); + } +} + +// Activate a model +elseif ($action == 'set') +{ + $ret = addDocumentModel($value, $type, $label, $scandir); +} elseif ($action == 'del') +{ + $tmpobjectkey = GETPOST('object'); + + $ret = delDocumentModel($value, $type); + if ($ret > 0) + { + $constforval = strtoupper($tmpobjectkey).'_ADDON_PDF'; + if ($conf->global->$constforval == "$value") dolibarr_del_const($db, $constforval, $conf->entity); + } +} + +// Set default model +elseif ($action == 'setdoc') +{ + $tmpobjectkey = GETPOST('object'); + $constforval = strtoupper($tmpobjectkey).'_ADDON_PDF'; + if (dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity)) + { + // The constant that was read before the new set + // We therefore requires a variable to have a coherent view + $conf->global->$constforval = $value; + } + + // On active le modele + $ret = delDocumentModel($value, $type); + if ($ret > 0) + { + $ret = addDocumentModel($value, $type, $label, $scandir); + } +} elseif ($action == 'setmod') +{ + // TODO Check if numbering module chosen can be activated + // by calling method canBeActivated + $tmpobjectkey = GETPOST('object'); + $constforval = 'WORKSTATION_'.strtoupper($tmpobjectkey)."_ADDON"; + dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity); +} + + + +/* + * View + */ + +$form = new Form($db); + +$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + +$page_name = "WorkstationSetup"; +llxHeader('', $langs->trans($page_name)); + +// Subheader +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($langs->trans($page_name), $linkback, 'object_workstation@workstation'); + +// Configuration header +$head = workstationAdminPrepareHead(); +print dol_get_fiche_head($head, 'settings', '', -1, "workstation@workstation"); + +// Setup page goes here +//echo ''.$langs->trans("WorkstationSetupPage").'

'; + + +if ($action == 'edit') +{ + print '
'; + print ''; + print ''; + + print ''; + print ''; + + foreach ($arrayofparameters as $key => $val) + { + print ''; + } + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + $tooltiphelp = (($langs->trans($key.'Tooltip') != $key.'Tooltip') ? $langs->trans($key.'Tooltip') : ''); + print $form->textwithpicto($langs->trans($key), $tooltiphelp); + print '
'; + + print '
'; + print ''; + print '
'; + + print '
'; + print '
'; +} else { + if (!empty($arrayofparameters)) + { + print ''; + print ''; + + foreach ($arrayofparameters as $key => $val) + { + $setupnotempty++; + + print ''; + } + + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + $tooltiphelp = (($langs->trans($key.'Tooltip') != $key.'Tooltip') ? $langs->trans($key.'Tooltip') : ''); + print $form->textwithpicto($langs->trans($key), $tooltiphelp); + print ''.$conf->global->$key.'
'; + + print '
'; + print ''.$langs->trans("Modify").''; + print '
'; + }/* else { + print '
'.$langs->trans("NothingToSetup"); + }*/ +} + + +$moduledir = 'workstation'; +$myTmpObjects = array(); +$myTmpObjects['workstation'] = array('includerefgeneration'=>1, 'includedocgeneration'=>0); + + +foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) { + if ($myTmpObjectKey == 'MyObject') continue; + if ($myTmpObjectArray['includerefgeneration']) { + /* + * Orders Numbering model + */ + $setupnotempty++; + + print load_fiche_titre($langs->trans("NumberingModules", $myTmpObjectKey), '', ''); + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''."\n"; + + clearstatcache(); + + foreach ($dirmodels as $reldir) + { + $dir = dol_buildpath($reldir."core/modules/".$moduledir); + + if (is_dir($dir)) + { + $handle = opendir($dir); + if (is_resource($handle)) + { + while (($file = readdir($handle)) !== false) + { + if (strpos($file, 'mod_'.strtolower($myTmpObjectKey).'_') === 0 && substr($file, dol_strlen($file) - 3, 3) == 'php') + { + $file = substr($file, 0, dol_strlen($file) - 4); + + require_once $dir.'/'.$file.'.php'; + + $module = new $file($db); + + // Show modules according to features level + if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) continue; + if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) continue; + + if ($module->isEnabled()) + { + dol_include_once('/'.$moduledir.'/class/'.strtolower($myTmpObjectKey).'.class.php'); + + print ''; + + // Show example of numbering model + print ''."\n"; + + print ''; + + $mytmpinstance = new $myTmpObjectKey($db); + $mytmpinstance->initAsSpecimen(); + + // Info + $htmltooltip = ''; + $htmltooltip .= ''.$langs->trans("Version").': '.$module->getVersion().'
'; + + $nextval = $module->getNextValue($mytmpinstance); + if ("$nextval" != $langs->trans("NotAvailable")) { // Keep " on nextval + $htmltooltip .= ''.$langs->trans("NextValue").': '; + if ($nextval) { + if (preg_match('/^Error/', $nextval) || $nextval == 'NotConfigured') + $nextval = $langs->trans($nextval); + $htmltooltip .= $nextval.'
'; + } else { + $htmltooltip .= $langs->trans($module->error).'
'; + } + } + + print ''; + + print "\n"; + } + } + } + closedir($handle); + } + } + } + print "
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Example").''.$langs->trans("Status").''.$langs->trans("ShortInfo").'
'.$module->name."\n"; + print $module->info(); + print ''; + $tmp = $module->getExample(); + if (preg_match('/^Error/', $tmp)) { + $langs->load("errors"); + print '
'.$langs->trans($tmp).'
'; + } elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + else print $tmp; + print '
'; + $constforvar = 'WORKSTATION_'.strtoupper($myTmpObjectKey).'_ADDON'; + if ($conf->global->$constforvar == $file) + { + print img_picto($langs->trans("Activated"), 'switch_on'); + } else { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print ''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 0); + print '

\n"; + } + + if ($myTmpObjectArray['includedocgeneration']) { + /* + * Document templates generators + */ + $setupnotempty++; + $type = strtolower($myTmpObjectKey); + + print load_fiche_titre($langs->trans("DocumentModules", $myTmpObjectKey), '', ''); + + // Load array def with activated templates + $def = array(); + $sql = "SELECT nom"; + $sql .= " FROM ".MAIN_DB_PREFIX."document_model"; + $sql .= " WHERE type = '".$db->escape($type)."'"; + $sql .= " AND entity = ".$conf->entity; + $resql = $db->query($sql); + if ($resql) + { + $i = 0; + $num_rows = $db->num_rows($resql); + while ($i < $num_rows) + { + $array = $db->fetch_array($resql); + array_push($def, $array[0]); + $i++; + } + } else { + dol_print_error($db); + } + + print "\n"; + print "\n"; + print ''; + print ''; + print '\n"; + print '\n"; + print ''; + print ''; + print "\n"; + + clearstatcache(); + + foreach ($dirmodels as $reldir) + { + foreach (array('', '/doc') as $valdir) + { + $realpath = $reldir."core/modules/".$moduledir.$valdir; + $dir = dol_buildpath($realpath); + + if (is_dir($dir)) + { + $handle = opendir($dir); + if (is_resource($handle)) + { + while (($file = readdir($handle)) !== false) + { + $filelist[] = $file; + } + closedir($handle); + arsort($filelist); + + foreach ($filelist as $file) + { + if (preg_match('/\.modules\.php$/i', $file) && preg_match('/^(pdf_|doc_)/', $file)) + { + if (file_exists($dir.'/'.$file)) + { + $name = substr($file, 4, dol_strlen($file) - 16); + $classname = substr($file, 0, dol_strlen($file) - 12); + + require_once $dir.'/'.$file; + $module = new $classname($db); + + $modulequalified = 1; + if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) $modulequalified = 0; + if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) $modulequalified = 0; + + if ($modulequalified) + { + print ''; + + // Active + if (in_array($name, $def)) + { + print ''; + } else { + print '"; + } + + // Default + print ''; + + // Info + $htmltooltip = ''.$langs->trans("Name").': '.$module->name; + $htmltooltip .= '
'.$langs->trans("Type").': '.($module->type ? $module->type : $langs->trans("Unknown")); + if ($module->type == 'pdf') + { + $htmltooltip .= '
'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur; + } + $htmltooltip .= '
'.$langs->trans("Path").': '.preg_replace('/^\//', '', $realpath).'/'.$file; + + $htmltooltip .= '

'.$langs->trans("FeaturesSupported").':'; + $htmltooltip .= '
'.$langs->trans("Logo").': '.yn($module->option_logo, 1, 1); + $htmltooltip .= '
'.$langs->trans("MultiLanguage").': '.yn($module->option_multilang, 1, 1); + + print ''; + + // Preview + print ''; + + print "\n"; + } + } + } + } + } + } + } + } + + print '
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Status")."'.$langs->trans("Default")."'.$langs->trans("ShortInfo").''.$langs->trans("Preview").'
'; + print (empty($module->name) ? $name : $module->name); + print "\n"; + if (method_exists($module, 'info')) print $module->info($langs); + else print $module->description; + print ''."\n"; + print ''; + print img_picto($langs->trans("Enabled"), 'switch_on'); + print ''; + print ''."\n"; + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + print "'; + $constforvar = 'WORKSTATION_'.strtoupper($myTmpObjectKey).'_ADDON'; + if ($conf->global->$constforvar == $name) + { + print img_picto($langs->trans("Default"), 'on'); + } else { + print 'scandir.'&label='.urlencode($module->name).'" alt="'.$langs->trans("Default").'">'.img_picto($langs->trans("Disabled"), 'off').''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 0); + print ''; + if ($module->type == 'pdf') + { + print ''.img_object($langs->trans("Preview"), 'generic').''; + } else { + print img_object($langs->trans("PreviewNotAvailable"), 'generic'); + } + print '
'; + } +} + +/*if (empty($setupnotempty)) { + print '
'.$langs->trans("NothingToSetup"); +}*/ + +// Page end +print dol_get_fiche_end(); + +llxFooter(); +$db->close(); diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 38e8b601cf6..47f1d336279 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -134,10 +134,10 @@ if (empty($reshook)) // Set if we used free entry or predefined product $idprod = (int) GETPOST('idprod', 'int'); - $qty = GETPOST('qty', 'int'); - $qty_frozen = GETPOST('qty_frozen', 'int'); + $qty = price2num(GETPOST('qty', 'alpha'), 'MS'); + $qty_frozen = price2num(GETPOST('qty_frozen', 'alpha'), 'MS'); $disable_stock_change = GETPOST('disable_stock_change', 'int'); - $efficiency = GETPOST('efficiency', 'int'); + $efficiency = price2num(GETPOST('efficiency', 'alpha')); if ($qty == '') { setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors'); @@ -155,8 +155,6 @@ if (empty($reshook)) if (!$error) { - $lastposition = 0; - $bomline = new BOMLine($db); $bomline->fk_bom = $id; $bomline->fk_product = $idprod; @@ -195,10 +193,10 @@ if (empty($reshook)) $error = 0; // Set if we used free entry or predefined product - $qty = price2num(GETPOST('qty', 'int')); - $qty_frozen = GETPOST('qty_frozen', 'int'); + $qty = price2num(GETPOST('qty', 'alpha'), 'MS'); + $qty_frozen = price2num(GETPOST('qty_frozen', 'alpha'), 'MS'); $disable_stock_change = GETPOST('disable_stock_change', 'int'); - $efficiency = price2num(GETPOST('efficiency', 'int')); + $efficiency = price2num(GETPOST('efficiency', 'alpha')); if ($qty == '') { setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors'); diff --git a/htdocs/bom/tpl/objectline_create.tpl.php b/htdocs/bom/tpl/objectline_create.tpl.php index 1f0a00cb4b8..9e54fc67e8a 100644 --- a/htdocs/bom/tpl/objectline_create.tpl.php +++ b/htdocs/bom/tpl/objectline_create.tpl.php @@ -141,7 +141,7 @@ print ''; print ''; if (is_object($objectline)) { - print $objectline->showOptionals($extrafields, 'edit', array('style'=>$bcnd[$var], 'colspan'=>$coldisplay), '', '', 1); + print $objectline->showOptionals($extrafields, 'edit', array('style'=>$bcnd[$var], 'colspan'=>$coldisplay), '', '', 1, 'line'); } ?> diff --git a/htdocs/bom/tpl/objectline_edit.tpl.php b/htdocs/bom/tpl/objectline_edit.tpl.php index f31db94403b..4d10539c824 100644 --- a/htdocs/bom/tpl/objectline_edit.tpl.php +++ b/htdocs/bom/tpl/objectline_edit.tpl.php @@ -141,7 +141,7 @@ print ''; print ''; if (is_object($objectline)) { - print $objectline->showOptionals($extrafields, 'edit', array('style'=>$bcnd[$var], 'colspan'=>$coldisplay), '', '', 1); + print $objectline->showOptionals($extrafields, 'edit', array('style'=>$bcnd[$var], 'colspan'=>$coldisplay), '', '', 1, 'line'); } print "\n"; diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index 87c1a72789d..bc8506b2151 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -161,7 +161,7 @@ print ''; //Line extrafield if (!empty($extrafields)) { - print $line->showOptionals($extrafields, 'view', array('style'=>'class="drag drop oddeven"', 'colspan'=>$coldisplay), '', '', 1); + print $line->showOptionals($extrafields, 'view', array('style'=>'class="drag drop oddeven"', 'colspan'=>$coldisplay), '', '', 1, 'line'); } print "\n"; diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index 53e498fe303..cf64e0a1d04 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -1266,6 +1266,12 @@ if ($object->id > 0) } } + // Allow external modules to add their own shortlist of recent objects + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreRecentObjects', $parameters, $object, $action); + if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + else print $hookmanager->resPrint; + print ''; print '
'; diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 71da2e69336..23c960d3a4b 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -130,6 +130,8 @@ $permissiondellink = $usercancreate; // Used by the include of actions_dellink.i $permissiontoedit = $usercancreate; // Used by the include of actions_lineupdown.inc.php +//if ($thirdparty->fk_warehouse > 0) $object->warehouse_id = $thirdparty->fk_warehouse; + /* * Actions */ @@ -242,6 +244,7 @@ if (empty($reshook)) } // Validation elseif ($action == 'confirm_validate' && $confirm == 'yes' && $usercanvalidate) { + $idwarehouse = GETPOST('idwarehouse', 'int'); $result = $object->valid($user); if ($result >= 0) { @@ -349,6 +352,7 @@ if (empty($reshook)) $object->demand_reason_id = GETPOST('demand_reason_id'); $object->fk_delivery_address = GETPOST('fk_address', 'int'); $object->shipping_method_id = GETPOST('shipping_method_id', 'int'); + $object->warehouse_id = GETPOST('warehouse_id', 'int'); $object->duree_validite = $duration; $object->cond_reglement_id = GETPOST('cond_reglement_id'); $object->mode_reglement_id = GETPOST('mode_reglement_id'); @@ -380,6 +384,7 @@ if (empty($reshook)) $object->demand_reason_id = GETPOST('demand_reason_id', 'int'); $object->fk_delivery_address = GETPOST('fk_address', 'int'); $object->shipping_method_id = GETPOST('shipping_method_id', 'int'); + $object->warehouse_id = GETPOST('warehouse_id', 'int'); $object->duree_validite = price2num(GETPOST('duree_validite', 'alpha')); $object->cond_reglement_id = GETPOST('cond_reglement_id', 'int'); $object->mode_reglement_id = GETPOST('mode_reglement_id', 'int'); @@ -809,7 +814,7 @@ if (empty($reshook)) $tva_tx = ''; } - $qty = price2num(GETPOST('qty'.$predef), 'MS'); + $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS'); $remise_percent = GETPOST('remise_percent'.$predef); if (empty($remise_percent)) $remise_percent = 0; @@ -1239,7 +1244,7 @@ if (empty($reshook)) } } - $qty = price2num(GETPOST('qty'), 'MS'); + $qty = price2num(GETPOST('qty', 'alpha'), 'MS'); $result = $object->updateline(GETPOST('lineid', 'int'), $pu_ht, $qty, GETPOST('remise_percent'), $vat_rate, $localtax1_rate, $localtax2_rate, $description, 'HT', $info_bits, $special_code, GETPOST('fk_parent_line'), 0, $fournprice, $buyingprice, $label, $type, $date_start, $date_end, $array_options, $_POST["units"], $pu_ht_devise); @@ -1325,6 +1330,9 @@ if (empty($reshook)) } // shipping method elseif ($action == 'setshippingmethod' && $usercancreate) { $result = $object->setShippingMethod(GETPOST('shipping_method_id', 'int')); + }// warehouse + elseif ($action == 'setwarehouse' && $usercancreate) { + $result = $object->setWarehouse(GETPOST('warehouse_id', 'int')); } elseif ($action == 'update_extras') { $object->oldcopy = dol_clone($object); @@ -1469,6 +1477,7 @@ if ($action == 'create') $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0)); $remise_percent = (!empty($objectsrc->remise_percent) ? $objectsrc->remise_percent : (!empty($soc->remise_percent) ? $soc->remise_percent : 0)); $remise_absolue = (!empty($objectsrc->remise_absolue) ? $objectsrc->remise_absolue : (!empty($soc->remise_absolue) ? $soc->remise_absolue : 0)); + $warehouse_id = (!empty($objectsrc->warehouse_id) ? $objectsrc->warehouse_id : (!empty($soc->warehouse_id) ? $soc->warehouse_id : 0)); $dateinvoice = (empty($dateinvoice) ? (empty($conf->global->MAIN_AUTOFILL_DATE) ?-1 : '') : $dateinvoice); // Replicate extrafields @@ -1485,6 +1494,13 @@ if ($action == 'create') if (!empty($conf->multicurrency->enabled) && !empty($soc->multicurrency_code)) $currency_code = $soc->multicurrency_code; } + //Warehouse default if null + if (!empty($conf->stock->enabled) && empty($warehouse_id) && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) + { + if (empty($object->warehouse_id) && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE)) $warehouse_id = $conf->global->MAIN_DEFAULT_WAREHOUSE; + if (empty($object->warehouse_id) && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE_USER)) $warehouse_id = $user->fk_warehouse; + } + $object = new Propal($db); print '
'; @@ -1517,9 +1533,13 @@ if ($action == 'create') print $soc->getNomUrl(1); print ''; print ''; + if (!empty($conf->global->SOCIETE_ASK_FOR_SHIPPING_METHOD) && !empty($soc->shipping_method_id)) { + $shipping_method_id = $soc->shipping_method_id; + } + //$warehouse_id = $soc->warehouse_id; } else { print ''; - print $form->select_company('', 'socid', '(s.client = 1 OR s.client = 2 OR s.client = 3) AND status=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300 maxwidth500'); + print img_picto('', 'company').$form->select_company('', 'socid', '(s.client = 1 OR s.client = 2 OR s.client = 3) AND status=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300 maxwidth500'); // reload page to retrieve customer informations if (empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED)) { @@ -1543,6 +1563,7 @@ if ($action == 'create') { // Contacts (ask contact only if thirdparty already defined). print "".$langs->trans("DefaultContact").''; + print img_picto('', 'contact'); $form->select_contacts($soc->id, $contactid, 'contactid', 1, $srccontactslist); print ''; @@ -1560,25 +1581,28 @@ if ($action == 'create') // Date print ''.$langs->trans('Date').''; - print $form->selectDate('', '', '', '', '', "addprop", 1, 1); + print img_picto('', 'object_calendarday').' '.$form->selectDate('', '', '', '', '', "addprop", 1, 1); print ''; // Validaty duration - print ''.$langs->trans("ValidityDuration").' '.$langs->trans("days").''; + print ''.$langs->trans("ValidityDuration").''.img_picto('', 'clock').'  '.$langs->trans("days").''; // Terms of payment print ''.$langs->trans('PaymentConditionsShort').''; + print img_picto('', 'paiment'); $form->select_conditions_paiements((GETPOSTISSET('cond_reglement_id') ? GETPOST('cond_reglement_id', 'int') : $soc->cond_reglement_id), 'cond_reglement_id', -1, 1); print ''; // Mode of payment print ''.$langs->trans('PaymentMode').''; + print img_picto('', 'bank').' '; $form->select_types_paiements((GETPOSTISSET('mode_reglement_id') ? GETPOST('mode_reglement_id', 'int') : $soc->mode_reglement_id), 'mode_reglement_id'); print ''; // Bank Account if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL) && !empty($conf->banque->enabled)) { print ''.$langs->trans('BankAccount').''; + print img_picto('', 'bank_account'); $form->select_comptes($soc->fk_account, 'fk_account', 0, '', 1); print ''; } @@ -1593,6 +1617,7 @@ if ($action == 'create') if (!empty($conf->commande->enabled)) print ' ('.$langs->trans('AfterOrder').')'; print ''; + print img_picto('', 'clock').' '; $form->selectAvailabilityDelay('', 'availability_id', '', 1); print ''; @@ -1602,13 +1627,24 @@ if ($action == 'create') $shipping_method_id = $soc->shipping_method_id; } print ''.$langs->trans('SendingMethod').''; + print img_picto('', 'object_dollyrevert').' '; print $form->selectShippingMethod($shipping_method_id, 'shipping_method_id', '', 1); print ''; } + // Warehouse + if (!empty($conf->stock->enabled) && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL)) { + require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; + $formproduct = new FormProduct($db); + print ''.$langs->trans('Warehouse').''; + print img_picto('', 'stock').$formproduct->selectWarehouses($warehouse_id, 'warehouse_id', '', 1, 0, 0, '', 0, 0, array(), 'maxwidth175 maxwidth500 widthcentpercentminusxx'); + print ''; + } + // Delivery date (or manufacturing) print ''.$langs->trans("DeliveryDate").''; print ''; + print img_picto('', 'object_calendarday').' '; if ($conf->global->DATE_LIVRAISON_WEEK_DELAY != "") { $tmpdte = time() + ((7 * $conf->global->DATE_LIVRAISON_WEEK_DELAY) * 24 * 60 * 60); $syear = date("Y", $tmpdte); @@ -1626,6 +1662,7 @@ if ($action == 'create') $langs->load("projects"); print ''; print ''.$langs->trans("Project").''; + print img_picto('', 'project'); $numprojet = $formproject->select_projects(($soc->id > 0 ? $soc->id : -1), $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 0, 0, 'maxwidth500'); print ' id).'">'; print ''; @@ -1646,6 +1683,7 @@ if ($action == 'create') print ''; print ''.$langs->trans("DefaultModel").''; print ''; + print img_picto('', 'pdf').' '; $liste = ModelePDFPropales::liste_modeles($db); print $form->selectarray('model', $liste, ($conf->global->PROPALE_ADDON_PDF_ODT_DEFAULT ? $conf->global->PROPALE_ADDON_PDF_ODT_DEFAULT : $conf->global->PROPALE_ADDON_PDF)); print ""; @@ -2102,6 +2140,24 @@ if ($action == 'create') print ''; } + // Warehouse + if (!empty($conf->stock->enabled) && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL)) { + $langs->load('stocks'); + require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; + $formproduct = new FormProduct($db); + print ''; + $editenable = $usercancreate; + print $form->editfieldkey("Warehouse", 'warehouse', '', $object, $editenable); + print ''; + if ($action == 'editwarehouse') { + $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'warehouse_id', 1); + } else { + $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->warehouse_id, 'none'); + } + print ''; + print ''; + } + // Origin of demand print ''; print ''; } + if (!empty($arrayfields['s.name_alias']['checked'])) + { + print ''; + } if (!empty($arrayfields['s.town']['checked'])) print ''; if (!empty($arrayfields['s.zip']['checked'])) print ''; // State @@ -861,6 +872,7 @@ if ($resql) if (!empty($arrayfields['pr.ref']['checked'])) print_liste_field_titre($arrayfields['pr.ref']['label'], $_SERVER["PHP_SELF"], 'pr.ref', '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['pr.title']['checked'])) print_liste_field_titre($arrayfields['pr.title']['label'], $_SERVER["PHP_SELF"], 'pr.title', '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['s.nom']['checked'])) print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], 's.nom', '', $param, '', $sortfield, $sortorder); + if (!empty($arrayfields['s.name_alias']['checked'])) print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], 's.name_alias', '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['s.town']['checked'])) print_liste_field_titre($arrayfields['s.town']['label'], $_SERVER["PHP_SELF"], 's.town', '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['s.zip']['checked'])) print_liste_field_titre($arrayfields['s.zip']['label'], $_SERVER["PHP_SELF"], 's.zip', '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['state.nom']['checked'])) print_liste_field_titre($arrayfields['state.nom']['label'], $_SERVER["PHP_SELF"], "state.nom", "", $param, '', $sortfield, $sortorder); @@ -1024,6 +1036,15 @@ if ($resql) if (!$i) $totalarray['nbfield']++; } + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) + { + print ''; + if (!$i) $totalarray['nbfield']++; + } + // Town if (!empty($arrayfields['s.town']['checked'])) { diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 1fc7a0bf48b..6dd6fc6911a 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -113,11 +113,6 @@ $permissionnote = $usercancreate; // Used by the include of actions_setnotes.inc $permissiondellink = $usercancreate; // Used by the include of actions_dellink.inc.php $permissiontoadd = $usercancreate; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php -if (!empty($conf->expedition->enabled) && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) { - if (empty($object->warehouse_id) && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE)) $object->warehouse_id = $conf->global->MAIN_DEFAULT_WAREHOUSE; - if (empty($object->warehouse_id) && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE_USER)) $object->warehouse_id = $user->fk_warehouse; -} - $error = 0; $date_delivery = dol_mktime(GETPOST('liv_hour', 'int'), GETPOST('liv_min', 'int'), 0, GETPOST('liv_month', 'int'), GETPOST('liv_day', 'int'), GETPOST('liv_year', 'int')); @@ -633,7 +628,7 @@ if (empty($reshook)) $predef = ''; $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : ''); $price_ht = price2num(GETPOST('price_ht'), 'MU'); - $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CR'); + $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU'); $prod_entry_mode = GETPOST('prod_entry_mode'); if ($prod_entry_mode == 'free') { @@ -644,7 +639,7 @@ if (empty($reshook)) $tva_tx = ''; } - $qty = price2num(GETPOST('qty'.$predef, 'alpha')); + $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS'); $remise_percent = (GETPOSTISSET('remise_percent'.$predef) ? price2num(GETPOST('remise_percent'.$predef, 'alpha')) : 0); // Extrafields @@ -1538,6 +1533,13 @@ if ($action == 'create' && $usercancreate) $note_public = $object->getDefaultCreateValueFor('note_public'); } + //Warehouse default if null + if (!empty($conf->stock->enabled) && empty($warehouse_id) && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) + { + if (empty($object->warehouse_id) && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE)) $warehouse_id = $conf->global->MAIN_DEFAULT_WAREHOUSE; + if (empty($object->warehouse_id) && !empty($conf->global->MAIN_DEFAULT_WAREHOUSE_USER)) $warehouse_id = $user->fk_warehouse; + } + print ''; print ''; print ''; @@ -1595,6 +1597,7 @@ if ($action == 'create' && $usercancreate) if ($socid > 0) { // Contacts (ask contact only if thirdparty already defined). print "'; @@ -1613,14 +1616,14 @@ if ($action == 'create' && $usercancreate) // Date print ''; // Date delivery planned print ''; print '\n"; print ''; @@ -1631,6 +1634,7 @@ if ($action == 'create' && $usercancreate) // Mode de reglement print ''; @@ -1638,24 +1642,27 @@ if ($action == 'create' && $usercancreate) if (!empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_ORDER) && !empty($conf->banque->enabled)) { print ''; } // Delivery delay print ''; // Shipping Method if (!empty($conf->expedition->enabled)) { print ''; } // Warehouse - if (!empty($conf->expedition->enabled) && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) { + if (!empty($conf->stock->enabled) && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) { require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; $formproduct = new FormProduct($db); print ''; print ''; } + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) + { + print ''; + } // Town if (!empty($arrayfields['s.town']['checked'])) print ''; // Zip @@ -917,6 +929,7 @@ if ($resql) if (!empty($arrayfields['p.ref']['checked'])) print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder); if (!empty($arrayfields['p.title']['checked'])) print_liste_field_titre($arrayfields['p.title']['label'], $_SERVER["PHP_SELF"], "p.title", "", $param, '', $sortfield, $sortorder); if (!empty($arrayfields['s.nom']['checked'])) print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER["PHP_SELF"], 's.nom', '', $param, '', $sortfield, $sortorder); + if (!empty($arrayfields['s.name_alias']['checked'])) print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER["PHP_SELF"], 's.name_alias', '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['s.town']['checked'])) print_liste_field_titre($arrayfields['s.town']['label'], $_SERVER["PHP_SELF"], 's.town', '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['s.zip']['checked'])) print_liste_field_titre($arrayfields['s.zip']['label'], $_SERVER["PHP_SELF"], 's.zip', '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['state.nom']['checked'])) print_liste_field_titre($arrayfields['state.nom']['label'], $_SERVER["PHP_SELF"], "state.nom", "", $param, '', $sortfield, $sortorder); @@ -1077,6 +1090,14 @@ if ($resql) if (!$i) $totalarray['nbfield']++; } // Town + if (!empty($arrayfields['s.name_alias']['checked'])) + { + print ''; + if (!$i) $totalarray['nbfield']++; + } + // Town if (!empty($arrayfields['s.town']['checked'])) { print ''; } - $datefacture = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); + $newdateinvoice = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); // Date invoice print ''; // Date point of tax @@ -3509,7 +3525,7 @@ if ($action == 'create') $htmltext = ''; if (GETPOST('fac_rec', 'int') > 0) { - $dateexample = ($datefacture ? $datefacture : $dateinvoice); + $dateexample = ($newdateinvoice ? $newdateinvoice : $dateinvoice); if (empty($dateexample)) $dateexample = dol_now(); $substitutionarray = array( '__TOTAL_HT__' => $langs->trans("AmountHT").' ('.$langs->trans("Example").': '.price($exampletemplateinvoice->total_ht).')', diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index a1bde7e4f3d..da5bab5b47e 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -85,6 +85,7 @@ $search_type = GETPOST('search_type', 'int'); $search_project_ref = GETPOST('search_project_ref', 'alpha'); $search_project = GETPOST('search_project', 'alpha'); $search_societe = GETPOST('search_societe', 'alpha'); +$search_societe_alias = GETPOST('search_societe_alias', 'alpha'); $search_montant_ht = GETPOST('search_montant_ht', 'alpha'); $search_montant_vat = GETPOST('search_montant_vat', 'alpha'); $search_montant_localtax1 = GETPOST('search_montant_localtax1', 'alpha'); @@ -182,6 +183,7 @@ $arrayfields = array( 'p.ref'=>array('label'=>"ProjectRef", 'checked'=>1, 'enabled'=>(empty($conf->projet->enabled) ? 0 : 1), 'position'=>40), 'p.title'=>array('label'=>"ProjectLabel", 'checked'=>0, 'enabled'=>(empty($conf->projet->enabled) ? 0 : 1), 'position'=>40), 's.nom'=>array('label'=>"ThirdParty", 'checked'=>1, 'position'=>50), + 's.name_alias'=>array('label'=>"AliasNameShort", 'checked'=>1, 'position'=>51), 's.town'=>array('label'=>"Town", 'checked'=>1, 'position'=>55), 's.zip'=>array('label'=>"Zip", 'checked'=>1, 'position'=>60), 'state.nom'=>array('label'=>"StateShort", 'checked'=>0, 'position'=>65), @@ -254,6 +256,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter', $search_project_ref = ''; $search_project = ''; $search_societe = ''; + $search_societe_alias = ''; $search_montant_ht = ''; $search_montant_vat = ''; $search_montant_localtax1 = ''; @@ -422,7 +425,7 @@ $sql .= ' f.datef as df, f.date_valid, f.date_lim_reglement as datelimite, f.mod $sql .= ' f.paye as paye, f.fk_statut, f.close_code,'; $sql .= ' f.datec as date_creation, f.tms as date_update, f.date_closing as date_closing,'; $sql .= ' f.retained_warranty, f.retained_warranty_date_limit, f.situation_final, f.situation_cycle_ref, f.situation_counter,'; -$sql .= ' s.rowid as socid, s.nom as name, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur,'; +$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as name_alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta as code_compta_client, s.code_compta_fournisseur,'; $sql .= " typent.code as typent_code,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; $sql .= " country.code as country_code,"; @@ -486,12 +489,14 @@ if ($search_type != '' && $search_type != '-1') $sql .= " AND f.type IN (".$db-> if ($search_project_ref) $sql .= natural_search('p.ref', $search_project_ref); if ($search_project) $sql .= natural_search('p.title', $search_project); if ($search_societe) $sql .= natural_search('s.nom', $search_societe); +if ($search_societe_alias) $sql .= natural_search('s.name_alias', $search_societe_alias); if ($search_town) $sql .= natural_search('s.town', $search_town); if ($search_zip) $sql .= natural_search("s.zip", $search_zip); if ($search_state) $sql .= natural_search("state.nom", $search_state); if ($search_country) $sql .= " AND s.fk_pays IN (".$db->sanitize($db->escape($search_country)).')'; if ($search_type_thirdparty) $sql .= " AND s.fk_typent IN (".$db->sanitize($db->escape($search_type_thirdparty)).')'; if ($search_company) $sql .= natural_search('s.nom', $search_company); +if ($search_company_alias) $sql .= natural_search('s.name_alias', $search_company_alias); if ($search_montant_ht != '') $sql .= natural_search('f.total', $search_montant_ht, 1); if ($search_montant_vat != '') $sql .= natural_search('f.tva', $search_montant_vat, 1); if ($search_montant_localtax1 != '') $sql .= natural_search('f.localtax1', $search_montant_localtax1, 1); @@ -551,7 +556,7 @@ if (!$sall) $sql .= ' f.retained_warranty, f.retained_warranty_date_limit, f.situation_final, f.situation_cycle_ref, f.situation_counter,'; $sql .= ' f.fk_user_author, f.fk_multicurrency, f.multicurrency_code, f.multicurrency_tx, f.multicurrency_total_ht, f.multicurrency_total_tva,'; $sql .= ' f.multicurrency_total_tva, f.multicurrency_total_ttc,'; - $sql .= ' s.rowid, s.nom, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,'; + $sql .= ' s.rowid, s.nom, s.name_alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,'; $sql .= ' typent.code,'; $sql .= ' state.code_departement, state.nom,'; $sql .= ' country.code,'; @@ -628,6 +633,7 @@ if ($resql) if ($search_project) $param .= '&search_project='.urlencode($search_project); if ($search_type != '') $param .= '&search_type='.urlencode($search_type); if ($search_societe) $param .= '&search_societe='.urlencode($search_societe); + if ($search_societe_alias) $param .= '&search_societe_alias='.urlencode($search_societe_alias); if ($search_town) $param .= '&search_town='.urlencode($search_town); if ($search_zip) $param .= '&search_zip='.urlencode($search_zip); if ($search_sale > 0) $param .= '&search_sale='.urlencode($search_sale); @@ -861,6 +867,11 @@ if ($resql) { print ''; } + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) + { + print ''; + } // Town if (!empty($arrayfields['s.town']['checked'])) print ''; // Zip @@ -1099,6 +1110,7 @@ if ($resql) if (!empty($arrayfields['p.ref']['checked'])) print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER['PHP_SELF'], "p.ref", '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['p.title']['checked'])) print_liste_field_titre($arrayfields['p.title']['label'], $_SERVER['PHP_SELF'], "p.title", '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['s.nom']['checked'])) print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER['PHP_SELF'], 's.nom', '', $param, '', $sortfield, $sortorder); + if (!empty($arrayfields['s.name_alias']['checked'])) print_liste_field_titre($arrayfields['s.name_alias']['label'], $_SERVER['PHP_SELF'], 's.name_alias', '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['s.town']['checked'])) print_liste_field_titre($arrayfields['s.town']['label'], $_SERVER["PHP_SELF"], 's.town', '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['s.zip']['checked'])) print_liste_field_titre($arrayfields['s.zip']['label'], $_SERVER["PHP_SELF"], 's.zip', '', $param, '', $sortfield, $sortorder); if (!empty($arrayfields['state.nom']['checked'])) print_liste_field_titre($arrayfields['state.nom']['label'], $_SERVER["PHP_SELF"], "state.nom", "", $param, '', $sortfield, $sortorder); @@ -1361,6 +1373,14 @@ if ($resql) print ''; if (!$i) $totalarray['nbfield']++; } + // Alias + if (!empty($arrayfields['s.name_alias']['checked'])) + { + print ''; + if (!$i) $totalarray['nbfield']++; + } // Town if (!empty($arrayfields['s.town']['checked'])) { diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index 6b7f1612836..89737ca917f 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -578,9 +578,10 @@ class Paiement extends CommonObject * @param string $emetteur_nom Name of transmitter * @param string $emetteur_banque Name of bank * @param int $notrigger No trigger + * @param string $accountancycode When we record a free bank entry, we must provide accounting account if accountancy module is on. * @return int <0 if KO, bank_line_id if OK */ - public function addPaymentToBank($user, $mode, $label, $accountid, $emetteur_nom, $emetteur_banque, $notrigger = 0) + public function addPaymentToBank($user, $mode, $label, $accountid, $emetteur_nom, $emetteur_banque, $notrigger = 0, $accountancycode = '') { global $conf, $langs, $user; @@ -625,7 +626,8 @@ class Paiement extends CommonObject '', $user, $emetteur_nom, - $emetteur_banque + $emetteur_banque, + $accountancycode ); // Mise a jour fk_bank dans llx_paiement diff --git a/htdocs/contact/card.php b/htdocs/contact/card.php index 35c4bdc43e5..566b044c81e 100644 --- a/htdocs/contact/card.php +++ b/htdocs/contact/card.php @@ -200,7 +200,7 @@ if (empty($reshook)) } } } - $object->email = (string) GETPOST("email", 'alpha'); + $object->email = (string) GETPOST('email', 'custom', 0, FILTER_SANITIZE_EMAIL); $object->no_email = GETPOST("no_email", "int"); $object->phone_pro = (string) GETPOST("phone_pro", 'alpha'); $object->phone_perso = (string) GETPOST("phone_perso", 'alpha'); @@ -225,44 +225,59 @@ if (empty($reshook)) $action = 'create'; } - if (!GETPOST("lastname")) { + if (!empty($conf->mailing->enabled) && $conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS==-1 && $object->no_email==-1 && !empty($object->email)) { + $error++; + $errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentities("No_Email")); + $action = 'create'; + } + + if (!empty($object->email) && !isValidEMail($object->email)) + { + $langs->load("errors"); + $error++; + $errors[] = $langs->trans("ErrorBadEMail", GETPOST('email', 'alpha')); + $action = 'create'; + } + + if (empty($object->lastname)) { $error++; $errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentities("Lastname").' / '.$langs->transnoentities("Label")); $action = 'create'; } - if (!$error) - { + if (empty($error)) { $id = $object->create($user); - if ($id <= 0) - { + if ($id <= 0) { $error++; $errors = array_merge($errors, ($object->error ? array($object->error) : $object->errors)); $action = 'create'; - } else { - // Categories association - $contcats = GETPOST('contcats', 'array'); - $object->setCategories($contcats); + } + } - // Add mass emailing flag into table mailing_unsubscribe - if (GETPOST('no_email', 'int') && $object->email) - { - $sql = "SELECT COUNT(*) as nb FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE entity IN (".getEntity('mailing', 0).") AND email = '".$db->escape($object->email)."'"; - $resql = $db->query($sql); - if ($resql) - { - $obj = $db->fetch_object($resql); - if (empty($obj->nb)) - { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."mailing_unsubscribe(email, entity, date_creat) VALUES ('".$db->escape($object->email)."', ".$db->escape(getEntity('mailing', 0)).", '".$db->idate(dol_now())."')"; - $resql = $db->query($sql); - } - } + if (empty($error)) { + // Categories association + $contcats = GETPOST('contcats', 'array'); + if (count($contcats)>0) { + $result = $object->setCategories($contcats); + if ($result <= 0) { + $error++; + $errors = array_merge($errors, ($object->error ? array($object->error) : $object->errors)); + $action = 'create'; } } } - if (!$error && $id > 0) + if (empty($error) && !empty($conf->mailing->enabled) && !empty($object->email)) { + // Add mass emailing flag into table mailing_unsubscribe + $result=$object->setNoEmail($object->no_email); + if ($result<0) { + $error++; + $errors = array_merge($errors, ($object->error ? array($object->error) : $object->errors)); + $action = 'create'; + } + } + + if (empty($error) && $id > 0) { $db->commit(); if (!empty($backtopage)) $url = $backtopage; @@ -298,12 +313,26 @@ if (empty($reshook)) if ($action == 'update' && !$_POST["cancel"] && $user->rights->societe->contact->creer) { - if (empty($_POST["lastname"])) + if (empty(GETPOST("lastname", 'alpha'))) { $error++; $errors = array($langs->trans("ErrorFieldRequired", $langs->transnoentities("Name").' / '.$langs->transnoentities("Label"))); $action = 'edit'; } + if (!empty($conf->mailing->enabled) && $conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS==-1 && GETPOST("no_email", "int")==-1 && !empty(GETPOST('email', 'custom', 0, FILTER_SANITIZE_EMAIL))) { + $error++; + $errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentities("No_Email")); + $action = 'edit'; + } + + if (!empty(GETPOST('email', 'custom', 0, FILTER_SANITIZE_EMAIL)) && !isValidEMail(GETPOST('email', 'custom', 0, FILTER_SANITIZE_EMAIL))) + { + $langs->load("errors"); + $error++; + $errors[] = $langs->trans("ErrorBadEMail", GETPOST('email', 'alpha')); + $action = 'edit'; + } + if (!$error) { $contactid = GETPOST("contactid", 'int'); @@ -374,7 +403,7 @@ if (empty($reshook)) $object->state_id = GETPOST("state_id", 'int'); $object->country_id = GETPOST("country_id", 'int'); - $object->email = (string) GETPOST("email", 'alpha'); + $object->email = (string) GETPOST('email', 'custom', 0, FILTER_SANITIZE_EMAIL); $object->no_email = GETPOST("no_email", "int"); //$object->jabberid = GETPOST("jabberid", 'alpha'); //$object->skype = GETPOST("skype", 'alpha'); @@ -411,31 +440,15 @@ if (empty($reshook)) $categories = GETPOST('contcats', 'array'); $object->setCategories($categories); - $no_email = GETPOST('no_email', 'int'); - // Update mass emailing flag into table mailing_unsubscribe if (GETPOSTISSET('no_email') && $object->email) { - if ($no_email) - { - $sql = "SELECT COUNT(*) as nb FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE entity IN (".getEntity('mailing', 0).") AND email = '".$db->escape($object->email)."'"; - $resql = $db->query($sql); - if ($resql) - { - $obj = $db->fetch_object($resql); - $noemail = $obj->nb; - if (empty($noemail)) - { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."mailing_unsubscribe(email, entity, date_creat) VALUES ('".$db->escape($object->email)."', ".$db->escape(getEntity('mailing', 0)).", '".$db->idate(dol_now())."')"; - $resql = $db->query($sql); - } - } - } else { - $sql = "DELETE FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE email = '".$db->escape($object->email)."' AND entity = ".$db->escape(getEntity('mailing', 0)); - $resql = $db->query($sql); + $no_email = GETPOST('no_email', 'int'); + $result=$object->setNoEmail($no_email); + if ($result<0) { + setEventMessages($object->error, $object->errors, 'errors'); + $action = 'edit'; } - - $object->no_email = $no_email; } $object->old_lastname = ''; @@ -738,27 +751,36 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) print ''; print ''; + //Unsubscribe if (!empty($conf->mailing->enabled)) { - $noemail = ''; - if (empty($noemail) && !empty($object->email)) + if ($conf->use_javascript_ajax && $conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS==-1) { - $sql = "SELECT COUNT(*) as nb FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE entity IN (".getEntity('mailing').") AND email = '".$db->escape($object->email)."'"; - //print $sql; - $resql = $db->query($sql); - if ($resql) - { - $obj = $db->fetch_object($resql); - $noemail = $obj->nb; + print "\n".''."\n"; + } + if (!GETPOSTISSET("no_email") && !empty($object->email)) + { + $result=$object->getNoEmail(); + if ($result<0) { + setEventMessages($object->error, $object->errors, 'errors'); } } - print ''; - print ''; - print ''; + print ''; + print ''; print ''; } - print ''; + if (!empty($conf->socialnetworks->enabled)) { foreach ($socialnetworks as $key => $value) { @@ -774,39 +796,6 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) } } } - // if (! empty($conf->socialnetworks->enabled)) - // { - // // Jabber - // if (! empty($conf->global->SOCIALNETWORKS_JABBER)) - // { - // print ''; - // print ''; - // } - // // Skype - // if (! empty($conf->global->SOCIALNETWORKS_SKYPE)) - // { - // print ''; - // print ''; - // } - // // Twitter - // if (! empty($conf->global->SOCIALNETWORKS_TWITTER)) - // { - // print ''; - // print ''; - // } - // // Facebook - // if (! empty($conf->global->SOCIALNETWORKS_FACEBOOK)) - // { - // print ''; - // print ''; - // } - // // LinkedIn - // if (! empty($conf->global->SOCIALNETWORKS_LINKEDIN)) - // { - // print ''; - // print ''; - // } - // } // Visibility print ''; // Unsubscribe - print ''; if (!empty($conf->mailing->enabled)) { - $noemail = ''; - if (empty($noemail) && !empty($object->email)) + if ($conf->use_javascript_ajax && $conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS==-1) { - $sql = "SELECT COUNT(*) as nb FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE entity IN (".getEntity('mailing').") AND email = '".$db->escape($object->email)."'"; - //print $sql; - $resql = $db->query($sql); - if ($resql) - { - $obj = $db->fetch_object($resql); - $noemail = $obj->nb; + print "\n".''."\n"; + } + if (!GETPOSTISSET("no_email") && !empty($object->email)) + { + $result=$object->getNoEmail(); + if ($result<0) { + setEventMessages($object->error, $object->errors, 'errors'); } } - - print ''; - print ''; - } else { - print ''; + print ''; + print ''; + print ''; + print ''; } - print ''; if (!empty($conf->socialnetworks->enabled)) { foreach ($socialnetworks as $key => $value) { @@ -1300,20 +1301,11 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) // Unsubscribe opt-out if (!empty($conf->mailing->enabled)) { - //print 'eee'.$object->email; - $noemail = $object->no_email; - if (empty($noemail) && !empty($object->email)) - { - $sql = "SELECT COUNT(*) as nb FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE entity IN (".getEntity('mailing').") AND email = '".$db->escape($object->email)."'"; - //print $sql; - $resql = $db->query($sql); - if ($resql) - { - $obj = $db->fetch_object($resql); - $noemail = $obj->nb; - } + $result=$object->getNoEmail(); + if ($result<0) { + setEventMessages($object->error, $object->errors, 'errors'); } - print ''; + print ''; } print ''; - if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER) && $action == 'view') { - $out .= ''; + if ($display_type=='card') { + $out .= ''; + $out .= ''; + + $out .= ($display_type=='card' ? '' : ''); $html_id = !empty($this->id) ? $this->element.'_extras_'.$key.'_'.$this->id : ''; - - $out .= ''; + $out .= ($display_type=='card' ? '' : ''); /*for($ii = 0; $ii < ($colspan - 1); $ii++) { $out .=''; }*/ - if (!empty($conf->global->MAIN_EXTRAFIELDS_USE_TWO_COLUMS) && (($e % 2) == 1)) $out .= ''; - else $out .= ''; + if (!empty($conf->global->MAIN_EXTRAFIELDS_USE_TWO_COLUMS) && (($e % 2) == 1)) { + $out .= ($display_type=='card' ? '' : ''); + } else { + $out .= ($display_type=='card' ? '' : ''); + } $e++; } } diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index cf499bbde5d..21db0656c0e 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -924,15 +924,15 @@ class ExtraFields * Return HTML string to put an input field into a page * Code very similar with showInputField of common object * - * @param string $key Key of attribute - * @param string $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value) - * @param string $moreparam To add more parametes on html input tag - * @param string $keysuffix Prefix string to add after name and id of field (can be used to avoid duplicate names) - * @param string $keyprefix Suffix string to add before name and id of field (can be used to avoid duplicate names) - * @param string $morecss More css (to defined size of field. Old behaviour: may also be a numeric) - * @param int $objectid Current object id - * @param string $extrafieldsobjectkey If defined (for example $object->table_element), use the new method to get extrafields data - * @param string $mode 1=Used for search filters + * @param string $key Key of attribute + * @param string|array $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value); for dates in filter mode, a range array('start'=>, 'end'=>) should be provided + * @param string $moreparam To add more parameters on html input tag + * @param string $keysuffix Prefix string to add after name and id of field (can be used to avoid duplicate names) + * @param string $keyprefix Suffix string to add before name and id of field (can be used to avoid duplicate names) + * @param string $morecss More css (to defined size of field. Old behaviour: may also be a numeric) + * @param int $objectid Current object id + * @param string $extrafieldsobjectkey If defined (for example $object->table_element), use the new method to get extrafields data + * @param string $mode 1=Used for search filters * @return string */ public function showInputField($key, $value, $moreparam = '', $keysuffix = '', $keyprefix = '', $morecss = '', $objectid = 0, $extrafieldsobjectkey = '', $mode = 0) @@ -1024,8 +1024,22 @@ class ExtraFields // Do not show current date when field not required (see selectDate() method) if (!$required && $value == '') $value = '-1'; - // TODO Must also support $moreparam - $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1); + if ($mode == 1) { + // search filter on a date extrafield shows two inputs to select a date range + $prefill = array( + 'start' => isset($value['start']) ? $value['start'] : '', + 'end' => isset($value['end']) ? $value['end'] : ''); + $out = '
' + . $langs->trans('From') . ' ' + . $form->selectDate($prefill['start'], $keyprefix . $key . $keysuffix . '_start', 0, 0, 1) + . '
' + . $langs->trans('to') . ' ' + . $form->selectDate($prefill['end'], $keyprefix . $key . $keysuffix . '_end', 0, 0, 1) + . '
'; + } else { + // TODO Must also support $moreparam + $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1); + } } elseif (in_array($type, array('int', 'integer'))) { $tmp = explode(',', $size); @@ -1907,15 +1921,29 @@ class ExtraFields * @param string $key Key of attribute * @param string $object Object * @param int $colspan Value of colspan to use (it must includes the first column with title) + * @param string $display_type "card" for form display, "line" for document line display (extrafields on propal line, order line, etc...) * @return string HTML code with line for separator */ - public function showSeparator($key, $object, $colspan = 2) + public function showSeparator($key, $object, $colspan = 2, $display_type = 'card') { global $langs; - $out = '
'; + $out .= ''; + $out .= ''; + $out .= ''; $extrafield_param = $this->attributes[$object->table_element]['param'][$key]; if (!empty($extrafield_param) && is_array($extrafield_param)) { @@ -1925,27 +1953,27 @@ class ExtraFields $extrafield_collapse_display_value = intval($extrafield_param_list[0]); if ($extrafield_collapse_display_value == 1 || $extrafield_collapse_display_value == 2) { // Set the collapse_display status to cookie in priority or if ignorecollapsesetup is 1, if cookie and ignorecollapsesetup not defined, use the setup. - $collapse_display = ((isset($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key]) || GETPOST('ignorecollapsesetup', 'int')) ? ($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key] ? true : false) : ($extrafield_collapse_display_value == 2 ? false : true)); - $extrafields_collapse_num = $this->attributes[$object->table_element]['pos'][$key]; + $collapse_display = ((isset($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.(!empty($object->id)?'_'.$object->id:'')]) || GETPOST('ignorecollapsesetup', 'int')) ? ($_COOKIE['DOLCOLLAPSE_'.$object->table_element.'_extrafields_'.$key.(!empty($object->id)?'_'.$object->id:'')] ? true : false) : ($extrafield_collapse_display_value == 2 ? false : true)); + $extrafields_collapse_num = $this->attributes[$object->table_element]['pos'][$key].(!empty($object->id)?'_'.$object->id:''); $out .= ''; $out .= ''."\n"; print '
'; @@ -1356,7 +1392,13 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) // Email / Web print '
'; - print ''; + print 'browser->layout == 'phone') || empty($conf->mailing->enabled) ? ' colspan="3"' : '').'>'.img_picto('', 'object_email').' '; + if (!empty($conf->mailing->enabled) && !empty($conf->global->THIRDPARTY_SUGGEST_ALSO_ADDRESS_CREATION)) { + if ($conf->browser->layout == 'phone') print ''; + print ''; + print ''; + } + print ''; print ''; print ''; @@ -1512,6 +1554,22 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) print ""; //} + if (!empty($conf->global->THIRDPARTY_SUGGEST_ALSO_ADDRESS_CREATION)) + { + print '"; + } + + if (!empty($conf->global->THIRDPARTY_SUGGEST_ALSO_ADDRESS_CREATION)) + { + print '"; + } + // Supplier if (!empty($conf->fournisseur->enabled)) { print '
'; diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 10a2238088b..f689e7c3a4c 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -208,6 +208,8 @@ class Propal extends CommonObject public $demand_reason_id; public $demand_reason_code; + public $warehouse_id; + public $extraparams = array(); /** @@ -231,8 +233,6 @@ class Propal extends CommonObject public $multicurrency_total_tva; public $multicurrency_total_ttc; - public $oldcopy; - /** * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') @@ -298,6 +298,7 @@ class Propal extends CommonObject 'model_pdf' =>array('type'=>'varchar(255)', 'label'=>'PDFTemplate', 'enabled'=>1, 'visible'=>0, 'position'=>180), 'date_livraison' =>array('type'=>'date', 'label'=>'DateDeliveryPlanned', 'enabled'=>1, 'visible'=>-1, 'position'=>185), 'fk_shipping_method' =>array('type'=>'integer', 'label'=>'ShippingMethod', 'enabled'=>1, 'visible'=>-1, 'position'=>190), + 'fk_warehouse' =>array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php', 'label'=>'Fk warehouse', 'enabled'=>1, 'visible'=>-1, 'position'=>191), 'fk_availability' =>array('type'=>'integer', 'label'=>'Availability', 'enabled'=>1, 'visible'=>-1, 'position'=>195), 'fk_delivery_address' =>array('type'=>'integer', 'label'=>'DeliveryAddress', 'enabled'=>1, 'visible'=>0, 'position'=>200), // deprecated 'fk_input_reason' =>array('type'=>'integer', 'label'=>'InputReason', 'enabled'=>1, 'visible'=>-1, 'position'=>205), @@ -1051,6 +1052,7 @@ class Propal extends CommonObject $sql .= ", ref_client"; $sql .= ", date_livraison"; $sql .= ", fk_shipping_method"; + $sql .= ", fk_warehouse"; $sql .= ", fk_availability"; $sql .= ", fk_input_reason"; $sql .= ", fk_projet"; @@ -1083,6 +1085,7 @@ class Propal extends CommonObject $sql .= ", '".$this->db->escape($this->ref_client)."'"; $sql .= ", ".(empty($delivery_date) ? "NULL" : "'".$this->db->idate($delivery_date)."'"); $sql .= ", ".($this->shipping_method_id > 0 ? $this->shipping_method_id : 'NULL'); + $sql .= ", ".($this->warehouse_id > 0 ? $this->warehouse_id : 'NULL'); $sql .= ", ".$this->availability_id; $sql .= ", ".$this->demand_reason_id; $sql .= ", ".($this->fk_project ? $this->fk_project : "null"); @@ -1437,6 +1440,7 @@ class Propal extends CommonObject $sql .= ", p.fk_mode_reglement"; $sql .= ', p.fk_account'; $sql .= ", p.fk_shipping_method"; + $sql .= ", p.fk_warehouse"; $sql .= ", p.fk_incoterms, p.location_incoterms"; $sql .= ", p.fk_multicurrency, p.multicurrency_code, p.multicurrency_tx, p.multicurrency_total_ht, p.multicurrency_total_tva, p.multicurrency_total_ttc"; $sql .= ", p.tms as date_modification"; @@ -1510,6 +1514,7 @@ class Propal extends CommonObject $this->date_livraison = $this->db->jdate($obj->delivery_date); // deprecated $this->delivery_date = $this->db->jdate($obj->delivery_date); $this->shipping_method_id = ($obj->fk_shipping_method > 0) ? $obj->fk_shipping_method : null; + $this->warehouse_id = ($obj->fk_warehouse > 0) ? $obj->fk_warehouse : null; $this->availability_id = $obj->fk_availability; $this->availability_code = $obj->availability_code; $this->availability = $obj->availability; diff --git a/htdocs/comm/propal/list.php b/htdocs/comm/propal/list.php index 998e1e9e23e..1e3f4080678 100644 --- a/htdocs/comm/propal/list.php +++ b/htdocs/comm/propal/list.php @@ -67,6 +67,7 @@ $search_refproject = GETPOST('search_refproject', 'alpha'); $search_project = GETPOST('search_project', 'alpha'); $search_societe = GETPOST('search_societe', 'alpha'); +$search_societe_alias = GETPOST('search_societe_alias', 'alpha'); $search_montant_ht = GETPOST('search_montant_ht', 'alpha'); $search_montant_vat = GETPOST('search_montant_vat', 'alpha'); $search_montant_ttc = GETPOST('search_montant_ttc', 'alpha'); @@ -161,6 +162,7 @@ $arrayfields = array( 'pr.ref'=>array('label'=>"ProjectRef", 'checked'=>1, 'enabled'=>(empty($conf->projet->enabled) ? 0 : 1)), 'pr.title'=>array('label'=>"ProjectLabel", 'checked'=>0, 'enabled'=>(empty($conf->projet->enabled) ? 0 : 1)), 's.nom'=>array('label'=>"ThirdParty", 'checked'=>1), + 's.name_alias'=>array('label'=>"AliasNameShort", 'checked'=>1), 's.town'=>array('label'=>"Town", 'checked'=>1), 's.zip'=>array('label'=>"Zip", 'checked'=>1), 'state.nom'=>array('label'=>"StateShort", 'checked'=>0), @@ -223,6 +225,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_refproject = ''; $search_project = ''; $search_societe = ''; + $search_societe_alias = ''; $search_montant_ht = ''; $search_montant_vat = ''; $search_montant_ttc = ''; @@ -289,7 +292,7 @@ $help_url = 'EN:Commercial_Proposals|FR:Proposition_commerciale|ES:Presupuestos' $sql = 'SELECT'; if ($sall || $search_product_category > 0) $sql = 'SELECT DISTINCT'; -$sql .= ' s.rowid as socid, s.nom as name, s.email, s.town, s.zip, s.fk_pays, s.client, s.code_client, '; +$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.code_client, '; $sql .= " typent.code as typent_code,"; $sql .= " ava.rowid as availability,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; @@ -349,6 +352,7 @@ if ($search_project) $sql .= natural_search('pr.title', $search_project); if ($search_availability) $sql .= " AND p.fk_availability IN (".$db->sanitize($db->escape($search_availability)).')'; if ($search_societe) $sql .= natural_search('s.nom', $search_societe); +if ($search_societe_alias) $sql .= natural_search('s.name_alias', $search_societe_alias); if ($search_login) $sql .= natural_search("u.login", $search_login); if ($search_montant_ht != '') $sql .= natural_search("p.total_ht", $search_montant_ht, 1); if ($search_montant_vat != '') $sql .= natural_search("p.tva", $search_montant_vat, 1); @@ -459,6 +463,7 @@ if ($resql) if ($search_refcustomer) $param .= '&search_refcustomer='.urlencode($search_refcustomer); if ($search_refproject) $param .= '&search_refproject='.urlencode($search_refproject); if ($search_societe) $param .= '&search_societe='.urlencode($search_societe); + if ($search_societe_alias) $param .= '&search_societe_alias='.urlencode($search_societe_alias); if ($search_user > 0) $param .= '&search_user='.urlencode($search_user); if ($search_sale > 0) $param .= '&search_sale='.urlencode($search_sale); if ($search_montant_ht) $param .= '&search_montant_ht='.urlencode($search_montant_ht); @@ -621,6 +626,12 @@ if ($resql) print ''; print ''; + print ''; + print ''; + print $obj->alias; + print '
".$langs->trans("DefaultContact").''; + print img_picto('', 'contact'); $form->select_contacts($soc->id, $contactid, 'contactid', 1, $srccontactslist, '', 1); print '
'.$langs->trans('Date').''; - print $form->selectDate('', 're', '', '', '', "crea_commande", 1, 1); // Always autofill date with current date + print img_picto('', 'object_calendarday').' '.$form->selectDate('', 're', '', '', '', "crea_commande", 1, 1); // Always autofill date with current date print '
'.$langs->trans("DateDeliveryPlanned").''; $date_delivery = ($date_delivery ? $date_delivery : $object->date_delivery); - print $form->selectDate($date_delivery ? $date_delivery : -1, 'date_delivery', 1, 1, 1); + print img_picto('', 'object_calendarday').' '.$form->selectDate($date_delivery ? $date_delivery : -1, 'date_delivery', 1, 1, 1); print "
'.$langs->trans('PaymentMode').''; + print img_picto('', 'bank').' '; $form->select_types_paiements($mode_reglement_id, 'mode_reglement_id'); print '
'.$langs->trans('BankAccount').''; + print img_picto('', 'bank_account'); $form->select_comptes($fk_account, 'fk_account', 0, '', 1); print '
'.$langs->trans('AvailabilityPeriod').''; + print img_picto('', 'clock').' '; $form->selectAvailabilityDelay($availability_id, 'availability_id', '', 1); print '
'.$langs->trans('SendingMethod').''; + print img_picto('', 'object_dollyrevert').' '; print $form->selectShippingMethod($shipping_method_id, 'shipping_method_id', '', 1); print '
'.$langs->trans('Warehouse').''; @@ -1721,6 +1728,7 @@ if ($action == 'create' && $usercancreate) // Template to use by default print '
'.$langs->trans('DefaultModel').''; + print img_picto('', 'pdf').' '; include_once DOL_DOCUMENT_ROOT.'/core/modules/commande/modules_commande.php'; $liste = ModelePDFCommandes::liste_modeles($db); print $form->selectarray('model', $liste, $conf->global->COMMANDE_ADDON_PDF); @@ -2165,7 +2173,7 @@ if ($action == 'create' && $usercancreate) } // Warehouse - if (!empty($conf->expedition->enabled) && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) { + if (!empty($conf->stock->enabled) && !empty($conf->global->WAREHOUSE_ASK_WAREHOUSE_DURING_ORDER)) { $langs->load('stocks'); require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; $formproduct = new FormProduct($db); diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index 3cc0fa72ae6..248a45c629a 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -200,6 +200,8 @@ class Commande extends CommonOrder public $special_code; public $source; // Order mode. How we received order (by phone, by email, ...) + public $warehouse_id; + public $extraparams = array(); public $linked_objects = array(); @@ -231,11 +233,6 @@ class Commande extends CommonOrder public $multicurrency_total_tva; public $multicurrency_total_ttc; - /** - * @var Commande clone of order object - */ - public $oldcopy; - //! key of module source when order generated from a dedicated module ('cashdesk', 'takepos', ...) public $module_source; //! key of pos source ('0', '1', ...) diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index a3790528c8d..1531dfd622e 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -67,6 +67,7 @@ $search_product_category = GETPOST('search_product_category', 'int'); $search_ref = GETPOST('search_ref', 'alpha') != '' ?GETPOST('search_ref', 'alpha') : GETPOST('sref', 'alpha'); $search_ref_customer = GETPOST('search_ref_customer', 'alpha'); $search_company = GETPOST('search_company', 'alpha'); +$search_company_alias = GETPOST('search_company_alias', 'alpha'); $search_town = GETPOST('search_town', 'alpha'); $search_zip = GETPOST('search_zip', 'alpha'); $search_state = GETPOST("search_state", 'alpha'); @@ -149,6 +150,7 @@ $arrayfields = array( 'p.ref'=>array('label'=>"ProjectRef", 'checked'=>1, 'enabled'=>(empty($conf->projet->enabled) ? 0 : 1), 'position'=>20), 'p.title'=>array('label'=>"ProjectLabel", 'checked'=>0, 'enabled'=>(empty($conf->projet->enabled) ? 0 : 1), 'position'=>25), 's.nom'=>array('label'=>"ThirdParty", 'checked'=>1, 'position'=>30), + 's.name_alias'=>array('label'=>"AliasNameShort", 'checked'=>1, 'position'=>31), 's.town'=>array('label'=>"Town", 'checked'=>1, 'position'=>35), 's.zip'=>array('label'=>"Zip", 'checked'=>1, 'position'=>40), 'state.nom'=>array('label'=>"StateShort", 'checked'=>0, 'position'=>45), @@ -211,6 +213,7 @@ if (empty($reshook)) $search_ref = ''; $search_ref_customer = ''; $search_company = ''; + $search_company_alias = ''; $search_town = ''; $search_zip = ""; $search_state = ""; @@ -280,7 +283,7 @@ $help_url = "EN:Module_Customers_Orders|FR:Module_Commandes_Clients|ES:Módulo_P $sql = 'SELECT'; if ($sall || $search_product_category > 0) $sql = 'SELECT DISTINCT'; -$sql .= ' s.rowid as socid, s.nom as name, s.email, s.town, s.zip, s.fk_pays, s.client, s.code_client,'; +$sql .= ' s.rowid as socid, s.nom as name, s.name_alias as name_alias, s.email, s.town, s.zip, s.fk_pays, s.client, s.code_client,'; $sql .= " typent.code as typent_code,"; $sql .= " state.code_departement as state_code, state.nom as state_name,"; $sql .= ' c.rowid, c.ref, c.total_ht, c.tva as total_tva, c.total_ttc, c.ref_client, c.fk_user_author,'; @@ -362,6 +365,7 @@ if ($search_state) $sql .= natural_search("state.nom", if ($search_country) $sql .= " AND s.fk_pays IN (".$search_country.')'; if ($search_type_thirdparty) $sql .= " AND s.fk_typent IN (".$search_type_thirdparty.')'; if ($search_company) $sql .= natural_search('s.nom', $search_company); +if ($search_company_alias) $sql .= natural_search('s.name_alias', $search_company_alias); if ($search_sale > 0) $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".$search_sale; if ($search_user > 0) $sql .= " AND ec.fk_c_type_contact = tc.rowid AND tc.element='commande' AND tc.source='internal' AND ec.element_id = c.rowid AND ec.fk_socpeople = ".$search_user; if ($search_total_ht != '') $sql .= natural_search('c.total_ht', $search_total_ht, 1); @@ -466,6 +470,7 @@ if ($resql) if ($search_datedelivery_end) $param .= '&search_datedelivery_end_day='.dol_print_date($search_datedelivery_end, '%d').'&search_datedelivery_end_month='.dol_print_date($search_datedelivery_end, '%m').'&search_datedelivery_end_year='.dol_print_date($search_datedelivery_end, '%Y'); if ($search_ref) $param .= '&search_ref='.urlencode($search_ref); if ($search_company) $param .= '&search_company='.urlencode($search_company); + if ($search_company_alias) $param .= '&search_company_alias='.urlencode($search_company_alias); if ($search_ref_customer) $param .= '&search_ref_customer='.urlencode($search_ref_customer); if ($search_user > 0) $param .= '&search_user='.urlencode($search_user); if ($search_sale > 0) $param .= '&search_sale='.urlencode($search_sale); @@ -693,6 +698,13 @@ if ($resql) print ''; print ''; + print ''; + print ''; + print $obj->alias; + print ''; diff --git a/htdocs/compta/bank/various_payment/card.php b/htdocs/compta/bank/various_payment/card.php index 0efe367089c..0c2db362e75 100644 --- a/htdocs/compta/bank/various_payment/card.php +++ b/htdocs/compta/bank/various_payment/card.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2017-2021 Alexandre Spangaro * Copyright (C) 2018-2020 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -266,6 +266,18 @@ if ($action == 'confirm_clone' && $confirm == 'yes' && ($user->rights->banque->m $object->datev = $newdatepayment; } + if (GETPOSTISSET("clone_sens")) { + $object->sens = GETPOST("clone_sens", 'int'); + } else { + $object->sens = $object->sens; + } + + if (GETPOST("clone_amount", "alpha")) { + $object->amount = price2num(GETPOST("clone_amount", "alpha")); + } else { + $object->amount = price2num($object->amount); + } + if ($object->check()) { $id = $object->create($user); @@ -486,14 +498,19 @@ if ($id) // Clone confirmation if ($action === 'clone') { + $set_value_help = $form->textwithpicto('', $langs->trans($langs->trans("AccountingDirectionHelp"))); + $sensarray = array('0' => $langs->trans("Debit"), '1' => $langs->trans("Credit")); + $formquestion = array( array('type' => 'text', 'name' => 'clone_label', 'label' => $langs->trans("Label"), 'value' => $langs->trans("CopyOf").' '.$object->label), - ); - $formquestion[] = array('type' => 'date', 'tdclass'=>'fieldrequired', 'name' => 'clone_date_payment', 'label' => $langs->trans("DatePayment"), 'value' => -1); - $formquestion[] = array('type' => 'date', 'name' => 'clone_date_value', 'label' => $langs->trans("DateValue"), 'value' => -1); - $formquestion[] = array('type' => 'other', 'tdclass'=>'fieldrequired', 'name' => 'accountid', 'label' => $langs->trans("BankAccount"), 'value' => $form->select_comptes($accountid, "accountid", 0, '', 1, '', 0, 'minwidth200', 1)); + array('type' => 'date', 'tdclass'=>'fieldrequired', 'name' => 'clone_date_payment', 'label' => $langs->trans("DatePayment"), 'value' => -1), + array('type' => 'date', 'name' => 'clone_date_value', 'label' => $langs->trans("DateValue"), 'value' => -1), + array('type' => 'other', 'tdclass'=>'fieldrequired', 'name' => 'clone_accountid', 'label' => $langs->trans("BankAccount"), 'value' => $form->select_comptes($object->fk_account, "accountid", 0, '', 1, '', 0, 'minwidth200', 1)), + array('type' => 'text', 'name' => 'clone_amount', 'label' => $langs->trans("Amount"), 'value' => price($object->amount)), + array('type' => 'select', 'name' => 'clone_sens', 'label' => $langs->trans("Sens") . ' ' . $set_value_help, 'values' => $sensarray, 'default' => $object->sens), + ); - print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneVariousPayment', $object->ref), 'confirm_clone', $formquestion, 'yes', 1, 300); + print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneVariousPayment', $object->ref), 'confirm_clone', $formquestion, 'yes', 1, 350); } print dol_get_fiche_head($head, 'card', $langs->trans("VariousPayment"), -1, $object->picto); diff --git a/htdocs/compta/facture/card-rec.php b/htdocs/compta/facture/card-rec.php index 25505325c98..35d70e1edd6 100644 --- a/htdocs/compta/facture/card-rec.php +++ b/htdocs/compta/facture/card-rec.php @@ -439,7 +439,7 @@ if (empty($reshook)) $predef = ''; $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : ''); $price_ht = price2num(GETPOST('price_ht'), 'MU'); - $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CR'); + $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU'); $prod_entry_mode = GETPOST('prod_entry_mode', 'alpha'); if ($prod_entry_mode == 'free') { @@ -450,7 +450,7 @@ if (empty($reshook)) $tva_tx = ''; } - $qty = price2num(GETPOST('qty'.$predef), 'alpha'); + $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS'); $remise_percent = GETPOST('remise_percent'.$predef); // Extrafields diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 6d8054a0362..7250d673494 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -977,11 +977,14 @@ if (empty($reshook)) if ($_POST['type'] == Facture::TYPE_REPLACEMENT) { $dateinvoice = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); - if (empty($dateinvoice)) - { + if (empty($dateinvoice)) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors'); $action = 'create'; + } elseif ($dateinvoice > (dol_now() + (empty($conf->global->INVOICE_MAX_FUTURE_DELAY) ? 0 : $conf->global->INVOICE_MAX_FUTURE_DELAY))) { + $error++; + setEventMessages($langs->trans("ErrorDateIsInFuture"), null, 'errors'); + $action = 'create'; } if (!($_POST['fac_replacement'] > 0)) { @@ -1029,7 +1032,7 @@ if (empty($reshook)) // Credit note invoice if (GETPOST('type') == Facture::TYPE_CREDIT_NOTE) { - $sourceinvoice = GETPOST('fac_avoir'); + $sourceinvoice = GETPOST('fac_avoir', 'int'); if (!($sourceinvoice > 0) && empty($conf->global->INVOICE_CREDIT_NOTE_STANDALONE)) { $error++; @@ -1038,11 +1041,14 @@ if (empty($reshook)) } $dateinvoice = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); - if (empty($dateinvoice)) - { + if (empty($dateinvoice)) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors'); $action = 'create'; + } elseif ($dateinvoice > (dol_now() + (empty($conf->global->INVOICE_MAX_FUTURE_DELAY) ? 0 : $conf->global->INVOICE_MAX_FUTURE_DELAY))) { + $error++; + setEventMessages($langs->trans("ErrorDateIsInFuture"), null, 'errors'); + $action = 'create'; } $date_pointoftax = dol_mktime(12, 0, 0, GETPOST('date_pointoftaxmonth', 'int'), GETPOST('date_pointoftaxday', 'int'), GETPOST('date_pointoftaxyear', 'int')); @@ -1255,11 +1261,14 @@ if (empty($reshook)) if (($_POST['type'] == Facture::TYPE_STANDARD || $_POST['type'] == Facture::TYPE_DEPOSIT) && GETPOST('fac_rec', 'int') > 0) { $dateinvoice = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); - if (empty($dateinvoice)) - { + if (empty($dateinvoice)) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors'); $action = 'create'; + } elseif ($dateinvoice > (dol_now() + (empty($conf->global->INVOICE_MAX_FUTURE_DELAY) ? 0 : $conf->global->INVOICE_MAX_FUTURE_DELAY))) { + $error++; + setEventMessages($langs->trans("ErrorDateIsInFuture"), null, 'errors'); + $action = 'create'; } $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']); @@ -1305,11 +1314,14 @@ if (empty($reshook)) } $dateinvoice = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); - if (empty($dateinvoice)) - { + if (empty($dateinvoice)) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors'); $action = 'create'; + } elseif ($dateinvoice > (dol_now() + (empty($conf->global->INVOICE_MAX_FUTURE_DELAY) ? 0 : $conf->global->INVOICE_MAX_FUTURE_DELAY))) { + $error++; + setEventMessages($langs->trans("ErrorDateIsInFuture"), null, 'errors'); + $action = 'create'; } $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']); @@ -1725,11 +1737,15 @@ if (empty($reshook)) // Situation invoices if (GETPOST('type') == Facture::TYPE_SITUATION && (!empty($_POST['situations']))) { - $datefacture = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); - if (empty($datefacture)) { + $dateinvoice = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); + if (empty($dateinvoice)) { $error++; $mesg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")); setEventMessages($mesg, null, 'errors'); + } elseif ($dateinvoice > (dol_now() + (empty($conf->global->INVOICE_MAX_FUTURE_DELAY) ? 0 : $conf->global->INVOICE_MAX_FUTURE_DELAY))) { + $error++; + setEventMessages($langs->trans("ErrorDateIsInFuture"), null, 'errors'); + $action = 'create'; } $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']); @@ -1811,7 +1827,7 @@ if (empty($reshook)) } $object->fetch_thirdparty(); - $object->date = $datefacture; + $object->date = $dateinvoice; $object->date_pointoftax = $date_pointoftax; $object->note_public = trim(GETPOST('note_public', 'restricthtml')); $object->note = trim(GETPOST('note', 'restricthtml')); @@ -3347,11 +3363,11 @@ if ($action == 'create') print '
'.$langs->trans('DateInvoice').''; - print $form->selectDate($datefacture ? $datefacture : $dateinvoice, '', '', '', '', "add", 1, 1); + print $form->selectDate($newdateinvoice ? $newdateinvoice : $dateinvoice, '', '', '', '', "add", 1, 1); print '
'; + print $obj->name_alias; + print '
'.$form->selectyesno('no_email', (GETPOSTISSET("no_email") ? GETPOST("no_email", 'alpha') : $noemail), 1).''.$form->selectyesno('no_email', (GETPOSTISSET("no_email") ? GETPOST("no_email", 'int') : $conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS), 1, false, ($conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS==-1)).'
jabberid).'">
skype).'">
twitter).'">
facebook).'">
linkedin).'">
'; @@ -1050,28 +1039,40 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) print '
'.$form->selectyesno('no_email', (GETPOSTISSET("no_email") ?GETPOST("no_email", 'alpha') : $noemail), 1).'
'.$form->selectyesno('no_email', (GETPOSTISSET("no_email") ? GETPOST("no_email", 'int') : $object->no_email), 1, false, ($conf->global->MAILING_CONTACT_DEFAULT_BULK_STATUS==-1)).'
'.$langs->trans("No_Email").''.yn($noemail).'
'.$langs->trans("No_Email").''.yn($object->no_email).'
'.$langs->trans("ContactVisibility").''; diff --git a/htdocs/contact/class/contact.class.php b/htdocs/contact/class/contact.class.php index 8fe4943d267..0283a01074d 100644 --- a/htdocs/contact/class/contact.class.php +++ b/htdocs/contact/class/contact.class.php @@ -1180,6 +1180,20 @@ class Contact extends CommonObject } } + if (!$error) + { + // Remove Roles + $sql = "DELETE FROM ".MAIN_DB_PREFIX."societe_contacts WHERE fk_socpeople = ".$this->id; + dol_syslog(__METHOD__, LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) + { + $error++; + $this->error .= $this->db->lasterror(); + $errorflag = -1; + } + } + if (!$error) { // Remove category @@ -1880,4 +1894,94 @@ class Contact extends CommonObject return "Error, mode/status not found"; } + + + /** + * Set "blacklist" mailing status + * + * @param int $no_email 1=Do not send mailing, 0=Ok to recieve mailling + * @return int <0 if KO, >0 if OK + */ + public function setNoEmail($no_email) + { + $error = 0; + + // Update mass emailing flag into table mailing_unsubscribe + if ($this->email) + { + $this->db->begin(); + + if ($no_email) + { + $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE entity IN (".getEntity('mailing', 0).") AND email = '".$this->db->escape($this->email)."'"; + $resql = $this->db->query($sql); + if ($resql) + { + $obj = $this->db->fetch_object($resql); + $noemail = $obj->nb; + if (empty($noemail)) + { + $sql = "INSERT INTO ".MAIN_DB_PREFIX."mailing_unsubscribe(email, entity, date_creat) VALUES ('".$this->db->escape($this->email)."', ".$this->db->escape(getEntity('mailing', 0)).", '".$this->db->idate(dol_now())."')"; + $resql = $this->db->query($sql); + if (!$resql) + { + $error++; + $this->error = $this->db->lasterror(); + $this->errors[] = $this->error; + } + } + } else { + $error++; + $this->error = $this->db->lasterror(); + $this->errors[] = $this->error; + } + } else { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE email = '".$this->db->escape($this->email)."' AND entity = ".$this->db->escape(getEntity('mailing', 0)); + $resql = $this->db->query($sql); + if (!$resql) + { + $error++; + $this->error = $this->db->lasterror(); + $this->errors[] = $this->error; + } + } + + if (empty($error)) { + $this->no_email = $no_email; + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return $error * -1; + } + } + + return 0; + } + + /** + * get "blacklist" mailing status + * set no_email attribut to 1 or 0 + * + * @return int <0 if KO, >0 if OK + */ + public function getNoEmail() + { + if ($this->email) + { + $sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE entity IN (".getEntity('mailing').") AND email = '".$this->db->escape($this->email)."'"; + $resql = $this->db->query($sql); + if ($resql) + { + $obj = $this->db->fetch_object($resql); + $this->no_email = $obj->nb; + return 1; + } else { + $this->error = $this->db->lasterror(); + $this->errors[] = $this->error; + return -1; + } + } + return 0; + } } diff --git a/htdocs/contrat/card.php b/htdocs/contrat/card.php index 4ee7c2d631c..ca03905b834 100644 --- a/htdocs/contrat/card.php +++ b/htdocs/contrat/card.php @@ -385,7 +385,7 @@ if (empty($reshook)) $predef = ''; $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : ''); $price_ht = price2num(GETPOST('price_ht'), 'MU'); - $price_ht_devise = price2num(GETPOST('multicurrency_price_ht', 'CR')); + $price_ht_devise = price2num(GETPOST('multicurrency_price_ht', 'CU')); if (GETPOST('prod_entry_mode', 'alpha') == 'free') { $idprod = 0; @@ -395,7 +395,7 @@ if (empty($reshook)) $tva_tx = ''; } - $qty = price2num(GETPOST('qty'.$predef), 'alpha'); + $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS'); $remise_percent = ((GETPOST('remise_percent'.$predef) != '') ? GETPOST('remise_percent'.$predef) : 0); if ($qty == '') diff --git a/htdocs/core/actions_sendmails.inc.php b/htdocs/core/actions_sendmails.inc.php index 929d35d9730..1bea255bda2 100644 --- a/htdocs/core/actions_sendmails.inc.php +++ b/htdocs/core/actions_sendmails.inc.php @@ -227,7 +227,7 @@ if (($action == 'send' || $action == 'relance') && !$_POST['addfile'] && !$_POST } if (count($receivercc) > 0) { foreach ($receivercc as $key => $val) { - if ($val == 'thirdparty') { // Key selected means currentthird party (may be usd for current member or current user too) + if ($val == 'thirdparty') { // Key selected means current thirdparty (may be usd for current member or current user too) // Recipient was provided from combo list $tmparray[] = dol_string_nospecial($thirdparty->name, ' ', array(",")).' <'.$thirdparty->email.'>'; } elseif ($val == 'contact') { // Key selected means current contact @@ -399,7 +399,6 @@ if (($action == 'send' || $action == 'relance') && !$_POST['addfile'] && !$_POST $error++; } // End call triggers - if ($error) { setEventMessages($object->error, $object->errors, 'errors'); } diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index c8994d32a1d..d701da55d8f 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -14,6 +14,7 @@ * Copyright (C) 2017 Rui Strecht * Copyright (C) 2018-2020 Frédéric France * Copyright (C) 2018 Josep Lluís Amador + * Copyright (C) 2021 Gauthier VERDOL * * 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 @@ -3660,6 +3661,56 @@ abstract class CommonObject } } + /** + * Function used to get an array with all items linked to an object id in association table + * @param int $fk_object_where id of object we need to get linked items + * @param string $field_select name of field we need to get a list + * @param string $field_where name of field of object we need to get linked items + * @param string $table_element name of association table + * @return array + */ + static public function getAllItemsLinkedByObjectID($fk_object_where, $field_select, $field_where, $table_element) + { + if(empty($fk_object_where) || empty($field_where) || empty($table_element)) return -1; + + global $db; + + $sql = 'SELECT '.$field_select.' FROM '.MAIN_DB_PREFIX.$table_element.' WHERE '.$field_where.' = '.$fk_object_where; + $resql = $db->query($sql); + + $TRes = array(); + if (!empty($resql)) { + while ($res = $db->fetch_object($resql)) { + $TRes[] = $res->{$field_select}; + } + } + + return $TRes; + + } + + /** + * Function used to remove all items linked to an object id in association table + * @param int $fk_object_where id of object we need to remove linked items + * @param string $field_where name of field of object we need to delete linked items + * @param string $table_element name of association table + * @return int + */ + static public function deleteAllItemsLinkedByObjectID($fk_object_where, $field_where, $table_element) + { + if(empty($fk_object_where) || empty($field_where) || empty($table_element)) return -1; + + global $db; + + $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$table_element.' WHERE '.$field_where.' = '.$fk_object_where; + $resql = $db->query($sql); + + if (empty($resql)) return 0; + + return 1; + + } + /** * Set status of an object * @@ -6819,9 +6870,10 @@ abstract class CommonObject * @param string $keysuffix Suffix string to add after name and id of field (can be used to avoid duplicate names) * @param string $keyprefix Prefix string to add before name and id of field (can be used to avoid duplicate names) * @param string $onetrtd All fields in same tr td. Used by objectline_create.tpl.php for example. + * @param string $display_type "card" for form display, "line" for document line display (extrafields on propal line, order line, etc...) * @return string */ - public function showOptionals($extrafields, $mode = 'view', $params = null, $keysuffix = '', $keyprefix = '', $onetrtd = 0) + public function showOptionals($extrafields, $mode = 'view', $params = null, $keysuffix = '', $keyprefix = '', $onetrtd = 0, $display_type = 'card') { global $db, $conf, $langs, $action, $form, $hookmanager; @@ -6876,7 +6928,7 @@ abstract class CommonObject } $colspan = ''; - if (is_array($params) && count($params) > 0) { + if (is_array($params) && count($params) > 0 && $display_type=='card') { if (array_key_exists('cols', $params)) { $colspan = $params['cols']; } elseif (array_key_exists('colspan', $params)) { // For backward compatibility. Use cols instead now. @@ -6935,7 +6987,7 @@ abstract class CommonObject } } - $out .= $extrafields->showSeparator($key, $this, ($colspan + 1)); + $out .= $extrafields->showSeparator($key, $this, ($colspan + 1), $display_type); } else { $class = (!empty($extrafields->attributes[$this->table_element]['hidden'][$key]) ? 'hideobject ' : ''); $csstyle = ''; @@ -6954,10 +7006,11 @@ abstract class CommonObject $domData .= ' data-targetid="'.$this->id.'"'; $html_id = (empty($this->id) ? '' : 'extrarow-'.$this->element.'_'.$key.'_'.$this->id); + if ($display_type=='card') { + if (!empty($conf->global->MAIN_EXTRAFIELDS_USE_TWO_COLUMS) && ($e % 2) == 0) { $colspan = '0'; } - if (!empty($conf->global->MAIN_EXTRAFIELDS_USE_TWO_COLUMS) && ($e % 2) == 0) { $colspan = '0'; } - - if ($action == 'selectlines') { $colspan++; } + if ($action == 'selectlines') { $colspan++; } + } // Convert date into timestamp format (value in memory must be a timestamp) if (in_array($extrafields->attributes[$this->table_element]['type'][$key], array('date', 'datetime'))) @@ -6984,11 +7037,13 @@ abstract class CommonObject $labeltoshow = $langs->trans($label); $helptoshow = $langs->trans($extrafields->attributes[$this->table_element]['help'][$key]); - $out .= '
'; + $out .= '
attributes[$this->table_element]['help'][$key])) $out .= $form->textwithpicto($labeltoshow, $helptoshow); else $out .= $labeltoshow; } - $out .= '
'; + if ($display_type=='card') { + $out .= ''; + } elseif ($display_type=='line') { + $out .= '
'; + } switch ($mode) { case "view": @@ -7022,15 +7081,18 @@ abstract class CommonObject break; } - $out .= '
'; + if ($display_type=='card') { + $tagtype='tr'; + $tagtype_dyn='td'; + }elseif ($display_type=='line') { + $tagtype='div'; + $tagtype_dyn='span'; + $colspan=0; + } + + $out = '<'.$tagtype.' id="trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'" class="trextrafieldseparator trextrafieldseparator'.$key.(!empty($object->id)?'_'.$object->id:'').'">'; + $out .= '<'.$tagtype_dyn.' '.(!empty($colspan)?'colspan="' . $colspan . '"':'').'>'; + $out .=''; $out .= $langs->trans($this->attributes[$object->table_element]['label'][$key]); - $out .= '
'.$form->editfieldkey('EMail', 'email', '', $object, 0, 'string', '', empty($conf->global->SOCIETE_EMAIL_MANDATORY) ? '' : $conf->global->SOCIETE_EMAIL_MANDATORY).''.img_picto('', 'object_email').'
'.$form->editfieldkey($langs->trans('No_Email') .' ('.$langs->trans('Contact').')', 'contact_no_email', '', $object, 0).'browser->layout == 'phone') || empty($conf->mailing->enabled) ? ' colspan="3"' : '').'>'.$form->selectyesno('contact_no_email', (GETPOSTISSET("contact_no_email") ?GETPOST("contact_no_email", 'alpha') : $object->no_email), 1, false, 1).'
'.$form->editfieldkey('Web', 'url', '', $object, 0).''.img_picto('', 'globe').'
'.$form->editfieldkey('ContactCategoriesShort', 'contcats', '', $object, 0).''; + $cate_arbo = $form->select_all_categories(Categorie::TYPE_CONTACT, null, 'parent', null, null, 1); + print img_picto('', 'category').$form->multiselectarray('contcats', $cate_arbo, GETPOST('contcats', 'array'), null, null, 'quatrevingtpercent widthcentpercentminusx', 0, 0); + print "
'.$form->editfieldkey('ContactCategoriesShort', 'contcats', '', $object, 0).''; + $cate_arbo = $form->select_all_categories(Categorie::TYPE_CONTACT, null, 'parent', null, null, 1); + print img_picto('', 'category').$form->multiselectarray('contcats', $cate_arbo, GETPOST('contcats', 'array'), null, null, 'quatrevingtpercent widthcentpercentminusx', 0, 0); + print "
'.$form->editfieldkey('SuppliersCategoriesShort', 'suppcats', '', $object, 0).''; @@ -1555,6 +1613,39 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) print '
'."\n"; + // Accountancy codes + print ''; + + if (! empty($conf->accounting->enabled)) + { + // Accountancy_code_sell + print ''; + print ''; + + // Accountancy_code_buy + print ''; + print ''; + } + else // For external software + { + // Accountancy_code_sell + print ''; + print ''; + + // Accountancy_code_buy + print ''; + print ''; + } + print '
'.$langs->trans("ProductAccountancySellCode").''; + $accountancy_code_sell = GETPOST('accountancy_code_sell', 'alpha'); + print $formaccounting->select_account($accountancy_code_sell, 'accountancy_code_sell', 1, null, 1, 1, ''); + print '
'.$langs->trans("ProductAccountancyBuyCode").''; + $accountancy_code_buy = GETPOST('accountancy_code_buy', 'alpha'); + print $formaccounting->select_account($accountancy_code_buy, 'accountancy_code_buy', 1, null, 1, 1, ''); + print '
'.$langs->trans("ProductAccountancySellCode").''; + print '
'.$langs->trans("ProductAccountancyBuyCode").''; + print '
'; + print dol_get_fiche_end(); print '
'; @@ -1669,6 +1760,9 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) $object->webservices_url = GETPOST('webservices_url', 'custom', 0, FILTER_SANITIZE_URL); $object->webservices_key = GETPOST('webservices_key', 'san_alpha'); + $object->accountancy_code_sell = GETPOST('accountancy_code_sell', 'alpha'); + $object->accountancy_code_buy = GETPOST('accountancy_code_buy', 'alpha'); + //Incoterms if (!empty($conf->incoterm->enabled)) { @@ -2198,10 +2292,42 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) print img_picto('', 'user').$form->multiselectarray('commercial', $userlist, $arrayselected, 0, 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0, '', '', '', 1); print ''; + print ''; + + print '
'; + + print ''; + + if (! empty($conf->accounting->enabled)) + { + // Accountancy_code_sell + print ''; + print ''; + + // Accountancy_code_buy + print ''; + print ''; + } + else // For external software + { + // Accountancy_code_sell + print ''; + print ''; + + // Accountancy_code_buy + print ''; + print ''; + } print '
'.$langs->trans("ProductAccountancySellCode").''; + print $formaccounting->select_account($object->accountancy_code_sell, 'accountancy_code_sell', 1, '', 1, 1); + print '
'.$langs->trans("ProductAccountancyBuyCode").''; + print $formaccounting->select_account($object->accountancy_code_buy, 'accountancy_code_buy', 1, '', 1, 1); + print '
'.$langs->trans("ProductAccountancySellCode").''; + print '
'.$langs->trans("ProductAccountancyBuyCode").''; + print '
'; print '
'; - print dol_get_fiche_end(); + print dol_get_fiche_end(); print '
'; print ''; @@ -2579,6 +2705,42 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) print ''; } + // Accountancy sell code + print ''; + print $langs->trans("ProductAccountancySellCode"); + print ''; + if (! empty($conf->accounting->enabled)) + { + if (! empty($object->accountancy_code_sell)) + { + $accountingaccount = new AccountingAccount($db); + $accountingaccount->fetch('', $object->accountancy_code_sell, 1); + + print $accountingaccount->getNomUrl(0, 1, 1, '', 1); + } + } else { + print $object->accountancy_code_sell; + } + print ''; + + // Accountancy buy code + print ''; + print $langs->trans("ProductAccountancyBuyCode"); + print ''; + if (! empty($conf->accounting->enabled)) + { + if (! empty($object->accountancy_code_buy)) + { + $accountingaccount2 = new AccountingAccount($db); + $accountingaccount2->fetch('', $object->accountancy_code_buy, 1); + + print $accountingaccount2->getNomUrl(0, 1, 1, '', 1); + } + } else { + print $object->accountancy_code_buy; + } + print ''; + // Other attributes $parameters = array('socid'=>$socid, 'colspan' => ' colspan="3"', 'colspanvalue' => '3'); include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index d1513af17de..14e2cbe3277 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -693,6 +693,15 @@ class Societe extends CommonObject */ public $logo_squarred_mini; + /** + * @var string Accountancy account for sales + */ + public $accountancy_code_sell; + + /** + * @var string Accountancy account for bought + */ + public $accountancy_code_buy; // Multicurrency /** @@ -798,6 +807,9 @@ class Societe extends CommonObject } $this->import_key = trim($this->import_key); + $this->accountancy_code_buy = trim($this->accountancy_code_buy); + $this->accountancy_code_sell= trim($this->accountancy_code_sell); + if (!empty($this->multicurrency_code)) { $this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code); } @@ -827,8 +839,24 @@ class Societe extends CommonObject if ($result >= 0) { $this->entity = ((isset($this->entity) && is_numeric($this->entity)) ? $this->entity : $conf->entity); - $sql = "INSERT INTO ".MAIN_DB_PREFIX."societe (nom, name_alias, entity, datec, fk_user_creat, canvas, status, ref_ext, fk_stcomm, fk_incoterms, location_incoterms ,import_key, fk_multicurrency, multicurrency_code)"; - $sql .= " VALUES ('".$this->db->escape($this->name)."', '".$this->db->escape($this->name_alias)."', ".$this->db->escape($this->entity).", '".$this->db->idate($now)."'"; + $sql = "INSERT INTO ".MAIN_DB_PREFIX."societe ("; + $sql .= "nom"; + $sql .= ", name_alias"; + $sql .= ", entity"; + $sql .= ", datec"; + $sql .= ", fk_user_creat"; + $sql .= ", canvas"; + $sql .= ", status"; + $sql .= ", ref_ext"; + $sql .= ", fk_stcomm"; + $sql .= ", fk_incoterms"; + $sql .= ", location_incoterms"; + $sql .= ", import_key"; + $sql .= ", fk_multicurrency"; + $sql .= ", multicurrency_code"; + $sql .= ", accountancy_code_buy"; + $sql .= ", accountancy_code_sell"; + $sql .= ") VALUES ('".$this->db->escape($this->name)."', '".$this->db->escape($this->name_alias)."', ".$this->db->escape($this->entity).", '".$this->db->idate($now)."'"; $sql .= ", ".(!empty($user->id) ? ((int) $user->id) : "null"); $sql .= ", ".(!empty($this->canvas) ? "'".$this->db->escape($this->canvas)."'" : "null"); $sql .= ", ".$this->status; @@ -838,7 +866,10 @@ class Societe extends CommonObject $sql .= ", '".$this->db->escape($this->location_incoterms)."'"; $sql .= ", ".(!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null"); $sql .= ", ".(int) $this->fk_multicurrency; - $sql .= ", '".$this->db->escape($this->multicurrency_code)."')"; + $sql .= ", '".$this->db->escape($this->multicurrency_code)."'"; + $sql .= ", '".$this->db->escape($this->accountancy_code_buy)."'"; + $sql .= ", '".$this->db->escape($this->accountancy_code_sell)."'"; + $sql .= ")"; dol_syslog(get_class($this)."::create", LOG_DEBUG); $result = $this->db->query($sql); @@ -900,10 +931,18 @@ class Societe extends CommonObject * Create a contact/address from thirdparty * * @param User $user Object user + * @param int $no_email 1=Do not send mailing, 0=Ok to recieve mailling + * @param array $tags Array of tag to affect to contact * @return int <0 if KO, >0 if OK */ - public function create_individual(User $user) + public function create_individual(User $user, $no_email, $tags = array()) { + global $conf; + + $error = 0; + + $this->db->begin(); + // phpcs:enable require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; $contact = new Contact($this->db); @@ -923,14 +962,43 @@ class Societe extends CommonObject $contact->town = $this->town; $contact->phone_pro = $this->phone; - $result = $contact->create($user); - if ($result < 0) { + $contactId = $contact->create($user); + if ($contactId < 0) { + $error++; $this->error = $contact->error; $this->errors = $contact->errors; dol_syslog(get_class($this)."::create_individual ERROR:".$this->error, LOG_ERR); } - return $result; + if (empty($error) && is_array($tags) && !empty($tags)) { + $result = $contact->setCategories($tags); + if ($result < 0) { + $error++; + $this->error = $contact->error; + $this->errors = array_merge($this->errors, $contact->errors); + dol_syslog(get_class($this) . "::create_individual Affect Tag ERROR:" . $this->error, LOG_ERR); + $contactId = $result; + } + } + + if (empty($error) && !empty($conf->mailing->enabled) && !empty($contact->email) && isset($no_email)) { + $result = $contact->setNoEmail($no_email); + if ($result < 0) { + $this->error = $contact->error; + $this->errors = array_merge($this->errors, $contact->errors); + dol_syslog(get_class($this) . "::create_individual set mailing status ERROR:" . $this->error, LOG_ERR); + $contactId = $result; + } + } + + if (!empty($error)) { + dol_syslog(get_class($this)."::create_individual success"); + $this->db->commit(); + } else { + $this->db->rollback(); + } + + return $contactId; } /** @@ -1193,6 +1261,9 @@ class Societe extends CommonObject $this->webservices_url = $this->webservices_url ?clean_url($this->webservices_url, 0) : ''; $this->webservices_key = trim($this->webservices_key); + $this->accountancy_code_buy = trim($this->accountancy_code_buy); + $this->accountancy_code_sell= trim($this->accountancy_code_sell); + //Incoterms $this->fk_incoterms = (int) $this->fk_incoterms; $this->location_incoterms = trim($this->location_incoterms); @@ -1318,6 +1389,9 @@ class Societe extends CommonObject $sql .= ",supplier_order_min_amount= ".($this->supplier_order_min_amount != '' ? $this->supplier_order_min_amount : 'null'); $sql .= ",fk_prospectlevel='".$this->db->escape($this->fk_prospectlevel)."'"; + $sql.= ", accountancy_code_buy = '" . $this->db->escape($this->accountancy_code_buy)."'"; + $sql.= ", accountancy_code_sell= '" . $this->db->escape($this->accountancy_code_sell)."'"; + $sql .= ",webservices_url = ".(!empty($this->webservices_url) ? "'".$this->db->escape($this->webservices_url)."'" : "null"); $sql .= ",webservices_key = ".(!empty($this->webservices_key) ? "'".$this->db->escape($this->webservices_key)."'" : "null"); @@ -1489,6 +1563,7 @@ class Societe extends CommonObject $sql .= ', s.fk_effectif as effectif_id'; $sql .= ', s.fk_forme_juridique as forme_juridique_code'; $sql .= ', s.webservices_url, s.webservices_key'; + $sql .= ', s.accountancy_code_buy, s.accountancy_code_sell'; $sql .= ', s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur, s.parent, s.barcode'; $sql .= ', s.fk_departement as state_id, s.fk_pays as country_id, s.fk_stcomm, s.remise_supplier, s.mode_reglement, s.cond_reglement, s.transport_mode'; $sql .= ', s.fk_account, s.tva_assuj'; @@ -1673,6 +1748,9 @@ class Societe extends CommonObject $this->webservices_url = $obj->webservices_url; $this->webservices_key = $obj->webservices_key; + $this->accountancy_code_buy = $obj->accountancy_code_buy; + $this->accountancy_code_sell = $obj->accountancy_code_sell; + $this->outstanding_limit = $obj->outstanding_limit; $this->order_min_amount = $obj->order_min_amount; $this->supplier_order_min_amount = $obj->supplier_order_min_amount; @@ -4490,4 +4568,57 @@ class Societe extends CommonObject return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables); } + + /** + * Sets an accountancy code for a thirdparty. + * Also calls COMPANY_MODIFY trigger when modified + * + * @param string $type It can be only 'buy' or 'sell' + * @param string $value Accountancy code + * @return int <0 KO >0 OK + */ + public function setAccountancyCode($type, $value) + { + global $user, $langs, $conf; + + $this->db->begin(); + + if ($type == 'buy') { + $field = 'accountancy_code_buy'; + } elseif ($type == 'sell') { + $field = 'accountancy_code_sell'; + } else { + return -1; + } + + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET "; + $sql.= "$field = '".$this->db->escape($value)."'"; + $sql.= " WHERE rowid = ".$this->id; + + dol_syslog(get_class($this)."::".__FUNCTION__." sql=".$sql, LOG_DEBUG); + $resql = $this->db->query($sql); + + if ($resql) { + // Call triggers + include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; + $interface=new Interfaces($this->db); + $result=$interface->run_triggers('COMPANY_MODIFY', $this, $user, $langs, $conf); + if ($result < 0) { + $this->errors=$interface->errors; + $this->db->rollback(); + return -1; + } + // End call triggers + + $this->$field = $value; + + $this->db->commit(); + return 1; + } + else { + $this->error=$this->db->lasterror(); + $this->db->rollback(); + return -1; + } + } } diff --git a/htdocs/societe/price.php b/htdocs/societe/price.php index 0afe58ece05..dfcfde06c6c 100644 --- a/htdocs/societe/price.php +++ b/htdocs/societe/price.php @@ -88,6 +88,7 @@ if (empty($reshook)) // add price by customer $prodcustprice->fk_soc = $socid; + $prodcustprice->ref_customer = GETPOST('ref_customer', 'alpha'); $prodcustprice->fk_product = GETPOST('prodid', 'int'); $prodcustprice->price = price2num(GETPOST("price"), 'MU'); $prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU'); @@ -162,6 +163,7 @@ if (empty($reshook)) $update_child_soc = GETPOST('updatechildprice'); // update price by customer + $prodcustprice->ref_customer = GETPOST('ref_customer', 'alpha'); $prodcustprice->price = price2num(GETPOST("price"), 'MU'); $prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU'); $prodcustprice->price_base_type = GETPOST("price_base_type", 'alpha'); @@ -298,6 +300,10 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print ''; print ''; + // Ref. Customer + print ''.$langs->trans('RefCustomer').''; + print ''; + // VAT print ''.$langs->trans("VATRate").''; print $form->load_tva("tva_tx", $object->tva_tx, $mysoc, '', $object->id, $object->tva_npr, '', false, 1); @@ -376,6 +382,10 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print "".$staticprod->getNomUrl(1).""; print ''; + // Ref. Customer + print ''.$langs->trans('RefCustomer').''; + print ''; + // VAT print ''.$langs->trans("VATRate").''; print $form->load_tva("tva_tx", $prodcustprice->tva_tx, $mysoc, '', $staticprod->id, $prodcustprice->recuperableonly); @@ -465,6 +475,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print ''; print ''.$langs->trans("Product").''; + print ''.$langs->trans('RefCustomer').''; print ''.$langs->trans("AppliedPricesFrom").''; print ''.$langs->trans("PriceBase").''; print ''.$langs->trans("VAT").''; @@ -482,6 +493,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { $staticprod->fetch($line->fk_product); print "".$staticprod->getNomUrl(1).""; + print ''.$line->ref_customer.''; print "".dol_print_date($line->datec, "dayhour").""; print ''.$langs->trans($line->price_base_type).""; @@ -551,6 +563,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print ''; print ''.$langs->trans("Ref").''; print ''.$langs->trans("Product").''; + print ''.$langs->trans('RefCustomer').''; print ''.$langs->trans("AppliedPricesFrom").''; print ''.$langs->trans("PriceBase").''; print ''.$langs->trans("VAT").''; @@ -567,7 +580,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print ''; print ''; print ''; - print ' '; + print ' '; print ''; print ''; print ' '; @@ -590,6 +603,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print "".$staticprod->getNomUrl(1).""; print "".$staticprod->label.""; + print ''.$line->ref_customer.''; print "".dol_print_date($line->datec, "dayhour").""; print ''.$langs->trans($line->price_base_type).""; @@ -627,7 +641,7 @@ if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) { print "\n"; } } else { - $colspan = 9; + $colspan = 10; if ($user->rights->produit->supprimer || $user->rights->service->supprimer) $colspan += 1; print ''.$langs->trans('None').''; } diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index a571a207bc5..a9411e6d283 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -555,9 +555,9 @@ if (empty($reshook)) $tva_tx = ''; } - $qty = price2num(GETPOST('qty'.$predef), 'alpha'); + $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS'); $remise_percent = GETPOST('remise_percent'.$predef); - $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CR'); + $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU'); // Extrafields $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line); @@ -869,7 +869,7 @@ if (empty($reshook)) } $price_base_type = 'HT'; - $pu_ht_devise = GETPOST('multicurrency_subprice'); + $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), 'CU'); // Add buying price $fournprice = (GETPOST('fournprice') ? GETPOST('fournprice') : ''); diff --git a/htdocs/takepos/freezone.php b/htdocs/takepos/freezone.php index 4cca5816fab..a010ba184eb 100644 --- a/htdocs/takepos/freezone.php +++ b/htdocs/takepos/freezone.php @@ -95,7 +95,7 @@ top_htmlhead($head, '', 0, 0, $arrayofjs, $arrayofcss); */ function Save() { console.log("We click so we call page invoice.php with place= tva_tx="+vatRate); - $.get( "invoice.php", { action: "", place: "", desc:$('#desc').val(), number:$('#number').val(), tva_tx: vatRate} ); + parent.$("#poslines").load("invoice.php?action=freezone&place=&desc="+$('#desc').val()+"&number="+$('#number').val()+"&tva_tx="+vatRate); parent.$.colorbox.close(); } diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index ec012a8ddcd..6fedcd0292a 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -475,7 +475,7 @@ function Floors() { function FreeZone() { console.log("Open box to enter a free product"); - $.colorbox({href:"freezone.php?action=freezone&place="+place, onClosed: function () { Refresh(); },width:"80%", height:"200px", transition:"none", iframe:"true", title:"trans("FreeZone"); ?>"}); + $.colorbox({href:"freezone.php?action=freezone&place="+place, width:"80%", height:"200px", transition:"none", iframe:"true", title:"trans("FreeZone"); ?>"}); } function TakeposOrderNotes() { diff --git a/htdocs/workstation/class/workstation.class.php b/htdocs/workstation/class/workstation.class.php new file mode 100755 index 00000000000..31497cbc919 --- /dev/null +++ b/htdocs/workstation/class/workstation.class.php @@ -0,0 +1,1054 @@ + + * Copyright (C) 2020 Gauthier VERDOL + * + * 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 class/workstation.class.php + * \ingroup workstation + * \brief This file is a CRUD class file for Workstation (Create/Read/Update/Delete) + */ + +// Put here all includes required by your class file +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; +//require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + +/** + * Class for Workstation + */ +class Workstation extends CommonObject +{ + /** + * @var string ID of module. + */ + public $module = 'workstation'; + + /** + * @var string ID to identify managed object. + */ + public $element = 'workstation'; + + /** + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. + */ + public $table_element = 'workstation_workstation'; + + /** + * @var int Does this object support multicompany module ? + * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table + */ + public $ismultientitymanaged = 0; + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 0; + + /** + * @var string String with name of icon for workstation. Must be the part after the 'object_' into object_workstation.png + */ + public $picto = 'mrp'; + + + const STATUS_DISABLED = 0; + const STATUS_ENABLED = 1; + + + /** + * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') + * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" + * 'label' the translation key. + * 'picto' is code of a picto to show before value in forms + * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) + * 'position' is the sort order of field. + * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. + * 'index' if we want an index in database. + * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. + * 'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8). + * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'maxwidth200', 'wordbreak', 'tdoverflowmax200' + * 'help' is a string visible as a tooltip on field + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. + * 'arraykeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel") + * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. + * 'comment' is not used. You can store here any text of your choice. It is not used by application. + * + * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. + */ + + // BEGIN MODULEBUILDER PROPERTIES + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields=array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), + 'ref' => array('type'=>'varchar(128)', 'picto'=>'mrp', 'label'=>'Ref', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>1, 'noteditable'=>'0', 'default'=>'', 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'comment'=>"Reference of object"), + 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>30, 'notnull'=>1, 'visible'=>1, 'searchall'=>1, 'css'=>'minwidth300', 'showoncombobox'=>'1',), + 'type' => array('type'=>'select', 'label'=>'Type', 'enabled'=>'1', 'position'=>32, 'default'=>1, 'notnull'=>1, 'visible'=>1, 'arrayofkeyval'=>array('HUMAN'=>'Human', 'MACHINE'=>'Machine', 'BOTH'=>'HumanMachine'),), + 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>61, 'notnull'=>0, 'visible'=>0,), + 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>62, 'notnull'=>0, 'visible'=>0,), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>500, 'notnull'=>1, 'visible'=>-2,), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>501, 'notnull'=>0, 'visible'=>-2,), + 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>510, 'notnull'=>1, 'visible'=>-2, 'foreignkey'=>'user.rowid',), + 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>511, 'notnull'=>-1, 'visible'=>-2,), + 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>512, 'notnull'=>-1, 'visible'=>-2,), + 'nb_operators_required' => array('type'=>'integer', 'label'=>'NbOperatorsRequired', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,), + 'thm_operator_estimated' => array('type'=>'double', 'help'=>'THMEstimatedHelp','label'=>'THMOperatorEstimated', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,), + 'thm_machine_estimated' => array('type'=>'double', 'help'=>'THMEstimatedHelp', 'label'=>'THMMachineEstimated', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>1,), + 'status' => array('type'=>'smallint', 'label'=>'Status', 'enabled'=>'1', 'position'=>1000, 'default'=>1, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Disabled', '1'=>'Enabled'),), + ); + public $rowid; + public $ref; + public $label; + public $note_public; + public $note_private; + public $date_creation; + public $tms; + public $fk_user_creat; + public $fk_user_modif; + public $import_key; + public $status; + public $nb_operators_required; + public $thm_operator_estimated; + public $thm_machine_estimated; + // END MODULEBUILDER PROPERTIES + + + // If this object has a subtable with lines + + /** + * @var int Name of subtable line + */ + //public $table_element_line = 'workstation_workstationline'; + + /** + * @var int Field with ID of parent key if this object has a parent + */ + //public $fk_element = 'fk_workstation'; + + /** + * @var int Name of subtable class that manage subtable lines + */ + //public $class_element_line = 'Workstationline'; + + /** + * @var array List of child tables. To test if we can delete object. + */ + //protected $childtables = array(); + + /** + * @var array List of child tables. To know object to delete on cascade. + * If name matches '@ClassNAme:FilePathClass;ParentFkFieldName' it will + * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object + */ + //protected $childtablesoncascade = array('workstation_workstationdet'); + + /** + * @var WorkstationLine[] Array of subtable lines + */ + //public $lines = array(); + + + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + dol_include_once('/workstation/class/workstationusergroup.class.php'); + dol_include_once('/workstation/class/workstationresource.class.php'); + + $this->db = $db; + + $this->fields['ref']['default'] = $this->getNextNumRef(); + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible'] = 0; + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) $this->fields['entity']['enabled'] = 0; + + // Example to show how to set values of fields definition dynamically + /*if ($user->rights->workstation->workstation->read) { + $this->fields['myfield']['visible'] = 1; + $this->fields['myfield']['noteditable'] = 0; + }*/ + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) + { + if (isset($val['enabled']) && empty($val['enabled'])) + { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) + { + foreach ($this->fields as $key => $val) + { + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) + { + foreach ($val['arrayofkeyval'] as $key2 => $val2) + { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, Id of created object if OK + */ + public function create(User $user, $notrigger = false) + { + global $db; + + $id = $this->createCommon($user, $notrigger); + + // Usergroups + $groups = GETPOST('groups'); + if (empty($groups)) $groups = $this->usergroups; // createFromClone + if (!empty($groups)) { + foreach ($groups as $id_group) { + $ws_usergroup = new WorkstationUserGroup($db); + $ws_usergroup->fk_workstation = $id; + $ws_usergroup->fk_usergroup = $id_group; + $ws_usergroup->createCommon($user); + $this->usergroups[] = $id_group; + } + } + + // Resources + $resources = GETPOST('resources'); + if (empty($resources)) $resources = $this->resources; // createFromClone + if (!empty($resources)) { + foreach ($resources as $id_resource) { + $ws_resource = new WorkstationResource($db); + $ws_resource->fk_workstation = $id; + $ws_resource->fk_resource = $id_resource; + $ws_resource->createCommon($user); + $this->resources[] = $id_resource; + } + } + + return $id; + } + + /** + * Clone an object into another one + * + * @param User $user User that creates + * @param int $fromid Id of object to clone + * @return mixed New object created, <0 if KO + */ + public function createFromClone(User $user, $fromid) + { + global $langs, $extrafields; + $error = 0; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $object = new self($this->db); + + $this->db->begin(); + + // Load source object + $result = $object->fetch($fromid); + if ($result > 0 && !empty($object->table_element_line)) $object->fetchLines(); + + // get lines so they will be clone + //foreach($this->lines as $line) + // $line->fetch_optionals(); + + // Reset some properties + unset($object->id); + unset($object->fk_user_creat); + unset($object->import_key); + + // Clear fields + if (property_exists($object, 'ref')) $object->ref = empty($this->fields['ref']['default']) ? "Copy_Of_".$object->ref : $this->fields['ref']['default']; + if (property_exists($object, 'label')) $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label : $this->fields['label']['default']; + if (property_exists($object, 'status')) { $object->status = self::STATUS_DISABLED; } + if (property_exists($object, 'date_creation')) { $object->date_creation = dol_now(); } + if (property_exists($object, 'date_modification')) { $object->date_modification = null; } + // ... + // Clear extrafields that are unique + if (is_array($object->array_options) && count($object->array_options) > 0) + { + $extrafields->fetch_name_optionals_label($this->table_element); + foreach ($object->array_options as $key => $option) + { + $shortkey = preg_replace('/options_/', '', $key); + if (!empty($extrafields->attributes[$this->table_element]['unique'][$shortkey])) + { + //var_dump($key); var_dump($clonedObj->array_options[$key]); exit; + unset($object->array_options[$key]); + } + } + } + + // Create clone + $object->context['createfromclone'] = 'createfromclone'; + $result = $object->create($user); + if ($result < 0) { + $error++; + $this->error = $object->error; + $this->errors = $object->errors; + } + + if (!$error) + { + // copy internal contacts + if ($this->copy_linked_contact($object, 'internal') < 0) + { + $error++; + } + } + + if (!$error) + { + // copy external contacts if same company + if (property_exists($this, 'socid') && $this->socid == $object->socid) + { + if ($this->copy_linked_contact($object, 'external') < 0) + $error++; + } + } + + unset($object->context['createfromclone']); + + // End + if (!$error) { + $this->db->commit(); + return $object; + } else { + $this->db->rollback(); + return -1; + } + } + + /** + * Load object in memory from the database + * + * @param int $id Id object + * @param string $ref Ref + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetch($id, $ref = null) + { + $result = $this->fetchCommon($id, $ref); + + $this->usergroups = WorkstationUserGroup::getAllGroupsOfWorkstation($this->id); + $this->resources = WorkstationResource::getAllResourcesOfWorkstation($this->id); + + if ($result > 0 && !empty($this->table_element_line)) $this->fetchLines(); + return $result; + } + + /** + * Load object lines in memory from the database + * + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetchLines() + { + $this->lines = array(); + + $result = $this->fetchLinesCommon(); + return $result; + } + + + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) + * @param string $filtermode Filter mode (AND or OR) + * @return array|int int <0 if KO, array of pages if OK + */ + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + { + global $conf; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $records = array(); + + $sql = 'SELECT '; + $sql .= $this->getFieldList(); + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + else $sql .= ' WHERE 1 = 1'; + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key.'='.$value; + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } elseif (strpos($value, '%') === false) { + $sqlwhere[] = $key.' IN ('.$this->db->sanitize($this->db->escape($value)).')'; + } else { + $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= ' '.$this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < ($limit ? min($limit, $num) : $num)) + { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; + } + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function update(User $user, $notrigger = false) + { + + // Usergroups + $groups = GETPOST('groups'); + WorkstationUserGroup::deleteAllGroupsOfWorkstation($this->id); + $this->usergroups=array(); + + foreach ($groups as $id_group) { + $ws_usergroup = new WorkstationUserGroup($this->db); + $ws_usergroup->fk_workstation = $this->id; + $ws_usergroup->fk_usergroup = $id_group; + $ws_usergroup->createCommon($user); + $this->usergroups[] = $id_group; + } + + // Resources + $resources = GETPOST('resources'); + WorkstationResource::deleteAllResourcesOfWorkstation($this->id); + $this->resources=array(); + if (!empty($resources)) { + foreach ($resources as $id_resource) { + $ws_resource = new WorkstationResource($this->db); + $ws_resource->fk_workstation = $this->id; + $ws_resource->fk_resource = $id_resource; + $ws_resource->createCommon($user); + $this->resources[] = $id_resource; + } + } + + return $this->updateCommon($user, $notrigger); + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function delete(User $user, $notrigger = false) + { + return $this->deleteCommon($user, $notrigger); + //return $this->deleteCommon($user, $notrigger, 1); + } + + /** + * Delete a line of object in database + * + * @param User $user User that delete + * @param int $idline Id of line to delete + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int >0 if OK, <0 if KO + */ + public function deleteLine(User $user, $idline, $notrigger = false) + { + if ($this->status < 0) + { + $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus'; + return -2; + } + + return $this->deleteLineCommon($user, $idline, $notrigger); + } + + + /** + * Validate object + * + * @param User $user User making status change + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @return int <=0 if OK, 0=Nothing done, >0 if KO + */ + public function validate($user, $notrigger = 0) + { + global $conf, $langs; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + $error = 0; + + // Protection + if ($this->status == self::STATUS_VALIDATED) + { + dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING); + return 0; + } + + /*if (! ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation->write)) + || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->workstation->workstation->workstation_advance->validate)))) + { + $this->error='NotEnoughPermissions'; + dol_syslog(get_class($this)."::valid ".$this->error, LOG_ERR); + return -1; + }*/ + + $now = dol_now(); + + $this->db->begin(); + + // Define new ref + if (!$error && (preg_match('/^[\(]?PROV/i', $this->ref) || empty($this->ref))) // empty should not happened, but when it occurs, the test save life + { + $num = $this->getNextNumRef(); + } else { + $num = $this->ref; + } + $this->newref = $num; + + if (!empty($num)) { + // Validate + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " SET ref = '".$this->db->escape($num)."',"; + $sql .= " status = ".self::STATUS_VALIDATED; + if (!empty($this->fields['date_validation'])) $sql .= ", date_validation = '".$this->db->idate($now)."'"; + if (!empty($this->fields['fk_user_valid'])) $sql .= ", fk_user_valid = ".$user->id; + $sql .= " WHERE rowid = ".$this->id; + + dol_syslog(get_class($this)."::validate()", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) + { + dol_print_error($this->db); + $this->error = $this->db->lasterror(); + $error++; + } + + if (!$error && !$notrigger) + { + // Call trigger + $result = $this->call_trigger('WORKSTATION_VALIDATE', $user); + if ($result < 0) $error++; + // End call triggers + } + } + + if (!$error) + { + $this->oldref = $this->ref; + + // Rename directory if dir was a temporary ref + if (preg_match('/^[\(]?PROV/i', $this->ref)) + { + // Now we rename also files into index + $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'workstation/".$this->db->escape($this->newref)."'"; + $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'workstation/".$this->db->escape($this->ref)."' and entity = ".$conf->entity; + $resql = $this->db->query($sql); + if (!$resql) { $error++; $this->error = $this->db->lasterror(); } + + // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments + $oldref = dol_sanitizeFileName($this->ref); + $newref = dol_sanitizeFileName($num); + $dirsource = $conf->workstation->dir_output.'/workstation/'.$oldref; + $dirdest = $conf->workstation->dir_output.'/workstation/'.$newref; + if (!$error && file_exists($dirsource)) + { + dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest); + + if (@rename($dirsource, $dirdest)) + { + dol_syslog("Rename ok"); + // Rename docs starting with $oldref with $newref + $listoffiles = dol_dir_list($conf->workstation->dir_output.'/workstation/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/')); + foreach ($listoffiles as $fileentry) + { + $dirsource = $fileentry['name']; + $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource); + $dirsource = $fileentry['path'].'/'.$dirsource; + $dirdest = $fileentry['path'].'/'.$dirdest; + @rename($dirsource, $dirdest); + } + } + } + } + } + + // Set new ref and current status + if (!$error) + { + $this->ref = $num; + $this->status = self::STATUS_VALIDATED; + } + + if (!$error) + { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } + + + /** + * Set draft status + * + * @param int $status New status to set + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setStatus($status, $notrigger = 0) + { + global $user; + + $this->status = $status; + + if (empty($status)) return $this->setDisabled($user, $notrigger); + else return $this->setEnabled($user, $notrigger); + } + + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setEnabled($user, $notrigger = 0) + { + return $this->setStatusCommon($user, self::STATUS_ENABLED, $notrigger, 'WORKSTATION_ENABLED'); + } + + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int <0 if KO, >0 if OK + */ + public function setDisabled($user, $notrigger = 0) + { + return $this->setStatusCommon($user, self::STATUS_DISABLED, $notrigger, 'WORKSTATION_DISABLED'); + } + + /** + * Return a link to the object card (with optionaly the picto) + * + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to ('nolink', ...) + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL + */ + public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) + { + global $conf, $langs, $hookmanager; + + if (!empty($conf->dol_no_mouse_hover)) $notooltip = 1; // Force disable tooltips + + $result = ''; + + $label = img_picto('', $this->picto).' '.$langs->trans("Workstation").''; + $label .= '
'; + $label .= ''.$langs->trans('Ref').': '.$this->ref; + if (isset($this->status)) { + $label .= '
'.$langs->trans("Status").": ".$this->getLibStatut(5); + } + + $url = dol_buildpath('/workstation/workstation_card.php', 1).'?id='.$this->id; + + if ($option != 'nolink') + { + // Add param to save lastsearch_values or not + $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); + if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1; + if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1'; + } + + $linkclose = ''; + if (empty($notooltip)) + { + if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) + { + $label = $langs->trans("ShowWorkstation"); + $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; + } + $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; + $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; + } else $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); + + $linkstart = ''; + $linkend = ''; + + $result .= $linkstart; + + if (empty($this->showphoto_on_popup)) { + if ($withpicto) $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'mrp'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } else { + if ($withpicto) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + list($class, $module) = explode('@', $this->picto); + $upload_dir = $conf->$module->multidir_output[$conf->entity]."/$class/".dol_sanitizeFileName($this->ref); + $filearray = dol_dir_list($upload_dir, "files"); + $filename = $filearray[0]['name']; + if (!empty($filename)) { + $pospoint = strpos($filearray[0]['name'], '.'); + + $pathtophoto = $class.'/'.$this->ref.'/thumbs/'.substr($filename, 0, $pospoint).'_mini'.substr($filename, $pospoint); + if (empty($conf->global->{strtoupper($module.'_'.$class).'_FORMATLISTPHOTOSASUSERS'})) { + $result .= '
No photo
'; + } else { + $result .= '
No photo
'; + } + + $result .= '
'; + } else { + $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'mrp'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); + } + } + } + + if ($withpicto != 2) $result .= $this->ref; + + $result .= $linkend; + //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + + global $action, $hookmanager; + $hookmanager->initHooks(array('workstationdao')); + $parameters = array('id'=>$this->id, 'getnomurl'=>$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) $result = $hookmanager->resPrint; + else $result .= $hookmanager->resPrint; + + return $result; + } + + /** + * Return the label of the status + * + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function getLibStatut($mode = 0) + { + return $this->LibStatut($this->status, $mode); + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Return the status + * + * @param int $status Id status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function LibStatut($status, $mode = 0) + { + // phpcs:enable + if (empty($this->labelStatus) || empty($this->labelStatusShort)) + { + global $langs; + //$langs->load("workstation@workstation"); + $this->labelStatus[self::STATUS_DISABLED] = $langs->trans('Disabled'); + $this->labelStatus[self::STATUS_ENABLED] = $langs->trans('Enabled'); + } + + $statusType = 'status'.$status; + //if ($status == self::STATUS_VALIDATED) $statusType = 'status1'; + //if ($status == self::STATUS_CANCELED) $statusType = 'status6'; + + return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); + } + + /** + * Load the info information in the object + * + * @param int $id Id of object + * @return void + */ + public function info($id) + { + $sql = 'SELECT rowid, date_creation as datec, tms as datem,'; + $sql .= ' fk_user_creat, fk_user_modif'; + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; + $sql .= ' WHERE t.rowid = '.$id; + $result = $this->db->query($sql); + if ($result) + { + if ($this->db->num_rows($result)) + { + $obj = $this->db->fetch_object($result); + $this->id = $obj->rowid; + if ($obj->fk_user_author) + { + $cuser = new User($this->db); + $cuser->fetch($obj->fk_user_author); + $this->user_creation = $cuser; + } + + if ($obj->fk_user_valid) + { + $vuser = new User($this->db); + $vuser->fetch($obj->fk_user_valid); + $this->user_validation = $vuser; + } + + if ($obj->fk_user_cloture) + { + $cluser = new User($this->db); + $cluser->fetch($obj->fk_user_cloture); + $this->user_cloture = $cluser; + } + + $this->date_creation = $this->db->jdate($obj->datec); + $this->date_modification = $this->db->jdate($obj->datem); + $this->date_validation = $this->db->jdate($obj->datev); + } + + $this->db->free($result); + } else { + dol_print_error($this->db); + } + } + + /** + * Initialise object with example values + * Id must be 0 if object instance is a specimen + * + * @return void + */ + public function initAsSpecimen() + { + $this->initAsSpecimenCommon(); + } + + /** + * Create an array of lines + * + * @return array|int array of lines if OK, <0 if KO + */ + public function getLinesArray() + { + $this->lines = array(); + + $objectline = new WorkstationLine($this->db); + $result = $objectline->fetchAll('ASC', 'position', 0, 0, array('customsql'=>'fk_workstation = '.$this->id)); + + if (is_numeric($result)) + { + $this->error = $this->error; + $this->errors = $this->errors; + return $result; + } else { + $this->lines = $result; + return $this->lines; + } + } + + /** + * Returns the reference to the following non used object depending on the active numbering module. + * + * @return string Object free reference + */ + public function getNextNumRef() + { + global $langs, $conf; + $langs->load("workstation@workstation"); + + if (empty($conf->global->WORKSTATION_WORKSTATION_ADDON)) { + $conf->global->WORKSTATION_WORKSTATION_ADDON = 'mod_workstation_standard'; + } + + if (!empty($conf->global->WORKSTATION_WORKSTATION_ADDON)) + { + $mybool = false; + + $file = $conf->global->WORKSTATION_WORKSTATION_ADDON.".php"; + $classname = $conf->global->WORKSTATION_WORKSTATION_ADDON; + + // Include file with class + $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) + { + $dir = dol_buildpath($reldir."core/modules/workstation/"); + + // Load file with numbering class (if found) + $mybool |= @include_once $dir.$file; + } + + if ($mybool === false) + { + dol_print_error('', "Failed to include file ".$file); + return ''; + } + + if (class_exists($classname)) { + $obj = new $classname(); + $numref = $obj->getNextValue($this); + + if ($numref != '' && $numref != '-1') + { + return $numref; + } else { + $this->error = $obj->error; + //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error); + return ""; + } + } else { + print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname; + return ""; + } + } else { + print $langs->trans("ErrorNumberingModuleNotSetup", $this->element); + return ""; + } + } + + /** + * Create a document onto disk according to template module. + * + * @param string $modele Force template to use ('' to not force) + * @param Translate $outputlangs objet lang a utiliser pour traduction + * @param int $hidedetails Hide details of lines + * @param int $hidedesc Hide description + * @param int $hideref Hide ref + * @param null|array $moreparams Array to provide more information + * @return int 0 if KO, 1 if OK + */ + public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null) + { + global $conf, $langs; + + $result = 0; + $includedocgeneration = 0; + + $langs->load("workstation@workstation"); + + if (!dol_strlen($modele)) { + $modele = 'standard_workstation'; + + if ($this->model_pdf) { + $modele = $this->model_pdf; + } elseif (!empty($conf->global->WORKSTATION_ADDON_PDF)) { + $modele = $conf->global->WORKSTATION_ADDON_PDF; + } + } + + $modelpath = "core/modules/workstation/doc/"; + + if ($includedocgeneration) { + $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams); + } + + return $result; + } + + /** + * Action executed by scheduler + * CAN BE A CRON TASK. In such a case, parameters come from the schedule job setup field 'Parameters' + * Use public function doScheduledJob($param1, $param2, ...) to get parameters + * + * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) + */ + public function doScheduledJob() + { + global $conf, $langs; + + //$conf->global->SYSLOG_FILE = 'DOL_DATA_ROOT/dolibarr_mydedicatedlofile.log'; + + $error = 0; + $this->output = ''; + $this->error = ''; + + dol_syslog(__METHOD__, LOG_DEBUG); + + $now = dol_now(); + + $this->db->begin(); + + // ... + + $this->db->commit(); + + return $error; + } +} diff --git a/htdocs/workstation/class/workstationresource.class.php b/htdocs/workstation/class/workstationresource.class.php new file mode 100644 index 00000000000..21398460eca --- /dev/null +++ b/htdocs/workstation/class/workstationresource.class.php @@ -0,0 +1,98 @@ + + * Copyright (C) 2020 Gauthier VERDOL + * + * 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 class/workstationresource.class.php + * \ingroup workstation + * \brief This file is a CRUD class file for WorkstationResource (Create/Read/Update/Delete) + */ + +/** + * Class for WorkstationResource + */ + +class WorkstationResource extends CommonObject +{ + /** @var string $table_element Table name in SQL */ + public $table_element = 'workstation_workstation_resource'; + + /** @var string $element Name of the element (tip for better integration in Dolibarr: this value should be the reflection of the class name with ucfirst() function) */ + public $element = 'workstationresource'; + + public $fields = array( + 'fk_workstation' => array ('type' => 'integer'), + 'fk_resource' => array ('type' => 'integer') + ); + + /** + * WorkstationResource constructor. + * @param DoliDB $db Database connector + */ + public function __construct($db) + { + $this->db = $db; + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) + { + if (isset($val['enabled']) && empty($val['enabled'])) + { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) + { + foreach ($this->fields as $key => $val) + { + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) + { + foreach ($val['arrayofkeyval'] as $key2 => $val2) + { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + /** + * Function used to get an array with all resources linked to a workstation + * @param int $fk_workstation id of workstation we need to get linked resources + * @return array + */ + static public function getAllResourcesOfWorkstation($fk_workstation) + { + global $db; + $obj = new self($db); + return parent::getAllItemsLinkedByObjectID($fk_workstation, 'fk_resource', 'fk_workstation', $obj->table_element); + } + + /** + * Function used to remove all resources linked to a workstation + * @param int $fk_workstation id of workstation we need to remove linked resources + * @return int + */ + static public function deleteAllResourcesOfWorkstation($fk_workstation) + { + global $db; + $obj = new self($db); + return parent::deleteAllItemsLinkedByObjectID($fk_workstation, 'fk_workstation', $obj->table_element); + } +} diff --git a/htdocs/workstation/class/workstationusergroup.class.php b/htdocs/workstation/class/workstationusergroup.class.php new file mode 100644 index 00000000000..b45d24c7c60 --- /dev/null +++ b/htdocs/workstation/class/workstationusergroup.class.php @@ -0,0 +1,98 @@ + + * Copyright (C) 2020 Gauthier VERDOL + * + * 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 class/workstationusergroup.class.php + * \ingroup workstation + * \brief This file is a CRUD class file for WorkstationUserGroup (Create/Read/Update/Delete) + */ + +/** + * Class for WorkstationUserGroup + */ + +class WorkstationUserGroup extends CommonObject +{ + /** @var string $table_element Table name in SQL */ + public $table_element = 'workstation_workstation_usergroup'; + + /** @var string $element Name of the element (tip for better integration in Dolibarr: this value should be the reflection of the class name with ucfirst() function) */ + public $element = 'workstationusergroup'; + + public $fields = array( + 'fk_workstation' => array ('type' => 'integer'), + 'fk_usergroup' => array ('type' => 'integer') + ); + + /** + * WorkstationUserGroup constructor. + * @param DoliDB $db Database connector + */ + public function __construct($db) + { + $this->db = $db; + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) + { + if (isset($val['enabled']) && empty($val['enabled'])) + { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) + { + foreach ($this->fields as $key => $val) + { + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) + { + foreach ($val['arrayofkeyval'] as $key2 => $val2) + { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + /** + * Function used to get an array with all usergroups linked to a workstation + * @param int $fk_workstation id of workstation we need to get linked usergroups + * @return array + */ + static public function getAllGroupsOfWorkstation($fk_workstation) + { + global $db; + $obj = new self($db); + return parent::getAllItemsLinkedByObjectID($fk_workstation, 'fk_usergroup', 'fk_workstation', $obj->table_element); + } + + /** + * Function used to remove all usergroups linked to a workstation + * @param int $fk_workstation id of workstation we need to remove linked usergroups + * @return int + */ + static public function deleteAllGroupsOfWorkstation($fk_workstation) + { + global $db; + $obj = new self($db); + return parent::deleteAllItemsLinkedByObjectID($fk_workstation, 'fk_workstation', $obj->table_element); + } +} diff --git a/htdocs/workstation/lib/workstation.lib.php b/htdocs/workstation/lib/workstation.lib.php new file mode 100755 index 00000000000..18307d0cd3a --- /dev/null +++ b/htdocs/workstation/lib/workstation.lib.php @@ -0,0 +1,65 @@ + + * + * 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 workstation/lib/workstation.lib.php + * \ingroup workstation + * \brief Library files with common functions for Workstation + */ + +/** + * Prepare admin pages header + * + * @return array + */ +function workstationAdminPrepareHead() +{ + global $langs, $conf; + + $langs->load("workstation@workstation"); + + $h = 0; + $head = array(); + $head[$h][0] = DOL_URL_ROOT . "/admin/workstation.php"; + $head[$h][1] = $langs->trans("Settings"); + $head[$h][2] = 'settings'; + $h++; + + /* + $head[$h][0] = dol_buildpath("/workstation/admin/myobject_extrafields.php", 1); + $head[$h][1] = $langs->trans("ExtraFields"); + $head[$h][2] = 'myobject_extrafields'; + $h++; + */ + + /*$head[$h][0] = require_once "/admin/about.php"; + $head[$h][1] = $langs->trans("About"); + $head[$h][2] = 'about'; + $h++;*/ + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + //$this->tabs = array( + // 'entity:+tabname:Title:@workstation:/workstation/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@workstation:/workstation/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, null, $head, $h, 'workstation'); + + return $head; +} diff --git a/htdocs/workstation/lib/workstation_workstation.lib.php b/htdocs/workstation/lib/workstation_workstation.lib.php new file mode 100755 index 00000000000..cc7fcc58f89 --- /dev/null +++ b/htdocs/workstation/lib/workstation_workstation.lib.php @@ -0,0 +1,85 @@ + + * + * 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 lib/workstation_workstation.lib.php + * \ingroup workstation + * \brief Library files with common functions for Workstation + */ + +/** + * Prepare array of tabs for Workstation + * + * @param Workstation $object Workstation + * @return array Array of tabs + */ +function workstationPrepareHead($object) +{ + global $db, $langs, $conf; + + $langs->load("workstation@workstation"); + + $h = 0; + $head = array(); + + $head[$h][0] = dol_buildpath("/workstation/workstation_card.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Card"); + $head[$h][2] = 'card'; + $h++; + + if (isset($object->fields['note_public']) || isset($object->fields['note_private'])) + { + $nbNote = 0; + if (!empty($object->note_private)) $nbNote++; + if (!empty($object->note_public)) $nbNote++; + $head[$h][0] = dol_buildpath('/workstation/workstation_note.php', 1).'?id='.$object->id; + $head[$h][1] = $langs->trans('Notes'); + if ($nbNote > 0) $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.$nbNote.'' : ''); + $head[$h][2] = 'note'; + $h++; + } + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; + $upload_dir = $conf->workstation->dir_output."/workstation/".dol_sanitizeFileName($object->ref); + $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); + $nbLinks = Link::count($db, $object->element, $object->id); + $head[$h][0] = dol_buildpath("/workstation/workstation_document.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans('Documents'); + if (($nbFiles + $nbLinks) > 0) $head[$h][1] .= ''.($nbFiles + $nbLinks).''; + $head[$h][2] = 'document'; + $h++; + + $head[$h][0] = dol_buildpath("/workstation/workstation_agenda.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Events"); + $head[$h][2] = 'agenda'; + $h++; + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + //$this->tabs = array( + // 'entity:+tabname:Title:@workstation:/workstation/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@workstation:/workstation/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, $object, $head, $h, 'workstation@workstation'); + + complete_head_from_modules($conf, $langs, $object, $head, $h, 'workstation@workstation', 'remove'); + + return $head; +} diff --git a/htdocs/workstation/workstation_agenda.php b/htdocs/workstation/workstation_agenda.php new file mode 100755 index 00000000000..e2951554488 --- /dev/null +++ b/htdocs/workstation/workstation_agenda.php @@ -0,0 +1,276 @@ + + * Copyright (C) 2020 Gauthier VERDOL + * + * 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 workstation_agenda.php + * \ingroup workstation + * \brief Tab of events on Workstation + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +dol_include_once('/workstation/class/workstation.class.php'); +dol_include_once('/workstation/lib/workstation_workstation.lib.php'); + + +// Load translation files required by the page +$langs->loadLangs(array("workstation@workstation", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +if (GETPOST('actioncode', 'array')) { + $actioncode = GETPOST('actioncode', 'array', 3); + if (!count($actioncode)) $actioncode = '0'; +} else { + $actioncode = GETPOST("actioncode", "alpha", 3) ?GETPOST("actioncode", "alpha", 3) : (GETPOST("actioncode") == '0' ? '0' : (empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT) ? '' : $conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT)); +} +$search_agenda_label = GETPOST('search_agenda_label'); + +$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST("sortfield", 'alpha'); +$sortorder = GETPOST("sortorder", 'alpha'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (!$sortfield) $sortfield = 'a.datep,a.id'; +if (!$sortorder) $sortorder = 'DESC,DESC'; + +// Initialize technical objects +$object = new Workstation($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->workstation->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('workstationagenda', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) $upload_dir = $conf->workstation->multidir_output[$object->entity]."/".$object->id; + +// Security check - Protection if external user +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$result = restrictedArea($user, 'workstation', $object->id); + +$permissiontoadd = $user->rights->workstation->workstation->write; // Used by the include of actions_addupdatedelete.inc.php + + +/* + * Actions + */ + +$parameters = array('id'=>$id); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + // Cancel + if (GETPOST('cancel', 'alpha') && !empty($backtopage)) + { + header("Location: ".$backtopage); + exit; + } + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) // All tests are required to be compatible with all browsers + { + $actioncode = ''; + $search_agenda_label = ''; + } +} + + + +/* + * View + */ + +$form = new Form($db); + +if ($object->id > 0) +{ + $title = $langs->trans("Agenda"); + //if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/',$conf->global->MAIN_HTML_TITLE) && $object->name) $title=$object->name." - ".$title; + $help_url = ''; + llxHeader('', $title, $help_url); + + if (!empty($conf->notification->enabled)) $langs->load("mails"); + $head = workstationPrepareHead($object); + + + print dol_get_fiche_head($head, 'agenda', $langs->trans("Workstation"), -1, 'mrp'); + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
'; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project') . ' '; + if ($permissiontoadd) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.=''; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
'; + print '
'; + + $object->info($object->id); + dol_print_object_info($object, 1); + + print '
'; + + print dol_get_fiche_end(); + + + + // Actions buttons + + $objthirdparty = $object; + $objcon = new stdClass(); + + $out = '&origin='.urlencode($object->element.'@'.$object->module).'&originid='.urlencode($object->id); + $urlbacktopage = $_SERVER['PHP_SELF'].'?id='.$object->id; + $out .= '&backtopage='.urlencode($urlbacktopage); + $permok = $user->rights->agenda->myactions->create; + if ((!empty($objthirdparty->id) || !empty($objcon->id)) && $permok) + { + //$out.='trans("AddAnAction"),'filenew'); + //$out.=""; + } + + + print '
'; + + if (!empty($conf->agenda->enabled)) + { + if (!empty($user->rights->agenda->myactions->create) || !empty($user->rights->agenda->allactions->create)) + { + print ''.$langs->trans("AddAction").''; + } else { + print ''.$langs->trans("AddAction").''; + } + } + + print '
'; + + if (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) + { + $param = '&id='.$object->id.'&socid='.$socid; + if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param .= '&contextpage='.urlencode($contextpage); + if ($limit > 0 && $limit != $conf->liste_limit) $param .= '&limit='.urlencode($limit); + + + //print load_fiche_titre($langs->trans("ActionsOnWorkstation"), '', ''); + + // List of all actions + $filters = array(); + $filters['search_agenda_label'] = $search_agenda_label; + + // TODO Replace this with same code than into list.php + show_actions_done($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder, $object->module); + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/workstation/workstation_card.php b/htdocs/workstation/workstation_card.php new file mode 100755 index 00000000000..e5d51b20c84 --- /dev/null +++ b/htdocs/workstation/workstation_card.php @@ -0,0 +1,504 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * 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 workstation_card.php + * \ingroup workstation + * \brief Page to create/edit/view workstation + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/resource/class/dolresource.class.php'; +dol_include_once('/workstation/class/workstation.class.php'); +dol_include_once('/workstation/lib/workstation_workstation.lib.php'); +dol_include_once('/workstation/class/workstationusergroup.class.php'); + +// Load translation files required by the page +$langs->loadLangs(array("workstation@workstation", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$confirm = GETPOST('confirm', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'workstationcard'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); +$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); +$groups = GETPOST('groups'); +$resources = GETPOST('resources'); +//$lineid = GETPOST('lineid', 'int'); + +// Initialize technical objects +$object = new Workstation($db); +//$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->workstation->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('workstationcard', 'globalcard')); // Note that conf->hooks_modules contains array + +// Fetch optionals attributes and labels +//$extrafields->fetch_name_optionals_label($object->table_element); + +//$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// Initialize array of search criterias +$search_all = GETPOST("search_all", 'alpha'); +$search = array(); +foreach ($object->fields as $key => $val) +{ + if (GETPOST('search_'.$key, 'alpha')) $search[$key] = GETPOST('search_'.$key, 'alpha'); +} + +if (empty($action) && empty($id) && empty($ref)) $action = 'view'; + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once. + +$permissiontoread = $user->rights->workstation->workstation->read; +$permissiontoadd = $user->rights->workstation->workstation->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php +$permissiontodelete = $user->rights->workstation->workstation->delete; +$permissionnote = $user->rights->workstation->workstation->write; // Used by the include of actions_setnotes.inc.php +$permissiondellink = $user->rights->workstation->workstation->write; // Used by the include of actions_dellink.inc.php +$upload_dir = $conf->workstation->multidir_output[isset($object->entity) ? $object->entity : 1]; + +// Security check - Protection if external user +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$isdraft = (($object->statut == $object::STATUS_DRAFT) ? 1 : 0); +//$result = restrictedArea($user, 'workstation', $object->id, '', '', 'fk_soc', 'rowid', $isdraft); + +if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + $error = 0; + + $backurlforlist = dol_buildpath('/workstation/workstation_list.php', 1); + + if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) $backtopage = $backurlforlist; + else $backtopage = dol_buildpath('/workstation/workstation_card.php', 1).'?id='.($id > 0 ? $id : '__ID__'); + } + } + + $triggermodname = 'WORKSTATION_WORKSTATION_MODIFY'; // Name of trigger action code to execute when we modify record + + // Actions cancel, add, update, update_extras, confirm_validate, confirm_delete, confirm_deleteline, confirm_clone, confirm_close, confirm_setdraft, confirm_reopen + include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php'; + + // Actions when linking object each other + include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; + + // Actions when printing a doc from card + include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; + + // Action to move up and down lines of object + //include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; + + // Action to build doc + include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; + + if ($action == 'confirm_enable' && $confirm == "yes" && $permissiontoadd) { + if (!empty($object->id)) $object->setStatus(1); + } elseif ($action == 'confirm_disable' && $confirm == "yes" && $permissiontoadd) { + if (!empty($object->id)) $object->setStatus(0); + } +} + + + + +/* + * View + * + * Put here all code to build page + */ + +$form = new Form($db); +$formfile = new FormFile($db); +$formresource = new FormResource($db); + +$title = $langs->trans("Workstation"); +$help_url = ''; +llxHeader('', $title, $help_url); + +// Example : Adding jquery code +?> + +trans("NewObject", $langs->transnoentitiesnoconv("Workstation")), '', 'object_'.$object->picto); + + print '
'; + print ''; + print ''; + if ($backtopage) print ''; + if ($backtopageforcancel) print ''; + + print dol_get_fiche_head(array(), ''); + + // Set some default values + //if (! GETPOSTISSET('fieldname')) $_POST['fieldname'] = 'myvalue'; + + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_add.tpl.php'; + + print ''; + print ''; + + print ''; + print ''; + + // Other attributes + //include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; + + print '
'; + print $langs->trans('Groups'); + print ''; + print img_picto('', 'group'); + print $form->select_dolgroups($groups, 'groups', 1, '', 0, '', '', $object->entity, true); + print '
'; + print $langs->trans('Machines'); + print ''; + print img_picto('', 'resource'); + print $formresource->select_resource_list($resources, 'resources', '', '', 0, '', '', $object->entity, true, 0, '', true); + print '
'."\n"; + + print dol_get_fiche_end(); + + print '
'; + print ''; + print '  '; + print ''; // Cancel for create does not post form if we don't know the backtopage + print '
'; + + print '
'; + + //dol_set_focus('input[name="ref"]'); +} + +// Part to edit record +if (($id || $ref) && $action == 'edit') +{ + print load_fiche_titre($langs->trans("Workstation"), '', 'object_'.$object->picto); + + print '
'; + print ''; + print ''; + print ''; + if ($backtopage) print ''; + if ($backtopageforcancel) print ''; + + print dol_get_fiche_head(); + + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_edit.tpl.php'; + + print ''; + print ''; + + print ''; + print ''; + + // Other attributes + //include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_edit.tpl.php'; + + print '
'; + print $langs->trans('Groups'); + print ''; + print img_picto('', 'group'); + print $form->select_dolgroups(empty($groups) ? $object->usergroups : $groups, 'groups', 1, '', 0, '', '', $object->entity, true); + print '
'; + print $langs->trans('Machines'); + print ''; + print img_picto('', 'resource'); + print $formresource->select_resource_list(empty($resources) ? $object->resources : $resources, 'resources', '', '', 0, '', '', $object->entity, true, 0, '', true); + print '
'; + + print dol_get_fiche_end(); + + print '
'; + print '   '; + print '
'; + + print '
'; +} + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) +{ + $res = $object->fetch_optionals(); + + $head = workstationPrepareHead($object); + print dol_get_fiche_head($head, 'card', $langs->trans("Workstation"), -1, $object->picto); + + $formconfirm = ''; + + // Confirmation to delete + if ($action == 'delete') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteWorkstation'), $langs->trans('ConfirmDeleteObject'), 'confirm_delete', '', 0, 1); + } + // Clone confirmation + if ($action == 'clone') { + // Create an array for form + $formquestion = array(); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneAsk', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); + } + + // Confirmation of action xxxx + if ($action == 'enable') + { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('EnableAWorkstation'), $langs->trans("ConfirmEnableWorkstation", $object->ref), 'confirm_enable', $formquestion, 0, 1, 220); + } elseif ($action == 'disable') + { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DisableAWorkstation'), $langs->trans("ConfirmDisableWorkstation", $object->ref), 'confirm_disable', $formquestion, 0, 1, 220); + } + + // Call Hook formConfirm + $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid); + $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) $formconfirm .= $hookmanager->resPrint; + elseif ($reshook > 0) $formconfirm = $hookmanager->resPrint; + + // Print form confirm + print $formconfirm; + + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
'; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref .= '
'.$langs->trans('Project') . ' '; + if ($permissiontoadd) + { + //if ($action != 'classify') $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' '; + $morehtmlref .= ' : '; + if ($action == 'classify') { + //$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref .= '
'; + $morehtmlref .= ''; + $morehtmlref .= ''; + $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref .= ''; + $morehtmlref .= '
'; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
'; + print '
'; + print '
'; + print ''."\n"; + + // Common attributes + //$keyforbreak='fieldkeytoswitchonsecondcolumn'; // We change column just before this field + //unset($object->fields['fk_project']); // Hide field already shown in banner + //unset($object->fields['fk_soc']); // Hide field already shown in banner + if ($object->type === 'MACHINE') $object->fields['nb_operators_required']['visible'] = 0; + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; + + // Groups + if ($object->type !== 'MACHINE') { + $toprint = array(); + foreach ($object->usergroups as $id_group) { + $g = new UserGroup($db); + $g->fetch($id_group); + $toprint[] = '
  • ' . $g->getNomUrl(1) . '
  • '; + } + print ''; + } + + // Resources + if ($object->type !== 'HUMAN') { + $toprint = array(); + foreach ($object->resources as $id_resource) { + $r = new Dolresource($db); + $r->fetch($id_resource); + $toprint[] = '
  • ' . $r->getNomUrl(1) . '
  • '; + } + print ''; + } + + // Other attributes. Fields from hook formObjectOptions and Extrafields. + //include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; + + print '
    ' . $langs->trans('Groups') . ''; + print '
      ' . implode(' ', $toprint) . '
    '; + print '
    ' . $langs->trans('Machines') . ''; + print '
      ' . implode(' ', $toprint) . '
    '; + print '
    '; + print '
    '; + print '
    '; + + print '
    '; + + print dol_get_fiche_end(); + + + // Buttons for actions + + if ($action != 'presend' && $action != 'editline') { + print '
    '."\n"; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + + if (empty($reshook)) + { + // Modify + if ($permissiontoadd) { + print ''.$langs->trans("Modify").''."\n"; + } else { + print ''.$langs->trans('Modify').''."\n"; + } + + // Clone + if ($permissiontoadd) { + print ''.$langs->trans("ToClone").''."\n"; + } + + + if ($permissiontoadd) + { + if ($object->status == $object::STATUS_ENABLED) { + print ''.$langs->trans("Disable").''."\n"; + } else { + print ''.$langs->trans("Enable").''."\n"; + } + } + + + // Delete (need delete permission, or if draft, just need create/modify permission) + if ($permissiontodelete) + { + print ''.$langs->trans('Delete').''."\n"; + } else { + print ''.$langs->trans('Delete').''."\n"; + } + } + print '
    '."\n"; + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/workstation/workstation_document.php b/htdocs/workstation/workstation_document.php new file mode 100755 index 00000000000..89a34f55549 --- /dev/null +++ b/htdocs/workstation/workstation_document.php @@ -0,0 +1,228 @@ + + * Copyright (C) 2020 Gauthier VERDOL + * + * 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 workstation_document.php + * \ingroup workstation + * \brief Tab for documents linked to Workstation + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +dol_include_once('/workstation/class/workstation.class.php'); +dol_include_once('/workstation/lib/workstation_workstation.lib.php'); + +// Load translation files required by the page +$langs->loadLangs(array("workstation@workstation", "companies", "other", "mails")); + + +$action = GETPOST('action', 'aZ09'); +$confirm = GETPOST('confirm'); +$id = (GETPOST('socid', 'int') ? GETPOST('socid', 'int') : GETPOST('id', 'int')); +$ref = GETPOST('ref', 'alpha'); + +// Get parameters +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST("sortfield", 'alpha'); +$sortorder = GETPOST("sortorder", 'alpha'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 +$offset = $liste_limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (!$sortorder) $sortorder = "ASC"; +if (!$sortfield) $sortfield = "name"; +//if (! $sortfield) $sortfield="position_name"; + +// Initialize technical objects +$object = new Workstation($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->workstation->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('workstationdocument', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals + +if ($id > 0 || !empty($ref)) $upload_dir = $conf->workstation->multidir_output[$object->entity ? $object->entity : $conf->entity]."/workstation/".get_exdir(0, 0, 0, 1, $object); + +// Security check - Protection if external user +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$result = restrictedArea($user, 'workstation', $object->id); + +$permissiontoadd = $user->rights->workstation->workstation->write; // Used by the include of actions_addupdatedelete.inc.php + + + +/* + * Actions + */ + +include_once DOL_DOCUMENT_ROOT.'/core/actions_linkedfiles.inc.php'; + + +/* + * View + */ + +$form = new Form($db); + +$title = $langs->trans("Workstation").' - '.$langs->trans("Files"); +$help_url = ''; +//$help_url='EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas'; +llxHeader('', $title, $help_url); + +if ($object->id) +{ + /* + * Show tabs + */ + $head = workstationPrepareHead($object); + + print dol_get_fiche_head($head, 'document', $langs->trans("Workstation"), -1, $object->picto); + + + // Build file list + $filearray = dol_dir_list($upload_dir, "files", 0, '', '(\.meta|_preview.*\.png)$', $sortfield, (strtolower($sortorder) == 'desc' ?SORT_DESC:SORT_ASC), 1); + $totalsize = 0; + foreach ($filearray as $key => $file) + { + $totalsize += $file['size']; + } + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
    '; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
    '.$langs->trans('Project') . ' '; + if ($permissiontoadd) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
    '; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
    '; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
    '; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
    '; + + print '
    '; + print ''; + + // Number of files + print ''; + + // Total size + print ''; + + print '
    '.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
    '.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
    '; + + print '
    '; + + print dol_get_fiche_end(); + + $modulepart = 'workstation'; + //$permission = $user->rights->workstation->workstation->write; + $permission = 1; + //$permtoedit = $user->rights->workstation->workstation->write; + $permtoedit = 1; + $param = '&id='.$object->id; + + //$relativepathwithnofile='workstation/' . dol_sanitizeFileName($object->id).'/'; + $relativepathwithnofile = 'workstation/'.dol_sanitizeFileName($object->ref).'/'; + + include_once DOL_DOCUMENT_ROOT.'/core/tpl/document_actions_post_headers.tpl.php'; +} else { + accessforbidden('', 0, 1); +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/workstation/workstation_list.php b/htdocs/workstation/workstation_list.php new file mode 100755 index 00000000000..996e7dc34fd --- /dev/null +++ b/htdocs/workstation/workstation_list.php @@ -0,0 +1,687 @@ + + * Copyright (C) 2020 Gauthier VERDOL + * + * 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 workstation_list.php + * \ingroup workstation + * \brief List page for workstation + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/resource/class/html.formresource.class.php'; + +// load workstation libraries +require_once __DIR__.'/class/workstation.class.php'; + +// for other modules +//dol_include_once('/othermodule/class/otherobject.class.php'); + +// Load translation files required by the page +$langs->loadLangs(array("workstation@workstation", "other")); + +$action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ... +$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) +$show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk actions ? +$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation +$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button +$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'workstationlist'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page +$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') + +$id = GETPOST('id', 'int'); + +// Load variable for pagination +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) { $page = 0; } // If $page is not defined, or '' or -1 or if we click on clear filters +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; + +// Initialize technical objects +$object = new Workstation($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->workstation->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('workstationlist')); // Note that conf->hooks_modules contains array + +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); +//$extrafields->fetch_name_optionals_label($object->table_element_line); + +$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// Default sort order (if not yet defined by previous GETPOST) +if (!$sortfield) $sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition. +if (!$sortorder) $sortorder = "ASC"; + +// Initialize array of search criterias +$search_all = GETPOST('search_all', 'alphanohtml') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'); +$search = array(); + +foreach ($object->fields as $key => $val) +{ + if (GETPOST('search_'.$key, 'alpha') !== '') $search[$key] = GETPOST('search_'.$key, 'alpha'); + if (in_array($key, array('type', 'status')) && GETPOST('search_'.$key, 'alpha') == -1) $search[$key] = ''; +} + +$groups = GETPOST('groups'); +$resources = GETPOST('resources'); + +// List of fields to search into when doing a "search in all" +$fieldstosearchall = array(); +foreach ($object->fields as $key => $val) +{ + if ($val['searchall']) $fieldstosearchall['t.'.$key] = $val['label']; +} + +// Definition of array of fields for columns +$arrayfields = array(); +foreach ($object->fields as $key => $val) +{ + // If $val['visible']==0, then we never show the field + if (!empty($val['visible'])) { + $visible = dol_eval($val['visible'], 1); + $arrayfields['t.'.$key] = array( + 'label'=>$val['label'], + 'checked'=>(($visible < 0) ? 0 : 1), + 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1)), + 'position'=>$val['position'], + 'help'=>$val['help'] + ); + } +} + +$arrayfields['wug.fk_usergroup'] = array( + 'label'=>$langs->trans('Groups'), + 'checked'=>(($visible < 0) ? 0 : 1), + 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1)), + 'position'=>1000, + 'help'=>$val['help'] +); + +$arrayfields['wr.fk_resource'] = array( + 'label'=>$langs->trans('Resources'), + 'checked'=>(($visible < 0) ? 0 : 1), + 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1)), + 'position'=>1001, + 'help'=>$val['help'] +); + +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; + +$object->fields = dol_sort_array($object->fields, 'position'); +$arrayfields = dol_sort_array($arrayfields, 'position'); + +$permissiontoread = $user->rights->workstation->workstation->read; +$permissiontoadd = $user->rights->workstation->workstation->write; +$permissiontodelete = $user->rights->workstation->workstation->delete; + +// Security check +if (empty($conf->workstation->enabled)) accessforbidden('Module not enabled'); +$socid = 0; +if ($user->socid > 0) // Protection if external user +{ + //$socid = $user->socid; + accessforbidden(); +} +//$result = restrictedArea($user, 'workstation', $id, ''); +//if (!$permissiontoread) accessforbidden(); + + + +/* + * Actions + */ + +if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; } +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; } + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + // Selection of new fields + include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) // All tests are required to be compatible with all browsers + { + foreach ($object->fields as $key => $val) + { + $search[$key] = ''; + } + $groups=$resources=array(); + $toselect = ''; + $search_array_options = array(); + } + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha') + || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) + { + $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation + } + + // Mass actions + $objectclass = 'Workstation'; + $objectlabel = 'Workstation'; + $uploaddir = $conf->workstation->dir_output; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; +} + + + +/* + * View + */ + +$form = new Form($db); +$formresource = new FormResource($db); + +$now = dol_now(); + +//$help_url="EN:Module_Workstation|FR:Module_Workstation_FR|ES:Módulo_Workstation"; +$help_url = ''; +$title = $langs->trans('ListOf', $langs->transnoentitiesnoconv("Workstations")); + + +// Build and execute select +// -------------------------------------------------------------------- +$sql = 'SELECT '; +foreach ($object->fields as $key => $val) +{ + $sql .= 't.'.$key.', '; +} +// Add fields from extrafields +if (!empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.' as options_'.$key.', ' : ''); +} +// Add fields from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= preg_replace('/^,/', '', $hookmanager->resPrint); +$sql = preg_replace('/,\s*$/', '', $sql); +$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; +if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; +if (!empty($groups)) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'workstation_workstation_usergroup wug ON (wug.fk_workstation = t.rowid)'; +if (!empty($resources)) $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'workstation_workstation_resource wr ON (wr.fk_workstation = t.rowid)'; +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; +if ($object->ismultientitymanaged == 1) $sql .= " WHERE t.entity IN (".getEntity($object->element).")"; +else $sql .= " WHERE 1 = 1"; +foreach ($search as $key => $val) +{ + if ($key == 'status' && $search[$key] == -1) continue; + $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0); + if (strpos($object->fields[$key]['type'], 'integer:') === 0) { + if ($search[$key] == '-1') $search[$key] = ''; + $mode_search = 2; + } + if ($search[$key] != '') $sql .= natural_search($key, $search[$key], (($key == 'status') ? 2 : $mode_search)); +} +if ($search_all) $sql .= natural_search(array_keys($fieldstosearchall), $search_all); +//$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear); +// Add where from extra fields + +// usergroups +if (!empty($groups)) $sql.= ' AND wug.fk_usergroup IN('.implode(',', $groups).')'; + +// resources +if (!empty($resources)) $sql.= ' AND wr.fk_resource IN('.implode(',', $resources).')'; + +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; +// Add where from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; + +/* If a group by is required +$sql.= " GROUP BY "; +foreach($object->fields as $key => $val) +{ + $sql.='t.'.$key.', '; +} +// Add fields from extrafields +if (! empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) $sql.=($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : ''); +} +// Add where from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListGroupBy',$parameters, $object); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; +$sql=preg_replace('/,\s*$/','', $sql); +*/ +$sql.= ' GROUP BY t.rowid'; +$sql .= $db->order($sortfield, $sortorder); + +// Count total nb of records +$nbtotalofrecords = ''; +if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) +{ + $resql = $db->query($sql); + $nbtotalofrecords = $db->num_rows($resql); + if (($page * $limit) > $nbtotalofrecords) // if total of record found is smaller than page * limit, goto and load page 0 + { + $page = 0; + $offset = 0; + } +} +// if total of record found is smaller than limit, no need to do paging and to restart another select with limits set. +if (is_numeric($nbtotalofrecords) && ($limit > $nbtotalofrecords || empty($limit))) +{ + $num = $nbtotalofrecords; +} else { + if ($limit) $sql .= $db->plimit($limit + 1, $offset); + + $resql = $db->query($sql); + if (!$resql) + { + dol_print_error($db); + exit; + } + + $num = $db->num_rows($resql); +} + +// Direct jump if only one record found +if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all && !$page) +{ + $obj = $db->fetch_object($resql); + $id = $obj->rowid; + header("Location: ".dol_buildpath('/workstation/workstation_card.php', 1).'?id='.$id); + exit; +} + + +// Output page +// -------------------------------------------------------------------- + +llxHeader('', $title, $help_url); + +// Example : Adding jquery code +print ''; + +$arrayofselected = is_array($toselect) ? $toselect : array(); + +$param = ''; +if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param .= '&contextpage='.urlencode($contextpage); +if ($limit > 0 && $limit != $conf->liste_limit) $param .= '&limit='.urlencode($limit); +foreach ($search as $key => $val) +{ + if (is_array($search[$key]) && count($search[$key])) foreach ($search[$key] as $skey) $param .= '&search_'.$key.'[]='.urlencode($skey); + else $param .= '&search_'.$key.'='.urlencode($search[$key]); +} +if ($optioncss != '') $param .= '&optioncss='.urlencode($optioncss); +// Add $param from extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; +// Add $param from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook +$param .= $hookmanager->resPrint; + +// List of mass actions available +$arrayofmassactions = array( + //'validate'=>$langs->trans("Validate"), + //'generate_doc'=>$langs->trans("ReGeneratePDF"), + //'builddoc'=>$langs->trans("PDFMerge"), + //'presend'=>$langs->trans("SendByMail"), +); +if ($permissiontodelete) $arrayofmassactions['predelete'] = ''.$langs->trans("Delete"); +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) $arrayofmassactions = array(); +$massactionbutton = $form->selectMassAction('', $arrayofmassactions); + +print '
    '."\n"; +if ($optioncss != '') print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/workstation/workstation_card.php', 1).'?action=create&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd); + +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'object_'.$object->picto, 0, $newcardbutton, '', $limit, 0, 0, 1); + +// Add code for pre mass action (confirmation or email presend form) +$topicmail = "SendWorkstationRef"; +$modelmail = "workstation"; +$objecttmp = new Workstation($db); +$trackid = 'xxxx'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; + +if ($search_all) +{ + foreach ($fieldstosearchall as $key => $val) $fieldstosearchall[$key] = $langs->trans($val); + print '
    '.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
    '; +} + +$moreforfilter = ''; +/*$moreforfilter.='
    '; +$moreforfilter.= $langs->trans('MyFilter') . ': '; +$moreforfilter.= '
    ';*/ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +if (empty($reshook)) $moreforfilter .= $hookmanager->resPrint; +else $moreforfilter = $hookmanager->resPrint; + +if (!empty($moreforfilter)) +{ + print '
    '; + print $moreforfilter; + print '
    '; +} + +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); + +print '
    '; // You can use div-table-responsive-no-min if you dont need reserved height for your table +print ''."\n"; + + +// Fields title search +// -------------------------------------------------------------------- + +print ''; +foreach ($object->fields as $key => $val) +{ + $cssforfield = (empty($val['css']) ? '' : $val['css']); + if ($key == 'status') $cssforfield .= ($cssforfield ? ' ' : '').'center'; + elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) $cssforfield .= ($cssforfield ? ' ' : '').'center'; + elseif (in_array($val['type'], array('timestamp'))) $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID') $cssforfield .= ($cssforfield ? ' ' : '').'right'; + if (!empty($arrayfields['t.'.$key]['checked'])) + { + print ''; + } +} + +// usergroups +if (!empty($arrayfields['wug.fk_usergroup']['checked'])) { + print ''; +} + +// resources +if (!empty($arrayfields['wr.fk_resource']['checked'])) { + print ''; +} + +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; + +// Fields from hook +$parameters = array('arrayfields'=>$arrayfields); +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column +print ''; +print ''."\n"; + + +// Fields title label +// -------------------------------------------------------------------- +print ''; +foreach ($object->fields as $key => $val) +{ + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if ($key == 'status') $cssforfield .= ($cssforfield ? ' ' : '').'center'; + elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) $cssforfield .= ($cssforfield ? ' ' : '').'center'; + elseif (in_array($val['type'], array('timestamp'))) $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID') $cssforfield .= ($cssforfield ? ' ' : '').'right'; + if (!empty($arrayfields['t.'.$key]['checked'])) + { + print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''))."\n"; + } +} + +// usergroups +if (!empty($arrayfields['wug.fk_usergroup']['checked'])) { + print getTitleFieldOfList($arrayfields['wug.fk_usergroup']['label'], 0, $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, '') . "\n"; +} + +// resources +if (!empty($arrayfields['wr.fk_resource']['checked'])) { + print getTitleFieldOfList($arrayfields['wr.fk_resource']['label'], 0, $_SERVER['PHP_SELF'], '', '', $param, '', $sortfield, $sortorder, '') . "\n"; +} + +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; +// Hook fields +$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column +print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +print ''."\n"; + + +// Detect if we need a fetch on each output line +$needToFetchEachLine = 0; +if (is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) +{ + foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) + { + if (preg_match('/\$object/', $val)) $needToFetchEachLine++; // There is at least one compute field that use $object + } +} + + +// Loop on record +// -------------------------------------------------------------------- +$i = 0; +$totalarray = array(); +while ($i < ($limit ? min($num, $limit) : $num)) +{ + $obj = $db->fetch_object($resql); + if (empty($obj)) break; // Should not happen + + // Store properties in $object + $object->setVarsFromFetchObj($obj); + $object->usergroups = WorkstationUserGroup::getAllGroupsOfWorkstation($obj->rowid); + $object->resources = WorkstationResource::getAllResourcesOfWorkstation($obj->rowid); + + // Show here line of result + print ''; + foreach ($object->fields as $key => $val) + { + $cssforfield = (empty($val['css']) ? '' : $val['css']); + if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) $cssforfield .= ($cssforfield ? ' ' : '').'center'; + elseif ($key == 'status') $cssforfield .= ($cssforfield ? ' ' : '').'center'; + + if (in_array($val['type'], array('timestamp'))) $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + elseif ($key == 'ref') $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + + if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status'))) $cssforfield .= ($cssforfield ? ' ' : '').'right'; + //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; + + if (!empty($arrayfields['t.'.$key]['checked'])) + { + print ''; + if ($key == 'status') print $object->getLibStatut(5); + else print $object->showOutputField($val, $key, $object->$key, ''); + print ''; + if (!$i) $totalarray['nbfield']++; + if (!empty($val['isameasure'])) + { + if (!$i) $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; + $totalarray['val']['t.'.$key] += $object->$key; + } + } + } + + if (!empty($arrayfields['wug.fk_usergroup']['checked'])) { + $toprint = array(); + foreach ($object->usergroups as $id_group) { + $g = new UserGroup($db); + $g->fetch($id_group); + $toprint[] = '
  • ' . $g->getNomUrl(1) . '
  • '; + } + print '
    '; + } + + if (!empty($arrayfields['wr.fk_resource']['checked'])) { + $toprint = array(); + foreach ($object->resources as $id_resource) { + $r = new Dolresource($db); + $r->fetch($id_resource); + $toprint[] = '
  • ' . $r->getNomUrl(1) . '
  • '; + } + print ''; + } + + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Action column + print ''; + if (!$i) $totalarray['nbfield']++; + + print ''."\n"; + + $i++; +} + +// Show total line +include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + +// If no record found +if ($num == 0) +{ + $colspan = 1; + foreach ($arrayfields as $key => $val) { if (!empty($val['checked'])) $colspan++; } + print ''; +} + + +$db->free($resql); + +$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print '
    '; + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) print $form->selectarray('search_'.$key, $val['arrayofkeyval'], $search[$key], $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); + elseif (strpos($val['type'], 'integer:') === 0) { + print $object->showInputField($val, $key, $search[$key], '', '', 'search_', 'maxwidth125', 1); + } elseif (!preg_match('/^(date|timestamp)/', $val['type'])) print ''; + print ''; + print $form->select_dolgroups($groups, 'groups', 1, '', 0, '', '', $conf->entity, true); + print ''; + print $formresource->select_resource_list($resources, 'resources', '', '', 0, '', '', $conf->entity, true, 0, '', true); + print ''; +$searchpicto = $form->showFilterButtons(); +print $searchpicto; +print '
    '; + print '
      ' . implode(' ', $toprint) . '
    '; + print '
    '; + print '
      ' . implode(' ', $toprint) . '
    '; + print '
    '; + if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + { + $selected = 0; + if (in_array($object->id, $arrayofselected)) $selected = 1; + print ''; + } + print '
    '.$langs->trans("NoRecordFound").'
    '."\n"; +print '
    '."\n"; + +print '
    '."\n"; + +if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $nbtotalofrecords)) +{ + $hidegeneratedfilelistifempty = 1; + if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) $hidegeneratedfilelistifempty = 0; + + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; + $formfile = new FormFile($db); + + // Show list of available documents + $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder; + $urlsource .= str_replace('&', '&', $param); + + $filedir = $diroutputmassaction; + $genallowed = $permissiontoread; + $delallowed = $permissiontoadd; + + print $formfile->showdocuments('massfilesarea_workstation', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/workstation/workstation_note.php b/htdocs/workstation/workstation_note.php new file mode 100755 index 00000000000..a9d8a7f3fc2 --- /dev/null +++ b/htdocs/workstation/workstation_note.php @@ -0,0 +1,183 @@ + + * Copyright (C) 2020 Gauthier VERDOL + * + * 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 workstation_note.php + * \ingroup workstation + * \brief Tab for notes on Workstation + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +dol_include_once('/workstation/class/workstation.class.php'); +dol_include_once('/workstation/lib/workstation_workstation.lib.php'); + +// Load translation files required by the page +$langs->loadLangs(array("workstation@workstation", "companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object = new Workstation($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->workstation->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('workstationnote', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Security check - Protection if external user +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$result = restrictedArea($user, 'workstation', $id); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) $upload_dir = $conf->workstation->multidir_output[$object->entity]."/".$object->id; + +$permissionnote = $user->rights->workstation->workstation->write; // Used by the include of actions_setnotes.inc.php +$permissiontoadd = $user->rights->workstation->workstation->write; // Used by the include of actions_addupdatedelete.inc.php + + + +/* + * Actions + */ + +include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not include_once + + +/* + * View + */ + +$form = new Form($db); + +//$help_url='EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes'; +$help_url = ''; +llxHeader('', $langs->trans('Workstation'), $help_url); + +if ($id > 0 || !empty($ref)) +{ + $object->fetch_thirdparty(); + + $head = workstationPrepareHead($object); + + print dol_get_fiche_head($head, 'note', $langs->trans("Workstation"), -1, $object->picto); + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
    '; + /* + // Ref customer + $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, 0, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
    '.$langs->trans('Project') . ' '; + if ($permissiontoadd) + { + if ($action != 'classify') + //$morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + $morehtmlref.=' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
    '; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
    '; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref .= ': '.$proj->getNomUrl(); + } else { + $morehtmlref .= ''; + } + } + }*/ + $morehtmlref .= '
    '; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
    '; + print '
    '; + + + $cssclass = "titlefield"; + include DOL_DOCUMENT_ROOT.'/core/tpl/notes.tpl.php'; + + print '
    '; + + print dol_get_fiche_end(); +} + +// End of page +llxFooter(); +$db->close();