diff --git a/ChangeLog b/ChangeLog index 7b8e29d04e0..3cfc257bbb2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,7 @@ NEW: Add a payment module for Stripe. NEW: Add module "Product variant" (like red, blue for the product shoes) NEW: Accountancy - Activate multi-journal & Add journal_label to database (FEC) NEW: Add a tracking id into mass emailing. +NEW: Tax system more compatible with the new tax roollout in India (IGST / CGST / SGST). NEW: Add calculation function for Loan schedule NEW: Add "depends on" and "required by" into module informations NEW: Add hidden option THIRDPARTY_INCLUDE_PARENT_IN_LINKTO diff --git a/build/exe/doliwamp/doliwamp.iss b/build/exe/doliwamp/doliwamp.iss index 34757a5123a..2ef8ab32f22 100644 --- a/build/exe/doliwamp/doliwamp.iss +++ b/build/exe/doliwamp/doliwamp.iss @@ -353,10 +353,12 @@ begin begin // TODO Copy file or ask to install package ? //CustomMessage('YouWillInstallDoliWamp')+#13#13 - MsgBox('The package vcredist_x86.exe must have been installed first. It seems it is not. Please install it first from http://www.microsoft.com/en-us/download/details.aspx?id=30679 then restart DoliWamp installation/upgrade.',mbInformation,MB_OK); + MsgBox('The package vcredist_x86.exe must have been installed first. It seems it is not. Please install it first from http://www.microsoft.com/en-us/download/details.aspx?id=30679 then restart DoliWamp installation/upgrade.',mbInformation,MB_OK); end; - - + // Pb seems similar with msvcp110.dll + //vcredist_x64.exe + + // If we have a new database version, we should only copy old my.ini file into new directory // and change only all basedir= strings to use new version. Like this, data dir is still correct. // Install of service and stop/start scripts are already rebuild by installer. diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index 41b54022ee4..1843f3c8cfd 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -592,6 +592,8 @@ if ($nboftargetok) { print "Remove subdir of custom dir\n"; print "find $BUILDROOT/$PROJECT/htdocs/custom/* -type d -exec rm -fr {} \\;\n"; $ret=`find $BUILDROOT/$PROJECT/htdocs/custom/* -type d -exec rm -fr {} \\; >/dev/null 2>&1`; # For custom we want to remove all subdirs but not files + print "find $BUILDROOT/$PROJECT/htdocs/custom/* -type l -exec rm -fr {} \\;\n"; + $ret=`find $BUILDROOT/$PROJECT/htdocs/custom/* -type l -exec rm -fr {} \\; >/dev/null 2>&1`; # For custom we want to remove all subdirs, even symbolic links, but not files } # Build package for each target diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 1431df9f8a2..799ebf85a34 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -71,6 +71,7 @@ class BookKeeping extends CommonObject /** */ public $doc_date; + public $date_lim_reglement; public $doc_type; public $doc_ref; public $fk_doc; @@ -255,6 +256,7 @@ class BookKeeping extends CommonObject $sql = "INSERT INTO " . MAIN_DB_PREFIX . $this->table_element . " ("; $sql .= "doc_date"; + $sql .= ", date_lim_reglement"; $sql .= ", doc_type"; $sql .= ", doc_ref"; $sql .= ", fk_doc"; @@ -277,6 +279,7 @@ class BookKeeping extends CommonObject $sql .= ', entity'; $sql .= ") VALUES ("; $sql .= "'" . $this->db->idate($this->doc_date) . "'"; + $sql .= ",'" . $this->db->idate($this->date_lim_reglement) . "'"; $sql .= ",'" . $this->db->escape($this->doc_type) . "'"; $sql .= ",'" . $this->db->escape($this->doc_ref) . "'"; $sql .= "," . $this->fk_doc; @@ -444,6 +447,7 @@ class BookKeeping extends CommonObject // Insert request $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . $mode.'('; $sql .= 'doc_date,'; + $sql .= 'date_lim_reglement,'; $sql .= 'doc_type,'; $sql .= 'doc_ref,'; $sql .= 'fk_doc,'; @@ -466,6 +470,7 @@ class BookKeeping extends CommonObject $sql .= 'entity'; $sql .= ') VALUES ('; $sql .= ' ' . (! isset($this->doc_date) || dol_strlen($this->doc_date) == 0 ? 'NULL' : "'" . $this->db->idate($this->doc_date) . "'") . ','; + $sql .= ' ' . (! isset($this->date_lim_reglement) || dol_strlen($this->date_lim_reglement) == 0 ? 'NULL' : "'" . $this->db->idate($this->date_lim_reglement) . "'") . ','; $sql .= ' ' . (! isset($this->doc_type) ? 'NULL' : "'" . $this->db->escape($this->doc_type) . "'") . ','; $sql .= ' ' . (! isset($this->doc_ref) ? 'NULL' : "'" . $this->db->escape($this->doc_ref) . "'") . ','; $sql .= ' ' . (empty($this->fk_doc) ? '0' : $this->fk_doc) . ','; @@ -540,6 +545,7 @@ class BookKeeping extends CommonObject $sql = 'SELECT'; $sql .= ' t.rowid,'; $sql .= " t.doc_date,"; + $sql .= " t.date_lim_reglement,"; $sql .= " t.doc_type,"; $sql .= " t.doc_ref,"; $sql .= " t.fk_doc,"; @@ -577,6 +583,7 @@ class BookKeeping extends CommonObject $this->id = $obj->rowid; $this->doc_date = $this->db->jdate($obj->doc_date); + $this->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement); $this->doc_type = $obj->doc_type; $this->doc_ref = $obj->doc_ref; $this->fk_doc = $obj->fk_doc; @@ -1260,7 +1267,7 @@ class BookKeeping extends CommonObject global $user; $error = 0; - $object = new Accountingbookkeeping($this->db); + $object = new BookKeeping($this->db); $this->db->begin(); diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index d5746eb63e5..587d36d227a 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -401,7 +401,7 @@ if (! $error && $action == 'writebookkeeping') { $bookkeeping->numero_compte = $k; $bookkeeping->label_operation = $val["label"]; $bookkeeping->label_compte = $langs->trans("Bank"); - $bookkeeping->montant = ($mt < 0 ? - $mt : $mt); + $bookkeeping->montant = $mt; $bookkeeping->sens = ($mt >= 0) ? 'D' : 'C'; $bookkeeping->debit = ($mt >= 0 ? $mt : 0); $bookkeeping->credit = ($mt < 0 ? - $mt : 0); @@ -462,7 +462,7 @@ if (! $error && $action == 'writebookkeeping') { $bookkeeping->fk_doc = $key; $bookkeeping->fk_docdet = $val["fk_bank"]; $bookkeeping->label_operation = $tabcompany[$key]['name']; - $bookkeeping->montant = ($mt < 0 ? - $mt : $mt); + $bookkeeping->montant = $mt; $bookkeeping->sens = ($mt < 0) ? 'D' : 'C'; $bookkeeping->debit = ($mt < 0 ? - $mt : 0); $bookkeeping->credit = ($mt >= 0) ? $mt : 0; diff --git a/htdocs/accountancy/journal/expensereportsjournal.php b/htdocs/accountancy/journal/expensereportsjournal.php index 1907cfe7dae..d253fb2820a 100644 --- a/htdocs/accountancy/journal/expensereportsjournal.php +++ b/htdocs/accountancy/journal/expensereportsjournal.php @@ -203,7 +203,7 @@ if ($action == 'writebookkeeping') { $bookkeeping->label_operation = $tabuser[$key]['name']; $bookkeeping->montant = $mt; $bookkeeping->sens = ($mt >= 0) ? 'C' : 'D'; - $bookkeeping->debit = ($mt <= 0) ? $mt : 0; + $bookkeeping->debit = ($mt <= 0) ? -$mt : 0; $bookkeeping->credit = ($mt > 0) ? $mt : 0; $bookkeeping->code_journal = $journal; $bookkeeping->journal_label = $journal_label; diff --git a/htdocs/accountancy/journal/purchasesjournal.php b/htdocs/accountancy/journal/purchasesjournal.php index 40b9033002c..b095e4650dc 100644 --- a/htdocs/accountancy/journal/purchasesjournal.php +++ b/htdocs/accountancy/journal/purchasesjournal.php @@ -85,7 +85,7 @@ if (empty($date_start) || empty($date_end)) // We define date_start and date_end $idpays = $mysoc->country_id; -$sql = "SELECT f.rowid, f.ref, f.type, f.datef as df, f.libelle,f.ref_supplier,"; +$sql = "SELECT f.rowid, f.ref, f.type, f.datef as df, f.libelle,f.ref_supplier, f.date_lim_reglement as dlf, "; $sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.tva as total_tva, fd.total_localtax1, fd.total_localtax2, fd.tva_tx, fd.total_ttc, fd.vat_src_code,"; $sql .= " s.rowid as socid, s.nom as name, s.fournisseur, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,"; $sql .= " p.accountancy_code_buy , aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte"; @@ -155,6 +155,7 @@ if ($result) { } $tabfac[$obj->rowid]["date"] = $db->jdate($obj->df); + $tabfac[$obj->rowid]["datereg"] = $db->jdate($obj->dlr); $tabfac[$obj->rowid]["ref"] = $obj->ref_supplier . ' (' . $obj->ref . ')'; $tabfac[$obj->rowid]["refsologest"] = $obj->ref; $tabfac[$obj->rowid]["refsuppliersologest"] = $obj->ref_supplier; @@ -222,6 +223,7 @@ if ($action == 'writebookkeeping') { if ($mt) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; $bookkeeping->doc_ref = $val["ref"]; $bookkeeping->date_create = $now; $bookkeeping->doc_type = 'supplier_invoice'; @@ -269,6 +271,7 @@ if ($action == 'writebookkeeping') { if ($accountingaccount->fetch(null, $k, true)) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; $bookkeeping->doc_ref = $val["ref"]; $bookkeeping->date_create = $now; $bookkeeping->doc_type = 'supplier_invoice'; @@ -322,6 +325,7 @@ if ($action == 'writebookkeeping') { if ($mt) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; $bookkeeping->doc_ref = $val["ref"]; $bookkeeping->date_create = $now; $bookkeeping->doc_type = 'supplier_invoice'; diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index 4300b91eca6..c03c800f5d6 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -89,7 +89,7 @@ if (empty($date_start) || empty($date_end)) // We define date_start and date_end $idpays = $mysoc->country_id; -$sql = "SELECT f.rowid, f.facnumber, f.type, f.datef as df, f.ref_client,"; +$sql = "SELECT f.rowid, f.facnumber, f.type, f.datef as df, f.ref_client, f.date_lim_reglement as dlr,"; $sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.total_tva, fd.total_localtax1, fd.total_localtax2, fd.tva_tx, fd.total_ttc, fd.situation_percent, fd.vat_src_code,"; $sql .= " s.rowid as socid, s.nom as name, s.code_client, s.code_fournisseur, s.code_compta, s.code_compta_fournisseur,"; $sql .= " p.rowid as pid, p.ref as pref, p.accountancy_code_sell, aa.rowid as fk_compte, aa.account_number as compte, aa.label as label_compte"; @@ -178,6 +178,7 @@ if ($result) { // Invoice lines $tabfac[$obj->rowid]["date"] = $db->jdate($obj->df); + $tabfac[$obj->rowid]["datereg"] = $db->jdate($obj->dlr); $tabfac[$obj->rowid]["ref"] = $obj->facnumber; $tabfac[$obj->rowid]["type"] = $obj->type; $tabfac[$obj->rowid]["description"] = $obj->label_compte; @@ -240,6 +241,7 @@ if ($action == 'writebookkeeping') { if ($mt) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; $bookkeeping->doc_ref = $val["ref"]; $bookkeeping->date_create = $now; $bookkeeping->doc_type = 'customer_invoice'; @@ -287,6 +289,7 @@ if ($action == 'writebookkeeping') { if ($accountingaccount->fetch(null, $k, true)) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; $bookkeeping->doc_ref = $val["ref"]; $bookkeeping->date_create = $now; $bookkeeping->doc_type = 'customer_invoice'; @@ -340,6 +343,7 @@ if ($action == 'writebookkeeping') { if ($mt) { $bookkeeping = new BookKeeping($db); $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; $bookkeeping->doc_ref = $val["ref"]; $bookkeeping->date_create = $now; $bookkeeping->doc_type = 'customer_invoice'; diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index ecf95c5096d..60855c42d58 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -43,23 +43,23 @@ require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; class Categorie extends CommonObject { // Categories types - const TYPE_PRODUCT = 0; // TODO Replace with value 'product' - const TYPE_SUPPLIER = 1; // TODO Replace this value with 'supplier' - const TYPE_CUSTOMER = 2; // TODO Replace this value with 'customer' - const TYPE_MEMBER = 3; // TODO Replace this value with 'member' - const TYPE_CONTACT = 4; // TODO Replace this value with 'contact' - const TYPE_USER = 4; // categorie contact and user are same ! TODO Replace this value with 'user' - - const TYPE_ACCOUNT = 5; // TODO Replace this value with 'bank_account' - const TYPE_PROJECT = 6; // TODO Replace this value with 'project' + const TYPE_PRODUCT = 'product'; + const TYPE_SUPPLIER = 'supplier'; + const TYPE_CUSTOMER = 'customer'; + const TYPE_MEMBER = 'member'; + const TYPE_CONTACT = 'contact'; + const TYPE_USER = 'user'; + const TYPE_PROJECT = 'project'; + const TYPE_ACCOUNT = 'bank_account'; const TYPE_BANK_LINE = 'bank_line'; + public $picto = 'category'; /** * @var array ID mapping from type string * - * @note This array should be remove in future, once previous constants are moved to the string value. + * @note This array should be remove in future, once previous constants are moved to the string value. Deprecated */ private $MAP_ID = array( 'product' => 0, @@ -67,10 +67,21 @@ class Categorie extends CommonObject 'customer' => 2, 'member' => 3, 'contact' => 4, - 'user' => 4, 'account' => 5, 'project' => 6, + 'user' => 7, ); + public static $MAP_ID_TO_CODE = array( + 0 => 'product', + 1 => 'supplier', + 2 => 'customer', + 3 => 'member', + 4 => 'contact', + 5 => 'account', + 6 => 'project', + 7 => 'user', + ); + /** * @var array Foreign keys mapping from type string * @@ -82,9 +93,9 @@ class Categorie extends CommonObject 'supplier' => 'soc', 'member' => 'member', 'contact' => 'socpeople', - 'user' => 'user', - 'account' => 'account', - 'project' => 'project', + 'user' => 'user', + 'account' => 'account', + 'project' => 'project', ); /** * @var array Category tables mapping from type string @@ -97,9 +108,9 @@ class Categorie extends CommonObject 'supplier' => 'fournisseur', 'member' => 'member', 'contact' => 'contact', - 'user' => 'user', - 'account' => 'account', - 'project' => 'project', + 'user' => 'user', + 'account' => 'account', + 'project' => 'project', ); /** * @var array Object class mapping from type string @@ -113,8 +124,8 @@ class Categorie extends CommonObject 'member' => 'Adherent', 'contact' => 'Contact', 'user' => 'User', - 'account' => 'Account', - 'project' => 'Project', + 'account' => 'Account', + 'project' => 'Project', ); /** * @var array Object table mapping from type string @@ -128,8 +139,8 @@ class Categorie extends CommonObject 'member' => 'adherent', 'contact' => 'socpeople', 'user' => 'user', - 'account' => 'bank_account', - 'project' => 'projet', + 'account' => 'bank_account', + 'project' => 'projet', ); public $element='category'; diff --git a/htdocs/categories/index.php b/htdocs/categories/index.php index ea4d60e9b5b..c751fad67a7 100644 --- a/htdocs/categories/index.php +++ b/htdocs/categories/index.php @@ -39,6 +39,8 @@ $id=GETPOST('id','int'); $type=(GETPOST('type','aZ09') ? GETPOST('type','aZ09') : Categorie::TYPE_PRODUCT); $catname=GETPOST('catname','alpha'); +if (is_numeric($type)) $type=Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility + /* * View @@ -53,8 +55,8 @@ elseif ($type == Categorie::TYPE_CUSTOMER) { $title=$langs->trans("CustomersCat elseif ($type == Categorie::TYPE_MEMBER) { $title=$langs->trans("MembersCategoriesArea"); $typetext='member'; } elseif ($type == Categorie::TYPE_CONTACT) { $title=$langs->trans("ContactsCategoriesArea"); $typetext='contact'; } elseif ($type == Categorie::TYPE_ACCOUNT) { $title=$langs->trans("AccountsCategoriesArea"); $typetext='account'; } -elseif ($type == Categorie::TYPE_USER) { $title=$langs->trans("UsersCategoriesArea"); $typetext='user'; } elseif ($type == Categorie::TYPE_PROJECT) { $title=$langs->trans("ProjectsCategoriesArea"); $typetext='project'; } +elseif ($type == Categorie::TYPE_USER) { $title=$langs->trans("UsersCategoriesArea"); $typetext='user'; } else { $title=$langs->trans("CategoriesArea"); $typetext='unknown'; } $arrayofjs=array('/includes/jquery/plugins/jquerytreeview/jquery.treeview.js', '/includes/jquery/plugins/jquerytreeview/lib/jquery.cookie.js'); diff --git a/htdocs/categories/photos.php b/htdocs/categories/photos.php index e99e081e015..e6047ed2149 100644 --- a/htdocs/categories/photos.php +++ b/htdocs/categories/photos.php @@ -42,6 +42,8 @@ $type=GETPOST('type'); $action=GETPOST('action','aZ09'); $confirm=GETPOST('confirm'); +if (is_numeric($type)) $type=Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility + if ($id == "") { dol_print_error('','Missing parameter id'); @@ -100,15 +102,16 @@ if ($object->id) elseif ($type == Categorie::TYPE_CONTACT) $title=$langs->trans("ContactCategoriesShort"); elseif ($type == Categorie::TYPE_ACCOUNT) $title=$langs->trans("AccountsCategoriesShort"); elseif ($type == Categorie::TYPE_PROJECT) $title=$langs->trans("ProjectsCategoriesShort"); - else $title=$langs->trans("Category"); + elseif ($type == Categorie::TYPE_USER) $title=$langs->trans("UsersCategoriesShort"); + else $title=$langs->trans("Category"); $head = categories_prepare_head($object,$type); dol_fiche_head($head, 'photos', $title, -1, 'category'); - + $linkback = ''.$langs->trans("BackToList").''; - + $object->ref = $object->label; $morehtmlref='
'.$langs->trans("Root").' >> '; $ways = $object->print_all_ways(" >> ", '', 1); @@ -117,9 +120,9 @@ if ($object->id) $morehtmlref.=$way."
\n"; } $morehtmlref.='
'; - + dol_banner_tab($object, 'ref', $linkback, ($user->societe_id?0:1), 'ref', 'ref', $morehtmlref, '', 0, '', '', 1); - + /* * Confirmation de la suppression de photo */ @@ -129,7 +132,7 @@ if ($object->id) } print '
'; - + print '
'; print '
'; print ''; @@ -148,7 +151,7 @@ if ($object->id) print "
\n"; print '
'; - + print dol_fiche_end(); @@ -258,7 +261,7 @@ if ($object->id) } print ''; - + if ($nbphoto < 1) { print '
'.$langs->trans("NoPhotoYet")."
"; diff --git a/htdocs/categories/traduction.php b/htdocs/categories/traduction.php index 7dbe6325e1d..40b40eab921 100644 --- a/htdocs/categories/traduction.php +++ b/htdocs/categories/traduction.php @@ -35,11 +35,13 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; $langs->load("categories"); $langs->load("languages"); -$id = GETPOST('id', 'int'); -$ref = GETPOST('ref', 'alpha'); -$action=GETPOST('action','alpha'); -$cancel=GETPOST('cancel','alpha'); -$type=GETPOST('type'); +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action','alpha'); +$cancel = GETPOST('cancel','alpha'); +$type = GETPOST('type','aZ09'); + +if (is_numeric($type)) $type=Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility // Security check $fieldvalue = (! empty($id) ? $id : (! empty($ref) ? $ref : '')); @@ -153,6 +155,7 @@ elseif ($type == Categorie::TYPE_MEMBER) $title=$langs->trans("MembersCategor elseif ($type == Categorie::TYPE_CONTACT) $title=$langs->trans("ContactCategoriesShort"); elseif ($type == Categorie::TYPE_ACCOUNT) $title=$langs->trans("AccountsCategoriesShort"); elseif ($type == Categorie::TYPE_PROJECT) $title=$langs->trans("ProjectsCategoriesShort"); +elseif ($type == Categorie::TYPE_USER) $title=$langs->trans("UsersCategoriesShort"); else $title=$langs->trans("Category"); $head = categories_prepare_head($object,$type); @@ -256,9 +259,9 @@ if ($action == 'edit') print ''; } } - + print '
'; - + print '
'; print ''; print '     '; @@ -271,7 +274,7 @@ if ($action == 'edit') else if ($action != 'add') { if ($cnt_trans) print '
'; - + if (! empty($object->multilangs)) { foreach ($object->multilangs as $key => $value) diff --git a/htdocs/categories/viewcat.php b/htdocs/categories/viewcat.php index 1c6186d5df4..75a9215e18d 100644 --- a/htdocs/categories/viewcat.php +++ b/htdocs/categories/viewcat.php @@ -34,13 +34,13 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; $langs->load("categories"); -$id=GETPOST('id','int'); -$label=GETPOST('label'); -$type=GETPOST('type'); +$id = GETPOST('id','int'); +$label= GETPOST('label','alpha'); +$type = GETPOST('type','az09'); $action=GETPOST('action','aZ09'); -$confirm=GETPOST('confirm'); +$confirm = GETPOST('confirm','alpha'); $removeelem = GETPOST('removeelem','int'); -$elemid=GETPOST('elemid'); +$elemid = GETPOST('elemid','alpha'); if ($id == "" && $label == "") { @@ -61,6 +61,7 @@ if ($result <= 0) } $type=$object->type; +if (is_numeric($type)) $type=Categorie::$MAP_ID_TO_CODE[$type]; // For backward compatibility $extrafields = new ExtraFields($db); $extralabels = $extrafields->fetch_name_optionals_label($object->table_element); @@ -187,6 +188,7 @@ elseif ($type == Categorie::TYPE_MEMBER) $title=$langs->trans("MembersCategor elseif ($type == Categorie::TYPE_CONTACT) $title=$langs->trans("ContactCategoriesShort"); elseif ($type == Categorie::TYPE_ACCOUNT) $title=$langs->trans("AccountsCategoriesShort"); elseif ($type == Categorie::TYPE_PROJECT) $title=$langs->trans("ProjectsCategoriesShort"); +elseif ($type == Categorie::TYPE_USER) $title=$langs->trans("ProjectsCategoriesShort"); else $title=$langs->trans("Category"); $head = categories_prepare_head($object,$type); diff --git a/htdocs/comm/card.php b/htdocs/comm/card.php index dfdc9183886..cf7b5bf3dc0 100644 --- a/htdocs/comm/card.php +++ b/htdocs/comm/card.php @@ -603,11 +603,17 @@ if ($id > 0) if ($link) $boxstat.=''; } + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreBoxStatsCustomer', $parameters, $object, $action); + if(empty($reshook)){ + $boxstat.= $hookmanager->resPrint; + } + $boxstat.=''; $boxstat.=''; $boxstat.='
'; - print $boxstat; + print $boxstat; $now=dol_now(); diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index b1d8aa03022..b603d1e6a17 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -1750,6 +1750,7 @@ if ($action == 'create') $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->propal->creer, 'string', '', null, null, '', 1); // Thirdparty $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1); + if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) $morehtmlref.=' ('.$langs->trans("OtherProposals").')'; // Project if (! empty($conf->projet->enabled)) { diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index a4888b44861..ddb44153e49 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1924,6 +1924,7 @@ if ($action == 'create' && $user->rights->commande->creer) $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->commande->creer, 'string', '', null, null, '', 1); // Thirdparty $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1); + if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) $morehtmlref.=' ('.$langs->trans("OtherOrders").')'; // Project if (! empty($conf->projet->enabled)) { diff --git a/htdocs/compta/bank/class/api_bankaccounts.class.php b/htdocs/compta/bank/class/api_bankaccounts.class.php index 869b86238ff..c6fd3f72def 100644 --- a/htdocs/compta/bank/class/api_bankaccounts.class.php +++ b/htdocs/compta/bank/class/api_bankaccounts.class.php @@ -72,7 +72,7 @@ class BankAccounts extends DolibarrApi $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."bank_account as t"; $sql.= ' WHERE t.entity IN ('.getEntity('bank_account').')'; // Add sql filters - if ($sqlfilters) + if ($sqlfilters) { if (! DolibarrApi::_checkFilters($sqlfilters)) { @@ -81,7 +81,7 @@ class BankAccounts extends DolibarrApi $regexstring='\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)'; $sql.=" AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")"; } - + $sql.= $this->db->order($sortfield, $sortorder); if ($limit) { if ($page < 0) @@ -89,10 +89,10 @@ class BankAccounts extends DolibarrApi $page = 0; } $offset = $limit * $page; - + $sql.= $this->db->plimit($limit + 1, $offset); } - + dol_syslog("API Rest request"); $result = $this->db->query($sql); @@ -236,7 +236,7 @@ class BankAccounts extends DolibarrApi function _validate($data) { $account = array(); - foreach (Accounts::$FIELDS as $field) { + foreach (BankAccounts::$FIELDS as $field) { if (! isset($data[$field])) throw new RestException(400, "$field field missing"); $account[$field] = $data[$field]; diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 64ab86cf859..e13767b806e 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -400,6 +400,22 @@ if (empty($reshook)) setEventMessages($discount->error, $discount->errors, 'errors'); } } + + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09'); + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $ret = $object->fetch($id); // Reload to get new records + + $result = $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref); + if ($result < 0) setEventMessages($object->error, $object->errors, 'errors'); + } } else if ($action == 'setref_client' && $user->rights->facture->creer) @@ -1108,8 +1124,17 @@ if (empty($reshook)) foreach ($amountdeposit as $tva => $amount) { + $arraylist = array('amount' => 'FixAmount','variable' => 'VarAmount'); + $descline = $langs->trans('Deposit'); + $descline.= ' - '.$langs->trans($arraylist[$typeamount]); + if ($typeamount=='amount') { + $descline.= ' ('. price($valuedeposit, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)).')'; + } elseif ($typeamount=='variable') { + $descline.= ' ('. $valuedeposit.'%)'; + } + $descline.= ' - '.$srcobject->ref; $result = $object->addline( - $langs->trans('Deposit'), + $descline, $amount, // subprice 1, // quantity $tva, // vat rate @@ -1131,8 +1156,8 @@ if (empty($reshook)) 0, 0, 0, - 0, - $langs->trans('Deposit') + 0 + //,$langs->trans('Deposit') //Deprecated ); } @@ -3078,6 +3103,7 @@ else if ($id > 0 || ! empty($ref)) $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->facture->creer, 'string', '', null, null, '', 1); // Thirdparty $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1); + if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) $morehtmlref.=' ('.$langs->trans("OtherBills").')'; // Project if (! empty($conf->projet->enabled)) { diff --git a/htdocs/compta/paiement/class/paiement.class.php b/htdocs/compta/paiement/class/paiement.class.php index 495eb836bb4..a193cb1bff1 100644 --- a/htdocs/compta/paiement/class/paiement.class.php +++ b/htdocs/compta/paiement/class/paiement.class.php @@ -338,6 +338,24 @@ class Paiement extends CommonObject $error++; } } + } + + if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) + { + $outputlangs = $langs; + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $invoice->thirdparty->default_lang; + if (! empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $ret = $invoice->fetch($id); // Reload to get new records + + $result = $invoice->generateDocument($invoice->modelpdf, $outputlangs); + if ($result < 0) { + setEventMessages($invoice->error, $invoice->errors, 'errors'); + $error++; + } + } } } diff --git a/htdocs/contrat/list.php b/htdocs/contrat/list.php index 48a9afaaa56..d53bc0a3ee1 100644 --- a/htdocs/contrat/list.php +++ b/htdocs/contrat/list.php @@ -305,7 +305,7 @@ if ($resql) $i = 0; $arrayofselected=is_array($toselect)?$toselect:array(); - + if ($socid > 0) { $soc = new Societe($db); @@ -313,7 +313,7 @@ if ($resql) if (empty($search_name)) $search_name = $soc->name; } - $param=''; + $param=''; if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage; if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit; if ($sall != '') $param.='&sall='.$sall; diff --git a/htdocs/contrat/services.php b/htdocs/contrat/services.php index 2fdec21f735..6534ef1e362 100644 --- a/htdocs/contrat/services.php +++ b/htdocs/contrat/services.php @@ -332,7 +332,7 @@ if ($conf->categorie->enabled && ($user->rights->produit->lire || $user->rights- $moreforfilter.='
'; $moreforfilter.=$langs->trans('IncludingProductWithTag'). ': '; $cate_arbo = $form->select_all_categories(Categorie::TYPE_PRODUCT, null, 'parent', null, null, 1); - $moreforfilter.=$form->selectarray('search_product_category', $cate_arbo, $search_product_category, 1, 0, 0, '', 0, 0, 0, 0, '', 1); + $moreforfilter.=$form->selectarray('search_product_category', $cate_arbo, $search_product_category, 1, 0, 0, '', 0, 0, 0, 0, 'maxwidth300', 1); $moreforfilter.='
'; } @@ -523,7 +523,6 @@ while ($i < min($num,$limit)) $contractstatic->ref=$obj->ref?$obj->ref:$obj->cid; - print ''; // Ref diff --git a/htdocs/core/actions_fetchobject.inc.php b/htdocs/core/actions_fetchobject.inc.php index 520d3c2d6da..7c25fbe7981 100644 --- a/htdocs/core/actions_fetchobject.inc.php +++ b/htdocs/core/actions_fetchobject.inc.php @@ -28,9 +28,9 @@ // $cancel must be defined // $id or $ref must be defined (object is loaded in this file with fetch) -if (($id > 0 || (! empty($ref) && ! in_array($action, array('create','createtask')))) && empty($cancel)) +if (($id > 0 || (! empty($ref) && ! in_array($action, array('create', 'createtask', 'add')))) && empty($cancel)) { - $ret = $object->fetch($id,$ref); + $ret = $object->fetch($id, $ref); if ($ret > 0) { $object->fetch_thirdparty(); @@ -38,7 +38,8 @@ if (($id > 0 || (! empty($ref) && ! in_array($action, array('create','createtask } else { - setEventMessages($object->error, $object->errors, 'errors'); + if (empty($object->error) && ! count($object->errors)) setEventMessages('Fetch on object return an error without filling $object->error nor $object->errors', null, 'errors'); + else setEventMessages($object->error, $object->errors, 'errors'); $action=''; } } diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index be6f13a22c7..f4a55352f96 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -594,7 +594,7 @@ if (! $error && $massaction == 'delete' && $permtodelete) $nbok = 0; foreach($toselect as $toselectid) { - $result=$objecttmp->fetch($toselectid); + $result=$objecttmp->fetch($toselectid); if ($result > 0) { if (in_array($objecttmp->element, array('societe','member'))) $result = $objecttmp->delete($objecttmp->id, $user, 1); diff --git a/htdocs/core/ajax/selectsearchbox.php b/htdocs/core/ajax/selectsearchbox.php index 2e837fcbaae..2d92bc8f938 100644 --- a/htdocs/core/ajax/selectsearchbox.php +++ b/htdocs/core/ajax/selectsearchbox.php @@ -31,8 +31,17 @@ if (! isset($usedbyinclude) || empty($usedbyinclude)) if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); + if (! defined('NOREDIRECTBYMAINTOLOGIN')) define('NOREDIRECTBYMAINTOLOGIN','1'); $res=@include '../../main.inc.php'; + if ($res == 'ERROR_NOT_LOGGED') + { + $langs->load("other"); + $arrayresult['jumptologin']=array('img'=>'object_generic', 'label'=>$langs->trans("JumpToLogin"), 'text'=>' '.$langs->trans("JumpToLogin"), 'url'=>DOL_URL_ROOT.'/index.php'); + print json_encode($arrayresult); + if (is_object($db)) $db->close(); + exit; + } } include_once DOL_DOCUMENT_ROOT.'/core/lib/json.lib.php'; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index f1ec086cd03..53de8e56eb8 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -334,23 +334,23 @@ abstract class CommonObject // No constructor as it is an abstract class - /** - * Check an object id/ref exists - * If you don't need/want to instantiate object and just need to know if object exists, use this method instead of fetch - * + /** + * Check an object id/ref exists + * If you don't need/want to instantiate object and just need to know if object exists, use this method instead of fetch + * * @param string $element String of element ('product', 'facture', ...) * @param int $id Id of object * @param string $ref Ref of object to check * @param string $ref_ext Ref ext of object to check * @return int <0 if KO, 0 if OK but not found, >0 if OK and exists - */ - static function isExistingObject($element, $id, $ref='', $ref_ext='') - { - global $db,$conf; + */ + static function isExistingObject($element, $id, $ref='', $ref_ext='') + { + global $db,$conf; $sql = "SELECT rowid, ref, ref_ext"; $sql.= " FROM ".MAIN_DB_PREFIX.$element; - $sql.= " WHERE entity IN (".getEntity($element, true).")" ; + $sql.= " WHERE entity IN (".getEntity($element).")" ; if ($id > 0) $sql.= " AND rowid = ".$db->escape($id); else if ($ref) $sql.= " AND ref = '".$db->escape($ref)."'"; @@ -371,17 +371,17 @@ abstract class CommonObject else return 0; } return -1; - } + } - /** - * Method to output saved errors - * - * @return string String with errors - */ - function errorsToString() - { - return $this->error.(is_array($this->errors)?(($this->error!=''?', ':'').join(', ',$this->errors)):''); - } + /** + * Method to output saved errors + * + * @return string String with errors + */ + function errorsToString() + { + return $this->error.(is_array($this->errors)?(($this->error!=''?', ':'').join(', ',$this->errors)):''); + } /** * Return full name (civility+' '+name+' '+lastname) @@ -1309,7 +1309,7 @@ abstract class CommonObject * Load properties id_previous and id_next * * @param string $filter Optional filter. Example: " AND (t.field1 = 'aa' OR t.field2 = 'bb')" - * @param int $fieldid Name of field to use for the select MAX and MIN + * @param string $fieldid Name of field to use for the select MAX and MIN * @param int $nodbprefix Do not include DB prefix to forge table name * @return int <0 if KO, >0 if OK */ @@ -1322,6 +1322,7 @@ abstract class CommonObject dol_print_error('',get_class($this)."::load_previous_next_ref was called on objet with property table_element not defined"); return -1; } + if ($fieldid == 'none') return 1; // this->ismultientitymanaged contains // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe @@ -3947,7 +3948,7 @@ abstract class CommonObject // Now we add first model found in directories scanned $listofdir=explode(',',$dirtoscan); - foreach($listofdir as $key=>$tmpdir) + foreach($listofdir as $key => $tmpdir) { $tmpdir=trim($tmpdir); $tmpdir=preg_replace('/DOL_DATA_ROOT/',DOL_DATA_ROOT,$tmpdir); @@ -4736,19 +4737,6 @@ abstract class CommonObject - - /** - * Function test if type is date - * - * @param array $info content informations of field - * @return bool - */ - protected function isDate($info) - { - if(isset($info['type']) && ($info['type']=='date' || $info['type']=='datetime' || $info['type']=='timestamp')) return true; - else return false; - } - /** * Function test if type is array * @@ -4781,13 +4769,26 @@ abstract class CommonObject else return false; } + + /** + * Function test if type is date + * + * @param array $info content informations of field + * @return bool + */ + public function isDate($info) + { + if(isset($info['type']) && ($info['type']=='date' || $info['type']=='datetime' || $info['type']=='timestamp')) return true; + else return false; + } + /** * Function test if type is integer * * @param array $info content informations of field * @return bool */ - protected function isInt($info) + public function isInt($info) { if(is_array($info)) { @@ -4803,11 +4804,11 @@ abstract class CommonObject * @param array $info content informations of field * @return bool */ - protected function isFloat($info) + public function isFloat($info) { if(is_array($info)) { - if(isset($info['type']) && $info['type']=='float') return true; + if (isset($info['type']) && (preg_match('/^(double|real)/i', $info['type']))) return true; else return false; } else return false; @@ -4819,7 +4820,7 @@ abstract class CommonObject * @param array $info content informations of field * @return bool */ - protected function isText($info) + public function isText($info) { if(is_array($info)) { @@ -4846,49 +4847,58 @@ abstract class CommonObject } /** - * Function to prepare the values to insert + * Function to prepare the values to insert. + * Note $this->${field} are set by the page that make the createCommon or the updateCommon. * * @return array */ private function set_save_query() { - $query=array(); - foreach ($this->fields as $field=>$info) + global $conf; + + $queryarray=array(); + foreach ($this->fields as $field=>$info) // Loop on definition of fields { + // Depending on field type ('datetime', ...) if($this->isDate($info)) { if(empty($this->{$field})) { - $query[$field] = NULL; + $queryarray[$field] = NULL; } else { - $query[$field] = $this->db->idate($this->{$field}); + $queryarray[$field] = $this->db->idate($this->{$field}); } } else if($this->isArray($info)) { - $query[$field] = serialize($this->{$field}); + $queryarray[$field] = serialize($this->{$field}); } else if($this->isInt($info)) { - $query[$field] = (int) price2num($this->{$field}); + if ($field == 'entity' && is_null($this->{$field})) $queryarray[$field]=$conf->entity; + else + { + $queryarray[$field] = (int) price2num($this->{$field}); + if (empty($queryarray[$field])) $queryarray[$field]=0; // May be rest to null later if property 'nullifempty' is on for this field. + } } else if($this->isFloat($info)) { - $query[$field] = (double) price2num($this->{$field}); - } - elseif($this->isNull($info)) - { - $query[$field] = (is_null($this->{$field}) || (empty($this->{$field}) && $this->{$field}!==0 && $this->{$field}!=='0') ? null : $this->{$field}); + $queryarray[$field] = (double) price2num($this->{$field}); + if (empty($queryarray[$field])) $queryarray[$field]=0; } else { - $query[$field] = $this->{$field}; + $queryarray[$field] = $this->{$field}; } + + if ($info['type'] == 'timestamp' && empty($queryarray[$field])) unset($queryarray[$field]); + if (! empty($info['nullifempty']) && empty($queryarray[$field])) $queryarray[$field] = null; } - return $query; + return $queryarray; } /** @@ -4896,7 +4906,7 @@ abstract class CommonObject * * @param stdClass $obj Contain data of object from database */ - private function set_vars_by_db(&$obj) + private function setVarsFromFetchObj(&$obj) { foreach ($this->fields as $field => $info) { @@ -4913,7 +4923,8 @@ abstract class CommonObject } elseif($this->isInt($info)) { - $this->{$field} = (int) $obj->{$field}; + if ($field == 'rowid') $this->id = (int) $obj->{$field}; + else $this->{$field} = (int) $obj->{$field}; } elseif($this->isFloat($info)) { @@ -4947,15 +4958,14 @@ abstract class CommonObject /** * Add quote to field value if necessary * - * @param string|int $value value to protect - * @return string|int + * @param string|int $value Value to protect + * @param array $fieldsentry Properties of field + * @return string */ - protected function quote($value) { - - if(is_null($value)) return 'NULL'; - else if(is_numeric($value)) return $value; - else return "'".$this->db->escape( $value )."'"; - + protected function quote($value, $fieldsentry) { + if (is_null($value)) return 'NULL'; + else if (preg_match('/^(int|double|real)/i', $fieldsentry['type'])) return $this->db->escape("$value"); + else return "'".$this->db->escape($value)."'"; } @@ -4970,23 +4980,29 @@ abstract class CommonObject { $error = 0; - $fields = array_merge(array('datec'=>$this->db->idate(dol_now())), $this->set_save_query()); + $now=dol_now(); + + $fieldvalues = $this->set_save_query(); + if (array_key_exists('date_creation', $fieldvalues) && empty($fieldvalues['date_creation'])) $fieldvalues['date_creation']=$this->db->idate($now); + if (array_key_exists('fk_user_creat', $fieldvalues) && ! ($fieldvalues['fk_user_creat'] > 0)) $fieldvalues['fk_user_creat']=$user->id; + unset($fieldvalues['rowid']); // We suppose the field rowid is reserved field for autoincrement field. $keys=array(); $values = array(); - foreach ($fields as $k => $v) { + foreach ($fieldvalues as $k => $v) { $keys[] = $k; - $values[] = $this->quote($v); + $values[] = $this->quote($v, $this->fields[$k]); } $this->db->begin(); if (! $error) { - $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.' - ( '.implode( ",", $keys ).' ) - VALUES ( '.implode( ",", $values ).' ) '; - $res = $this->db->query( $sql ); + $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element; + $sql.= ' ('.implode( ", ", $keys ).')'; + $sql.= ' VALUES ('.implode( ", ", $values ).')'; + + $res = $this->db->query( $sql ); if ($res===false) { $error++; $this->errors[] = $this->db->lasterror(); @@ -4998,7 +5014,7 @@ abstract class CommonObject if (!$notrigger) { // Call triggers - $result=$this->call_trigger(strtoupper(get_class(self)).'_CREATE',$user); + $result=$this->call_trigger(strtoupper(get_class($this)).'_CREATE',$user); if ($result < 0) { $error++; } // End call triggers } @@ -5035,8 +5051,10 @@ abstract class CommonObject // Load source object $object->fetchCommon($fromid); - // Reset object - $object->id = 0; + // Reset some properties + unset($object->id); + unset($object->fk_user_creat); + unset($object->import_key); // Clear fields $object->ref = "copy_of_".$object->ref; @@ -5075,11 +5093,11 @@ abstract class CommonObject { if (empty($id) && empty($ref)) return false; - $sql = 'SELECT '.$this->get_field_list().', datec, tms'; + $sql = 'SELECT '.$this->get_field_list(); $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element; if(!empty($id)) $sql.= ' WHERE rowid = '.$id; - else $sql.= ' WHERE ref = \''.$this->quote($ref).'\''; + else $sql.= " WHERE ref = ".$this->quote($ref, $this->fields['ref']); $res = $this->db->query($sql); if ($res) @@ -5088,12 +5106,7 @@ abstract class CommonObject { if ($obj) { - $this->id = $id; - $this->set_vars_by_db($obj); - - $this->datec = $this->db->idate($obj->datec); - $this->tms = $this->db->idate($obj->tms); - + $this->setVarsFromFetchObj($obj); return $this->id; } else @@ -5127,27 +5140,27 @@ abstract class CommonObject { $error = 0; - $fields = $this->set_save_query(); + $fieldvalues = $this->set_save_query(); + unset($fieldvalues['rowid']); // We don't update this field, it is the key to define which record to update. - foreach ($fields as $k => $v) { + foreach ($fieldvalues as $k => $v) { if (is_array($key)){ $i=array_search($k, $key); if ( $i !== false) { - $where[] = $key[$i].'=' . $this->quote( $v ) ; + $where[] = $key[$i].'=' . $this->quote($v, $this->fields[$k]); continue; } } else { if ( $k == $key) { - $where[] = $k.'=' .$this->quote( $v ) ; + $where[] = $k.'=' .$this->quote($v, $this->fields[$k]); continue; } } - $tmp[] = $k.'='.$this->quote($v); + $tmp[] = $k.'='.$this->quote($v, $this->fields[$k]); } $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET '.implode( ',', $tmp ).' WHERE rowid='.$this->id ; $this->db->begin(); - if (! $error) { $res = $this->db->query($sql); @@ -5160,7 +5173,7 @@ abstract class CommonObject if (! $error && ! $notrigger) { // Call triggers - $result=$this->call_trigger(strtoupper(get_class(self)).'_MODIFY',$user); + $result=$this->call_trigger(strtoupper(get_class($this)).'_MODIFY',$user); if ($result < 0) { $error++; } //Do also here what you must do to rollback action if trigger fail // End call triggers } @@ -5191,7 +5204,7 @@ abstract class CommonObject if (! $error) { if (! $notrigger) { // Call triggers - $result=$this->call_trigger(strtoupper(get_class(self)).'_DELETE', $user); + $result=$this->call_trigger(strtoupper(get_class($this)).'_DELETE', $user); if ($result < 0) { $error++; } // Do also here what you must do to rollback action if trigger fail // End call triggers } diff --git a/htdocs/core/class/doleditor.class.php b/htdocs/core/class/doleditor.class.php index db768b4c630..eaf72ffff71 100644 --- a/htdocs/core/class/doleditor.class.php +++ b/htdocs/core/class/doleditor.class.php @@ -82,7 +82,7 @@ class DolEditor // Check if extended editor is ok. If not we force textarea if ((empty($conf->fckeditor->enabled) && $okforextendededitor != 'ace') || empty($okforextendededitor)) $this->tool = 'textarea'; if ($okforextendededitor === 'ace') $this->tool='ace'; - if ($conf->dol_use_jmobile) $this->tool = 'textarea'; // TODO ckeditor ko with mobile ? ace ko with mobile ? + //if ($conf->dol_use_jmobile) $this->tool = 'textarea'; // ckeditor and ace seems ok with mobile // Define content and some properties if ($this->tool == 'ckeditor') diff --git a/htdocs/core/class/extrafields.class.php b/htdocs/core/class/extrafields.class.php index e44fa8a5aec..966f3f859c0 100644 --- a/htdocs/core/class/extrafields.class.php +++ b/htdocs/core/class/extrafields.class.php @@ -281,7 +281,7 @@ class ExtraFields */ private function create_label($attrname, $label='', $type='', $pos=0, $size=0, $elementtype='member', $unique=0, $required=0, $param='', $alwayseditable=0, $perms='', $list=0, $ishidden=0, $default='', $computed='') { - global $conf; + global $conf,$user; if ($elementtype == 'thirdparty') $elementtype='societe'; if ($elementtype == 'contact') $elementtype='socpeople'; @@ -305,7 +305,27 @@ class ExtraFields $params=''; } - $sql = "INSERT INTO ".MAIN_DB_PREFIX."extrafields(name, label, type, pos, size, entity, elementtype, fieldunique, fieldrequired, param, alwayseditable, perms, list, ishidden, fielddefault, fieldcomputed)"; + $sql = "INSERT INTO ".MAIN_DB_PREFIX."extrafields("; + $sql.= " name,"; + $sql.= " label,"; + $sql.= " type,"; + $sql.= " pos,"; + $sql.= " size,"; + $sql.= " entity,"; + $sql.= " elementtype,"; + $sql.= " fieldunique,"; + $sql.= " fieldrequired,"; + $sql.= " param,"; + $sql.= " alwayseditable,"; + $sql.= " perms,"; + $sql.= " list,"; + $sql.= " ishidden,"; + $sql.= " fielddefault,"; + $sql.= " fieldcomputed,"; + $sql.= " fk_user_author,"; + $sql.= " fk_user_modif,"; + $sql.= " datec"; + $sql.= " )"; $sql.= " VALUES('".$attrname."',"; $sql.= " '".$this->db->escape($label)."',"; $sql.= " '".$type."',"; @@ -321,9 +341,12 @@ class ExtraFields $sql.= " ".$list.","; $sql.= " ".$ishidden.","; $sql.= " ".($default?"'".$this->db->escape($default)."'":"null").","; - $sql.= " ".($computed?"'".$this->db->escape($computed)."'":"null"); + $sql.= " ".($computed?"'".$this->db->escape($computed)."'":"null").","; + $sql .= " " . $user->id . ","; + $sql .= " " . $user->id . ","; + $sql .= "'" . $this->db->idate(dol_now()) . "'"; $sql.=')'; - + dol_syslog(get_class($this)."::create_label", LOG_DEBUG); if ($this->db->query($sql)) { @@ -562,7 +585,7 @@ class ExtraFields */ private function update_label($attrname,$label,$type,$size,$elementtype,$unique=0,$required=0,$pos=0,$param='',$alwayseditable=0,$perms='',$list=0,$ishidden=0,$default='',$computed='') { - global $conf; + global $conf, $user; dol_syslog(get_class($this)."::update_label ".$attrname.", ".$label.", ".$type.", ".$size.", ".$elementtype.", ".$unique.", ".$required.", ".$pos.", ".$alwayseditable.", ".$perms.", ".$list.", ".$ishidden.", ".$default.", ".$computed); // Clean parameters @@ -603,7 +626,10 @@ class ExtraFields $sql.= " list,"; $sql.= " ishidden,"; $sql.= " fielddefault,"; - $sql.= " fieldcomputed"; + $sql.= " fieldcomputed,"; + $sql.= " fk_user_author,"; + $sql.= " fk_user_modif,"; + $sql.= " datec"; $sql.= ") VALUES ("; $sql.= "'".$attrname."',"; $sql.= " ".$conf->entity.","; @@ -620,7 +646,10 @@ class ExtraFields $sql.= " ".$list.", "; $sql.= " ".$ishidden.", "; $sql.= " ".($default?"'".$this->db->escape($default)."'":"null").","; - $sql.= " ".($computed?"'".$this->db->escape($computed)."'":"null"); + $sql.= " ".($computed?"'".$this->db->escape($computed)."'":"null").","; + $sql .= " " . $user->id . ","; + $sql .= " " . $user->id . ","; + $sql .= "'" . $this->db->idate(dol_now()) . "'"; $sql.= ")"; $resql2=$this->db->query($sql); diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 9f6ff1451ec..32a6fdf7aba 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -5866,7 +5866,7 @@ class Form * @param string $paramid Name of parameter to use to name the id into the URL next/previous link. * @param string $morehtml More html content to output just before the nav bar. * @param int $shownav Show Condition (navigation is shown if value is 1). - * @param string $fieldid Name of field id into database to use for select next and previous (we make the select max and min on this field). + * @param string $fieldid Name of field id into database to use for select next and previous (we make the select max and min on this field). Use 'none' to disable next/prev. * @param string $fieldref Name of field ref of object (object->ref) to show or 'none' to not show ref. * @param string $morehtmlref More html to show after ref. * @param string $moreparam More param to add in nav link url. Must start with '&...'. diff --git a/htdocs/core/class/html.formwebsite.class.php b/htdocs/core/class/html.formwebsite.class.php new file mode 100644 index 00000000000..666311d1744 --- /dev/null +++ b/htdocs/core/class/html.formwebsite.class.php @@ -0,0 +1,1254 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/core/class/html.formwebsite.class.php + * \ingroup core + * \brief File of class to manage component html for module website + */ + + +/** + * Class to manage component html for module website + */ +class FormWebsite +{ + private $db; + public $error; + + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + function __construct($db) + { + $this->db = $db; + + return 1; + } + + + /** + * Return HTML select list of export models + * + * @param string $selected Id modele pre-selectionne + * @param string $htmlname Name of HTML select + * @param int $useempty Show empty value or not + * @return string Html component + */ + function selectWebsite($selected='',$htmlname='exportmodelid',$useempty=0) + { + $out=''; + + $sql = "SELECT rowid, ref"; + $sql.= " FROM ".MAIN_DB_PREFIX."website"; + $sql.= " WHERE 1 = 1"; + $sql.= " ORDER BY rowid"; + $result = $this->db->query($sql); + if ($result) + { + $out.='"; + } + else { + dol_print_error($this->db); + } + + return $out; + } + + + /** + * Return list of export models + * + * @param string $selected Id modele pre-selectionne + * @param string $htmlname Nom de la zone select + * @param string $type Type des modeles recherches + * @param int $useempty Affiche valeur vide dans liste + * @return void + */ + function select_import_model($selected='',$htmlname='importmodelid',$type='',$useempty=0) + { + $sql = "SELECT rowid, label"; + $sql.= " FROM ".MAIN_DB_PREFIX."import_model"; + $sql.= " WHERE type = '".$type."'"; + $sql.= " ORDER BY rowid"; + $result = $this->db->query($sql); + if ($result) + { + print '"; + } + else { + dol_print_error($this->db); + } + } + + + /** + * Return list of ecotaxes with label + * + * @param string $selected Preselected ecotaxes + * @param string $htmlname Name of combo list + * @return integer + */ + function select_ecotaxes($selected='',$htmlname='ecotaxe_id') + { + global $langs; + + $sql = "SELECT e.rowid, e.code, e.libelle, e.price, e.organization,"; + $sql.= " c.label as country"; + $sql.= " FROM ".MAIN_DB_PREFIX."c_ecotaxe as e,".MAIN_DB_PREFIX."c_country as c"; + $sql.= " WHERE e.active = 1 AND e.fk_pays = c.rowid"; + $sql.= " ORDER BY country, e.organization ASC, e.code ASC"; + + dol_syslog(get_class($this).'::select_ecotaxes', LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + print ''; + return 0; + } + else + { + dol_print_error($this->db); + return 1; + } + } + + + /** + * Return list of revenue stamp for country + * + * @param string $selected Value of preselected revenue stamp + * @param string $htmlname Name of combo list + * @param string $country_code Country Code + * @return string HTML select list + */ + function select_revenue_stamp($selected='',$htmlname='revenuestamp',$country_code='') + { + global $langs; + + $out=''; + + $sql = "SELECT r.taux"; + $sql.= " FROM ".MAIN_DB_PREFIX."c_revenuestamp as r,".MAIN_DB_PREFIX."c_country as c"; + $sql.= " WHERE r.active = 1 AND r.fk_pays = c.rowid"; + $sql.= " AND c.code = '".$country_code."'"; + + dol_syslog(get_class($this).'::select_revenue_stamp', LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + $out.=''; + return $out; + } + else + { + dol_print_error($this->db); + return ''; + } + } + + + /** + * Return a HTML select list to select a percent + * + * @param integer $selected pourcentage pre-selectionne + * @param string $htmlname nom de la liste deroulante + * @param int $disabled Disabled or not + * @param int $increment increment value + * @param int $start start value + * @param int $end end value + * @param int $showempty Add also an empty line + * @return string HTML select string + */ + function select_percent($selected=0,$htmlname='percent',$disabled=0,$increment=5,$start=0,$end=100,$showempty=0) + { + $return = ''; + + return $return; + } + + /** + * Return select list for categories (to use in form search selectors) + * + * @param int $type Type of category ('customer', 'supplier', 'contact', 'product', 'member'). Old mode (0, 1, 2, ...) is deprecated. + * @param integer $selected Preselected value + * @param string $htmlname Name of combo list + * @param int $nocateg Show also an entry "Not categorized" + * @param int $showempty Add also an empty line + * @param string $morecss More CSS + * @return string Html combo list code + * @see select_all_categories + */ + function select_categories($type, $selected=0, $htmlname='search_categ', $nocateg=0, $showempty=1, $morecss='') + { + global $conf, $langs; + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + + // For backward compatibility + if (is_numeric($type)) + { + dol_syslog(__METHOD__ . ': using numeric value for parameter type is deprecated. Use string code instead.', LOG_WARNING); + } + + // Load list of "categories" + $static_categs = new Categorie($this->db); + $tab_categs = $static_categs->get_full_arbo($type); + + $moreforfilter = ''; + // Enhance with select2 + if ($conf->use_javascript_ajax) + { + include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; + $comboenhancement = ajax_combobox('select_categ_'.$htmlname); + $moreforfilter.=$comboenhancement; + } + + // Print a select with each of them + $moreforfilter.=''; + + return $moreforfilter; + } + + + /** + * Return select list for categories (to use in form search selectors) + * + * @param string $selected Preselected value + * @param string $htmlname Name of combo list (example: 'search_sale') + * @param User $user Object user + * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status + * @param int $showempty 1=show also an empty value + * @param string $morecss More CSS + * @return string Html combo list code + */ + function select_salesrepresentatives($selected,$htmlname,$user,$showstatus=0,$showempty=1,$morecss='') + { + global $conf,$langs; + $langs->load('users'); + + $out = ''; + // Enhance with select2 + if ($conf->use_javascript_ajax) + { + include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; + + $comboenhancement = ajax_combobox($htmlname); + if ($comboenhancement) + { + $out.=$comboenhancement; + } + } + // Select each sales and print them in a select input + $out.=''; + + return $out; + } + + /** + * Return list of project and tasks + * + * @param int $selectedtask Pre-selected task + * @param int $projectid Project id + * @param string $htmlname Name of html select + * @param int $modeproject 1 to restrict on projects owned by user + * @param int $modetask 1 to restrict on tasks associated to user + * @param int $mode 0=Return list of tasks and their projects, 1=Return projects and tasks if exists + * @param int $useempty 0=Allow empty values + * @param int $disablechildoftaskid 1=Disable task that are child of the provided task id + * @return void + */ + function selectProjectTasks($selectedtask='', $projectid=0, $htmlname='task_parent', $modeproject=0, $modetask=0, $mode=0, $useempty=0, $disablechildoftaskid=0) + { + global $user, $langs; + + require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; + + //print $modeproject.'-'.$modetask; + $task=new Task($this->db); + $tasksarray=$task->getTasksArray($modetask?$user:0, $modeproject?$user:0, $projectid, 0, $mode); + if ($tasksarray) + { + print ''; + } + else + { + print '
'.$langs->trans("NoProject").'
'; + } + } + + /** + * Write lines of a project (all lines of a project if parent = 0) + * + * @param int $inc Cursor counter + * @param int $parent Id of parent task we want to see + * @param array $lines Array of task lines + * @param int $level Level + * @param int $selectedtask Id selected task + * @param int $selectedproject Id selected project + * @param int $disablechildoftaskid 1=Disable task that are child of the provided task id + * @return void + */ + private function _pLineSelect(&$inc, $parent, $lines, $level=0, $selectedtask=0, $selectedproject=0, $disablechildoftaskid=0) + { + global $langs, $user, $conf; + + $lastprojectid=0; + + $numlines=count($lines); + for ($i = 0 ; $i < $numlines ; $i++) + { + if ($lines[$i]->fk_parent == $parent) + { + $var = !$var; + + //var_dump($selectedproject."--".$selectedtask."--".$lines[$i]->fk_project."_".$lines[$i]->id); // $lines[$i]->id may be empty if project has no lines + + // Break on a new project + if ($parent == 0) // We are on a task at first level + { + if ($lines[$i]->fk_project != $lastprojectid) // Break found on project + { + if ($i > 0) print ''; + print '\n"; + + $lastprojectid=$lines[$i]->fk_project; + $inc++; + } + } + + $newdisablechildoftaskid=$disablechildoftaskid; + + // Print task + if (isset($lines[$i]->id)) // We use isset because $lines[$i]->id may be null if project has no task and are on root project (tasks may be caught by a left join). We enter here only if '0' or >0 + { + // Check if we must disable entry + $disabled=0; + if ($disablechildoftaskid && (($lines[$i]->id == $disablechildoftaskid || $lines[$i]->fk_parent == $disablechildoftaskid))) + { + $disabled++; + if ($lines[$i]->fk_parent == $disablechildoftaskid) $newdisablechildoftaskid=$lines[$i]->id; // If task is child of a disabled parent, we will propagate id to disable next child too + } + + print '\n"; + $inc++; + } + + $level++; + if ($lines[$i]->id) $this->_pLineSelect($inc, $lines[$i]->id, $lines, $level, $selectedtask, $selectedproject, $newdisablechildoftaskid); + $level--; + } + } + } + + + /** + * Output a HTML thumb of color or a text if not defined. + * + * @param string $color String with hex (FFFFFF) or comma RGB ('255,255,255') + * @param string $textifnotdefined Text to show if color not defined + * @return string HTML code for color thumb + * @see selectColor + */ + static function showColor($color, $textifnotdefined='') + { + $textcolor='FFF'; + if ($color) + { + $tmp=explode(',', $color); + if (count($tmp) > 1) // This is a comma RGB ('255','255','255') + { + $r = $tmp[0]; + $g = $tmp[1]; + $b = $tmp[2]; + } + else + { + $hexr=$color[0].$color[1]; + $hexg=$color[2].$color[3]; + $hexb=$color[4].$color[5]; + $r = hexdec($hexr); + $g = hexdec($hexg); + $b = hexdec($hexb); + } + $bright = (max($r, $g, $b) + min($r, $g, $b)) / 510.0; // HSL algorithm + if ($bright > 0.6) $textcolor='000'; + } + + include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + $color = colorArrayToHex(colorStringToArray($color,array()),''); + + if ($color) print ''; + else print $textifnotdefined; + } + + /** + * Output a HTML code to select a color + * + * @param string $set_color Pre-selected color + * @param string $prefix Name of HTML field + * @param string $form_name Deprecated. Not used. + * @param int $showcolorbox 1=Show color code and color box, 0=Show only color code + * @param array $arrayofcolors Array of colors. Example: array('29527A','5229A3','A32929','7A367A','B1365F','0D7813') + * @return void + * @deprecated Use instead selectColor + * @see selectColor() + */ + function select_color($set_color='', $prefix='f_color', $form_name='', $showcolorbox=1, $arrayofcolors='') + { + print $this->selectColor($set_color, $prefix, $form_name, $showcolorbox, $arrayofcolors); + } + + /** + * Output a HTML code to select a color. Field will return an hexa color like '334455'. + * + * @param string $set_color Pre-selected color + * @param string $prefix Name of HTML field + * @param string $form_name Deprecated. Not used. + * @param int $showcolorbox 1=Show color code and color box, 0=Show only color code + * @param array $arrayofcolors Array of colors. Example: array('29527A','5229A3','A32929','7A367A','B1365F','0D7813') + * @param string $morecss Add css style into input field + * @return string + * @see showColor + */ + static function selectColor($set_color='', $prefix='f_color', $form_name='', $showcolorbox=1, $arrayofcolors='', $morecss='') + { + // Deprecation warning + if ($form_name) { + dol_syslog(__METHOD__ . ": form_name parameter is deprecated", LOG_WARNING); + } + + global $langs,$conf; + + $out=''; + + if (! is_array($arrayofcolors) || count($arrayofcolors) < 1) + { + $langs->load("other"); + if (empty($conf->dol_use_jmobile)) + { + $out.= ''; + $out.= ''; + $out.= ''; + } + $out.= ''; + } + else // In most cases, this is not used. We used instead function with no specific list of colors + { + if (empty($conf->dol_use_jmobile)) + { + $out.= ''; + $out.= ''; + $out.= ''; + } + $out.= ''; + } + + return $out; + } + + /** + * Creation d'un icone de couleur + * + * @param string $color Couleur de l'image + * @param string $module Nom du module + * @param string $name Nom de l'image + * @param int $x Largeur de l'image en pixels + * @param int $y Hauteur de l'image en pixels + * @return void + */ + function CreateColorIcon($color,$module,$name,$x='12',$y='12') + { + global $conf; + + $file = $conf->$module->dir_temp.'/'.$name.'.png'; + + // On cree le repertoire contenant les icones + if (! file_exists($conf->$module->dir_temp)) + { + dol_mkdir($conf->$module->dir_temp); + } + + // On cree l'image en vraies couleurs + $image = imagecreatetruecolor($x,$y); + + $color = substr($color,1,6); + + $rouge = hexdec(substr($color,0,2)); //conversion du canal rouge + $vert = hexdec(substr($color,2,2)); //conversion du canal vert + $bleu = hexdec(substr($color,4,2)); //conversion du canal bleu + + $couleur = imagecolorallocate($image,$rouge,$vert,$bleu); + //print $rouge.$vert.$bleu; + imagefill($image,0,0,$couleur); //on remplit l'image + // On cree la couleur et on l'attribue a une variable pour ne pas la perdre + ImagePng($image,$file); //renvoie une image sous format png + ImageDestroy($image); + } + + /** + * Return HTML combo list of week + * + * @param string $selected Preselected value + * @param string $htmlname Nom de la zone select + * @param int $useempty Affiche valeur vide dans liste + * @return string + */ + function select_dayofweek($selected='',$htmlname='weekid',$useempty=0) + { + global $langs; + + $week = array( 0=>$langs->trans("Day0"), + 1=>$langs->trans("Day1"), + 2=>$langs->trans("Day2"), + 3=>$langs->trans("Day3"), + 4=>$langs->trans("Day4"), + 5=>$langs->trans("Day5"), + 6=>$langs->trans("Day6")); + + $select_week = ''; + return $select_week; + } + + /** + * Return HTML combo list of month + * + * @param string $selected Preselected value + * @param string $htmlname Name of HTML select object + * @param int $useempty Show empty in list + * @param int $longlabel Show long label + * @return string + */ + function select_month($selected='',$htmlname='monthid',$useempty=0,$longlabel=0) + { + global $langs; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + + if ($longlabel) $montharray = monthArray($langs, 0); // Get array + else $montharray = monthArray($langs, 1); + + $select_month = ''; + return $select_month; + } + + /** + * Return HTML combo list of years + * + * @param string $selected Preselected value (''=current year, -1=none, year otherwise) + * @param string $htmlname Name of HTML select object + * @param int $useempty Affiche valeur vide dans liste + * @param int $min_year Offset of minimum year into list (by default current year -10) + * @param int $max_year Offset of maximum year into list (by default current year + 5) + * @param int $offset Offset + * @param int $invert Invert + * @param string $option Option + * @return string + */ + function select_year($selected='',$htmlname='yearid',$useempty=0, $min_year=10, $max_year=5, $offset=0, $invert=0, $option='') + { + print $this->selectyear($selected,$htmlname,$useempty,$min_year,$max_year,$offset,$invert,$option); + } + + /** + * Return HTML combo list of years + * + * @param string $selected Preselected value (''=current year, -1=none, year otherwise) + * @param string $htmlname Name of HTML select object + * @param int $useempty Affiche valeur vide dans liste + * @param int $min_year Offset of minimum year into list (by default current year -10) + * @param int $max_year Offset of maximum year into list (by default current year + 5) + * @param int $offset Offset + * @param int $invert Invert + * @param string $option Option + * @return string + */ + function selectyear($selected='',$htmlname='yearid',$useempty=0, $min_year=10, $max_year=5, $offset=0, $invert=0, $option='') + { + $out=''; + + $currentyear = date("Y")+$offset; + $max_year = $currentyear+$max_year; + $min_year = $currentyear-$min_year; + if(empty($selected) && empty($useempty)) $selected = $currentyear; + + $out.= '\n"; + + return $out; + } + + /** + * Show form to select address + * + * @param int $page Page + * @param string $selected Id condition pre-selectionne + * @param int $socid Id of third party + * @param string $htmlname Nom du formulaire select + * @param string $origin Origine de l'appel pour pouvoir creer un retour + * @param int $originid Id de l'origine + * @return void + */ + function form_address($page, $selected, $socid, $htmlname='address_id', $origin='', $originid='') + { + global $langs,$conf; + global $form; + + if ($htmlname != "none") + { + print '
'; + print ''; + print ''; + $form->select_address($selected, $socid, $htmlname, 1); + print ''; + $langs->load("companies"); + print '   '.$langs->trans("AddAddress").''; + print '
'; + } + else + { + if ($selected) + { + require_once DOL_DOCUMENT_ROOT .'/societe/class/address.class.php'; + $address=new Address($this->db); + $result=$address->fetch_address($selected); + print ''.$address->label.''; + } + else + { + print " "; + } + } + } + + + + /** + * Get array with HTML tabs with boxes of a particular area including personalized choices of user. + * Class 'Form' must be known. + * + * @param User $user Object User + * @param String $areacode Code of area for pages ('0'=value for Home page) + * @return array array('selectboxlist'=>, 'boxactivated'=>, 'boxlista'=>, 'boxlistb'=>) + */ + static function getBoxesArea($user,$areacode) + { + global $conf,$langs,$db; + + include_once DOL_DOCUMENT_ROOT.'/core/class/infobox.class.php'; + + $confuserzone='MAIN_BOXES_'.$areacode; + + // $boxactivated will be array of boxes enabled into global setup + // $boxidactivatedforuser will be array of boxes choosed by user + + $selectboxlist=''; + $boxactivated=InfoBox::listBoxes($db, 'activated', $areacode, (empty($user->conf->$confuserzone)?null:$user), array(), 0); // Search boxes of common+user (or common only if user has no specific setup) + + $boxidactivatedforuser=array(); + foreach($boxactivated as $box) + { + if (empty($user->conf->$confuserzone) || $box->fk_user == $user->id) $boxidactivatedforuser[$box->id]=$box->id; // We keep only boxes to show for user + } + + // Define selectboxlist + $arrayboxtoactivatelabel=array(); + if (! empty($user->conf->$confuserzone)) + { + $boxorder=''; + $langs->load("boxes"); // Load label of boxes + foreach($boxactivated as $box) + { + if (! empty($boxidactivatedforuser[$box->id])) continue; // Already visible for user + $label=$langs->transnoentitiesnoconv($box->boxlabel); + if (preg_match('/graph/',$box->class)) $label.=' ('.$langs->trans("Graph").')'; + //$label = ''.$label; KO with select2. No html rendering. + $arrayboxtoactivatelabel[$box->id]=$label; // We keep only boxes not shown for user, to show into combo list + } + foreach($boxidactivatedforuser as $boxid) + { + if (empty($boxorder)) $boxorder.='A:'; + $boxorder.=$boxid.','; + } + + //var_dump($boxidactivatedforuser); + + // Class Form must have been already loaded + $selectboxlist.='
'; + $selectboxlist.=''; + $selectboxlist.=''; + $selectboxlist.=''; + $selectboxlist.=''; + $selectboxlist.=Form::selectarray('boxcombo', $arrayboxtoactivatelabel, -1, $langs->trans("ChooseBoxToAdd").'...', 0, 0, '', 0, 0, 0, 'ASC', 'maxwidth150onsmartphone', 0, 'hidden selected', 0, 1); + if (empty($conf->use_javascript_ajax)) $selectboxlist.=' '; + $selectboxlist.='
'; + $selectboxlist.=ajax_combobox("boxcombo"); + } + + // Javascript code for dynamic actions + if (! empty($conf->use_javascript_ajax)) + { + $selectboxlist.=''."\n"; + } + + // Define boxlista and boxlistb + $nbboxactivated=count($boxidactivatedforuser); + + if ($nbboxactivated) + { + $langs->load("boxes"); + $langs->load("projects"); + + $emptybox=new ModeleBoxes($db); + + $boxlista.="\n\n"; + $boxlista.='
'."\n"; + + // Define $box_max_lines + $box_max_lines=5; + if (! empty($conf->global->MAIN_BOXES_MAXLINES)) $box_max_lines=$conf->global->MAIN_BOXES_MAXLINES; + + $ii=0; + foreach ($boxactivated as $key => $box) + { + if ((! empty($user->conf->$confuserzone) && $box->fk_user == 0) || (empty($user->conf->$confuserzone) && $box->fk_user != 0)) continue; + if (empty($box->box_order) && $ii < ($nbboxactivated / 2)) $box->box_order='A'.sprintf("%02d",($ii+1)); // When box_order was not yet set to Axx or Bxx and is still 0 + if (preg_match('/^A/i',$box->box_order)) // column A + { + $ii++; + //print 'box_id '.$boxactivated[$ii]->box_id.' '; + //print 'box_order '.$boxactivated[$ii]->box_order.'
'; + // Show box + $box->loadBox($box_max_lines); + $boxlista.= $box->outputBox(); + } + } + + if (empty($conf->browser->phone)) + { + $emptybox->box_id='A'; + $emptybox->info_box_head=array(); + $emptybox->info_box_contents=array(); + $boxlista.= $emptybox->outputBox(array(),array()); + } + $boxlista.= "
\n"; + $boxlista.= "\n"; + + $boxlistb.= "\n\n"; + $boxlistb.= '\n"; + $boxlistb.= "\n"; + + } + + return array('selectboxlist'=>count($boxactivated)?$selectboxlist:'', 'boxactivated'=>$boxactivated, 'boxlista'=>$boxlista, 'boxlistb'=>$boxlistb); + } + + + /** + * Return a HTML select list of bank accounts + * + * @param string $htmlname Name of select zone + * @param string $dictionarytable Dictionary table + * @param string $keyfield Field for key + * @param string $labelfield Label field + * @param string $selected Selected value + * @param int $useempty 1=Add an empty value in list, 2=Add an empty value in list only if there is more than 2 entries. + * @param string $moreattrib More attributes on HTML select tag + * @return void + */ + function select_dictionary($htmlname,$dictionarytable,$keyfield='code',$labelfield='label',$selected='',$useempty=0,$moreattrib='') + { + global $langs, $conf; + + $langs->load("admin"); + + $sql = "SELECT rowid, ".$keyfield.", ".$labelfield; + $sql.= " FROM ".MAIN_DB_PREFIX.$dictionarytable; + $sql.= " ORDER BY ".$labelfield; + + dol_syslog(get_class($this)."::select_dictionary", LOG_DEBUG); + $result = $this->db->query($sql); + if ($result) + { + $num = $this->db->num_rows($result); + $i = 0; + if ($num) + { + print '"; + } + else + { + print $langs->trans("DictionaryEmpty"); + } + } + else { + dol_print_error($this->db); + } + } + +} + diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 6711ed2825f..0b8282ad5b6 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -393,6 +393,7 @@ function dol_dir_is_emtpy($folder) * * @param string $file Filename * @return int <0 if KO, Number of lines in files if OK + * @see dol_nboflines */ function dol_count_nb_of_line($file) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 51bc92a2b47..71acdf26202 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -627,18 +627,26 @@ function dol_buildpath($path, $type=0) /** * Create a clone of instance of object (new instance with same value for properties) - * Property that are reference are also new object (true clone) + * With native = 0: Property that are reference are also new object (true clone). This means $this->db is not valid. + * With native = 1: Use PHP clone. Property that are reference are same pointer. This means $this->db is still valid. * * @param object $object Object to clone + * @param int $native Native method or true method * @return object Object clone * @see https://php.net/manual/language.oop5.cloning.php */ -function dol_clone($object) +function dol_clone($object, $native=0) { //dol_syslog(__FUNCTION__ . " is deprecated", LOG_WARNING); - //$myclone = clone $object; // PHP clone is a shallow copy only, not a real clone, so properties of references will keep references (refer to the same target/variable - $myclone=unserialize(serialize($object)); + if (empty($native)) + { + $myclone=unserialize(serialize($object)); + } + else + { + $myclone = clone $object; // PHP clone is a shallow copy only, not a real clone, so properties of references will keep references (refer to the same target/variable) + } return $myclone; } @@ -1130,7 +1138,7 @@ function dol_get_fiche_end($notab=0) * @param string $paramid Name of parameter to use to name the id into the URL next/previous link * @param string $morehtml More html content to output just before the nav bar * @param int $shownav Show Condition (navigation is shown if value is 1) - * @param string $fieldid Nom du champ en base a utiliser pour select next et previous (we make the select max and min on this field) + * @param string $fieldid Nom du champ en base a utiliser pour select next et previous (we make the select max and min on this field). Use 'none' for no prev/next search. * @param string $fieldref Nom du champ objet ref (object->ref) a utiliser pour select next et previous * @param string $morehtmlref More html to show after ref * @param string $moreparam More param to add in nav link url. @@ -1281,7 +1289,8 @@ function dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='r if ($object->element == 'project' && ! $object->public) $picto = 'project'; // instead of projectpub $nophoto=img_picto('', 'object_'.$picto, '', false, 1); } - $morehtmlleft.='
No photo
'; + $morehtmlleft.=''; + $morehtmlleft.='
No photo
'; $morehtmlleft.=''; } } @@ -2548,7 +2557,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ if ($pictoisfullpath) { // Clean parameters - if (! preg_match('/(\.png|\.gif)$/i',$picto)) $picto .= '.png'; + if (! preg_match('/(\.png|\.gif|\.svg)$/i',$picto)) $picto .= '.png'; $fullpathpicto = $picto; } else @@ -2570,7 +2579,7 @@ function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $ } // Clean parameters - if (! preg_match('/(\.png|\.gif)$/i',$picto)) $picto .= '.png'; + if (! preg_match('/(\.png|\.gif|\.svg)$/i',$picto)) $picto .= '.png'; // If alt path are defined, define url where img file is, according to physical path foreach ($conf->file->dol_document_root as $type => $dirroot) // ex: array(["main"]=>"/home/maindir/htdocs", ["alt0"]=>"/home/moddir0/htdocs", ...) { @@ -4769,22 +4778,57 @@ function dol_string_nohtmltag($StringHtml,$removelinefeed=1,$pagecodeto='UTF-8') * Return first line of text. Cut will depends if content is HTML or not. * * @param string $text Input text + * @param int $nboflines Nb of lines to get (default is 1 = first line only) * @return string Output text * @see dol_nboflines_bis, dol_string_nohtmltag, dol_escape_htmltag */ -function dolGetFirstLineOfText($text) +function dolGetFirstLineOfText($text, $nboflines=1) { - if (dol_textishtml($text)) + if ($nboflines == 1) { - $firstline=preg_replace('/]*>.*$/s','',$text); // The s pattern modifier means the . can match newline characters - $firstline=preg_replace('/]*>.*$/s','',$firstline); // The s pattern modifier means the . can match newline characters + if (dol_textishtml($text)) + { + $firstline=preg_replace('/]*>.*$/s','',$text); // The s pattern modifier means the . can match newline characters + $firstline=preg_replace('/]*>.*$/s','',$firstline); // The s pattern modifier means the . can match newline characters + } + else + { + $firstline=preg_replace('/[\n\r].*/','',$text); + } + return $firstline.((strlen($firstline) != strlen($text))?'...':''); } else { - $firstline=preg_replace('/[\n\r].*/','',$text); + $ishtml=0; + if (dol_textishtml($text)) + { + $text=preg_replace('/\n/','',$text); + $ishtml=1; + $repTable = array("\t" => " ", "\n" => " ", "\r" => " ", "\0" => " ", "\x0B" => " "); + } + else + { + $repTable = array("\t" => " ", "\n" => "
", "\r" => " ", "\0" => " ", "\x0B" => " "); + } + + $text = strtr($text, $repTable); + if ($charset == 'UTF-8') { $pattern = '/(]*>)/Uu'; } // /U is to have UNGREEDY regex to limit to one html tag. /u is for UTF8 support + else $pattern = '/(]*>)/U'; // /U is to have UNGREEDY regex to limit to one html tag. + $a = preg_split($pattern, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + + $firstline=''; + $i=0; + $nba = count($a); // 2x nb of lines in $a because $a contains also a line for each new line separator + while (($i < $nba) && ($i < ($nboflines * 2))) + { + if ($i % 2 == 0) $firstline .= $a[$i]; + elseif (($i < (($nboflines * 2) - 1)) && ($i < ($nba - 1))) $firstline .= ($ishtml?"
\n":"\n"); + $i++; + } + unset($a); + return $firstline.(($i < $nba)?'...':''); } - return $firstline.((strlen($firstline) != strlen($text))?'...':''); } @@ -4946,7 +4990,7 @@ function dol_nboflines($s,$maxchar=0) /** - * Return nb of lines of a formated text with \n and
(we can't have both \n and br) + * Return nb of lines of a formated text with \n and
(WARNING: string must not have mixed \n and br separators) * * @param string $text Text * @param int $maxlinesize Largeur de ligne en caracteres (ou 0 si pas de limite - defaut) @@ -4982,6 +5026,8 @@ function dol_nboflines_bis($text,$maxlinesize=0,$charset='UTF-8') } } } + + unset($a); return $nblines; } diff --git a/htdocs/core/lib/modulebuilder.lib.php b/htdocs/core/lib/modulebuilder.lib.php index 0741dcef978..1df10e6a9c7 100644 --- a/htdocs/core/lib/modulebuilder.lib.php +++ b/htdocs/core/lib/modulebuilder.lib.php @@ -77,8 +77,8 @@ function rebuildObjectClass($destdir, $module, $objectname, $newmask) $i++; $typephp=''; $texttoinsert.= "\t\t'".$key."' => array('type'=>'".$val['type']."', 'label'=>'".$val['label']."',"; - $texttoinsert.= " 'visible'=>".$val['visible'].","; - $texttoinsert.= " 'enabled'=>".$val['enabled'].","; + $texttoinsert.= " 'visible'=>".($val['visible']?$val['visible']:0).","; + $texttoinsert.= " 'enabled'=>".($val['enabled']?$val['enabled']:0).","; if ($val['position']) $texttoinsert.= " 'position'=>".$val['position'].","; if ($val['notnull']) $texttoinsert.= " 'notnull'=>".$val['notnull'].","; if ($val['index']) $texttoinsert.= " 'index'=>".$val['index'].","; diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 98bd412abc2..a3f8676fb65 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -1447,55 +1447,55 @@ class DolibarrModules // Can not be abstract, because we need to insta * * @return int Error count (0 if ok) */ - function insert_tabs() - { - global $conf; + function insert_tabs() + { + global $conf; - $err=0; + $err=0; - if (! empty($this->tabs)) - { - $i=0; - foreach ($this->tabs as $key => $value) - { - if (is_array($value) && count($value) == 0) continue; // Discard empty arrays + if (! empty($this->tabs)) + { + $i=0; + foreach ($this->tabs as $key => $value) + { + if (is_array($value) && count($value) == 0) continue; // Discard empty arrays - $entity=$conf->entity; - $newvalue = $value; + $entity=$conf->entity; + $newvalue = $value; - if (is_array($value)) - { - $newvalue = $value['data']; - if (isset($value['entity'])) $entity = $value['entity']; - } + if (is_array($value)) + { + $newvalue = $value['data']; + if (isset($value['entity'])) $entity = $value['entity']; + } - if ($newvalue) - { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."const ("; - $sql.= "name"; - $sql.= ", type"; - $sql.= ", value"; - $sql.= ", note"; - $sql.= ", visible"; - $sql.= ", entity"; - $sql.= ")"; - $sql.= " VALUES ("; - $sql.= $this->db->encrypt($this->const_name."_TABS_".$i,1); - $sql.= ", 'chaine'"; - $sql.= ", ".$this->db->encrypt($value,1); - $sql.= ", null"; - $sql.= ", '0'"; - $sql.= ", ".$conf->entity; - $sql.= ")"; + if ($newvalue) + { + $sql = "INSERT INTO ".MAIN_DB_PREFIX."const ("; + $sql.= "name"; + $sql.= ", type"; + $sql.= ", value"; + $sql.= ", note"; + $sql.= ", visible"; + $sql.= ", entity"; + $sql.= ")"; + $sql.= " VALUES ("; + $sql.= $this->db->encrypt($this->const_name."_TABS_".$i,1); + $sql.= ", 'chaine'"; + $sql.= ", ".$this->db->encrypt($newvalue,1); + $sql.= ", null"; + $sql.= ", '0'"; + $sql.= ", ".$entity; + $sql.= ")"; - dol_syslog(get_class($this)."::insert_tabs", LOG_DEBUG); - $this->db->query($sql); - } - $i++; - } - } - return $err; - } + dol_syslog(get_class($this)."::insert_tabs", LOG_DEBUG); + $this->db->query($sql); + } + $i++; + } + } + return $err; + } /** * Adds constants diff --git a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php index 64d0da9b5fd..f9dac51389f 100644 --- a/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php +++ b/htdocs/core/modules/contract/doc/doc_generic_contract_odt.modules.php @@ -211,7 +211,7 @@ class doc_generic_contract_odt extends ModelePDFContract if (! is_object($object)) { $id = $object; - $object = new Contract($this->db); + $object = new Contrat($this->db); $result=$object->fetch($id); if ($result < 0) { diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php index da35434a34f..226679d7d00 100644 --- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php +++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php @@ -1,13 +1,13 @@ * Copyright (C) 2005-2012 Regis Houssin - * Copyright (C) 2008 Raphael Bertrand + * Copyright (C) 2008 Raphael Bertrand * Copyright (C) 2010-2014 Juanjo Menent - * Copyright (C) 2012 Christophe Battarel - * Copyright (C) 2012 Cédric Salvador - * Copyright (C) 2012-2014 Raphaël Doursenaud - * Copyright (C) 2015 Marcos García - * Copyright (C) 2017 Ferran Marcet + * Copyright (C) 2012 Christophe Battarel + * Copyright (C) 2012 Cédric Salvador + * Copyright (C) 2012-2014 Raphaël Doursenaud + * Copyright (C) 2015 Marcos García + * Copyright (C) 2017 Ferran Marcet * * 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 @@ -1576,7 +1576,7 @@ class pdf_crabe extends ModelePDFFactures if ($object->statut == Facture::STATUS_DRAFT) { $pdf->SetTextColor(128,0,0); - $textref.=' - '.$outputlangs->trans("NotValidated"); + $textref.=' - '.$outputlangs->transnoentities("NotValidated"); } $pdf->MultiCell($w, 4, $textref, '', 'R'); @@ -1663,7 +1663,7 @@ class pdf_crabe extends ModelePDFFactures $posy+=4; $pdf->SetXY($posx,$posy); $pdf->SetTextColor(0,0,60); - $pdf->MultiCell($w, 3, $langs->trans("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); + $pdf->MultiCell($w, 3, $langs->transnoentities("SalesRepresentative")." : ".$usertmp->getFullName($langs), '', 'R'); } } diff --git a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php index 0339f2ea255..130aa90ecfd 100644 --- a/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php +++ b/htdocs/core/modules/propale/doc/doc_generic_proposal_odt.modules.php @@ -167,7 +167,7 @@ class doc_generic_proposal_odt extends ModelePDFPropales $texte.=$file['name'].'
'; } $texte.='
'; - + if ($conf->global->MAIN_PROPAL_CHOOSE_ODT_DOCUMENT > 0) { // Model for creation @@ -252,7 +252,7 @@ class doc_generic_proposal_odt extends ModelePDFPropales if (! is_object($object)) { $id = $object; - $object = new Propale($this->db); + $object = new Propal($this->db); $result=$object->fetch($id); if ($result < 0) { diff --git a/htdocs/core/tpl/bloc_showhide.tpl.php b/htdocs/core/tpl/bloc_showhide.tpl.php index 2c5d71c79d5..80b928815cb 100644 --- a/htdocs/core/tpl/bloc_showhide.tpl.php +++ b/htdocs/core/tpl/bloc_showhide.tpl.php @@ -21,43 +21,45 @@ if (isset($parameters['showblocbydefault'])) $hide=(empty($parameters['showblocb if (isset($object->extraparams[$blocname]['showhide'])) $hide = (empty($object->extraparams[$blocname]['showhide']) ? true : false); ?> + - +'."\n"; +print '$(document).ready(function() {'."\n"; +print '$("#hide-'.$blocname.'").click(function(){'."\n"; +print ' setShowHide(0);'."\n"; +print ' $("#'.$blocname.'_bloc").hide("blind", {direction: "vertical"}, 300).removeClass("nohideobject");'."\n"; +print ' $(this).hide();'."\n"; +print ' $("#show-'.$blocname.'").show();'."\n"; +print '});'."\n"; - +print 'function setShowHide(status) {'."\n"; +print ' var id = '.$object->id.";\n"; +print " var element = '".$object->element."';\n"; +print " var htmlelement = '".$blocname."';\n"; +print ' var type = "showhide";'."\n"; +print ' $.get("'.dol_buildpath('/core/ajax/extraparams.php', 1); +print '?id="+id+"&element="+element+"&htmlelement="+htmlelement+"&type="+type+"&value="+status);'."\n"; +print '}'."\n"; -
-
-
+print '});'."\n"; +print ''."\n"; -
+print '
'.img_picto('', '1uparrow.png').'
'."\n"; +print '
'.img_picto('', '1downarrow.png').'
'."\n"; +print '
'.$title.'
'."\n"; +print '
'."\n"; - - -
-
- - \ No newline at end of file +include DOL_DOCUMENT_ROOT.'/core/tpl/'.$blocname.'.tpl.php'; +print '

'; +?> + diff --git a/htdocs/core/tpl/notes.tpl.php b/htdocs/core/tpl/notes.tpl.php index 2538e052ae4..87071e94203 100644 --- a/htdocs/core/tpl/notes.tpl.php +++ b/htdocs/core/tpl/notes.tpl.php @@ -1,7 +1,7 @@ - * Copyright (C) 2013 Florian Henry - * Copyright (C) 2014 Laurent Destailleur +/* Copyright (C) 2012 Regis Houssin + * Copyright (C) 2013 Florian Henry + * Copyright (C) 2014-2017 Laurent Destailleur * * 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 @@ -17,9 +17,10 @@ * along with this program. If not, see . */ -// $cssclass must be defined by caller. For example cssclass='fieldtitle" -$module = $object->element; -$note_public = 'note_public'; +// $permission must be defined by caller. +// $cssclass must be defined by caller. For example cssclass='fieldtitle" +$module = $object->element; +$note_public = 'note_public'; $note_private = 'note_private'; $colwidth=(isset($colwidth)?$colwidth:(empty($cssclass)?'25':'')); diff --git a/htdocs/fichinter/card.php b/htdocs/fichinter/card.php index 953b48a8adf..8035c2a2e98 100644 --- a/htdocs/fichinter/card.php +++ b/htdocs/fichinter/card.php @@ -1577,7 +1577,7 @@ else if ($id > 0 || ! empty($ref)) { if ($action != 'editdescription' && ($action != 'presend')) { // Validate - if ($object->statut == 0 && (count($object->lines) > 0 || !empty($conf->global->FICHINTER_DISABLE_DETAILS))) { + if ($object->statut == Fichinter::STATUS_DRAFT && (count($object->lines) > 0 || !empty($conf->global->FICHINTER_DISABLE_DETAILS))) { if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->creer) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->ficheinter_advance->validate)) { print ''; @@ -1585,7 +1585,7 @@ else if ($id > 0 || ! empty($ref)) } // Modify - if ($object->statut == 1 && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->creer) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->ficheinter_advance->unvalidate))) + if ($object->statut == Fichinter::STATUS_VALIDATED && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->creer) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->ficheinter->ficheinter_advance->unvalidate))) { print '
'; if (empty($conf->global->FICHINTER_DISABLE_DETAILS)) print $langs->trans("Modify"); @@ -1594,7 +1594,7 @@ else if ($id > 0 || ! empty($ref)) } // Send - if ($object->statut > 0) + if ($object->statut > Fichinter::STATUS_DRAFT) { if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->ficheinter->ficheinter_advance->send) { @@ -1606,10 +1606,10 @@ else if ($id > 0 || ! empty($ref)) // Event agenda if (! empty($conf->global->FICHINTER_ADDLINK_TO_EVENT)) { - if (! empty($conf->agenda->enabled) && $object->statut > 0) + if (! empty($conf->agenda->enabled) && $object->statut > Fichinter::STATUS_DRAFT) { $langs->load("agenda"); - if ($object->statut < 2) + if ($object->statut < Fichinter::STATUS_BILLED) { if ($user->rights->agenda->myactions->create) print ''; else print ''; @@ -1618,10 +1618,10 @@ else if ($id > 0 || ! empty($ref)) } // Proposal - if (! empty($conf->propal->enabled) && $object->statut > 0) + if (! empty($conf->propal->enabled) && $object->statut > Fichinter::STATUS_DRAFT) { $langs->load("propal"); - if ($object->statut < 2) + if ($object->statut < Fichinter::STATUS_BILLED) { if ($user->rights->propal->creer) print ''; else print ''; @@ -1629,10 +1629,10 @@ else if ($id > 0 || ! empty($ref)) } // Invoicing - if (! empty($conf->facture->enabled) && $object->statut > 0) + if (! empty($conf->facture->enabled) && $object->statut > Fichinter::STATUS_DRAFT) { $langs->load("bills"); - if ($object->statut < 2) + if ($object->statut < Fichinter::STATUS_BILLED) { if ($user->rights->facture->creer) print ''; else print ''; @@ -1640,7 +1640,7 @@ else if ($id > 0 || ! empty($ref)) if (! empty($conf->global->FICHINTER_CLASSIFY_BILLED)) // Option deprecated. In a future, billed must be managed with a dedicated field to 0 or 1 { - if ($object->statut != 2) + if ($object->statut != Fichinter::STATUS_BILLED) { print ''; } @@ -1652,7 +1652,7 @@ else if ($id > 0 || ! empty($ref)) } // Done - if (empty($conf->global->FICHINTER_CLASSIFY_BILLED) && $object->statut > 0 && $object->statut < 3) + if (empty($conf->global->FICHINTER_CLASSIFY_BILLED) && $object->statut > Fichinter::STATUS_DRAFT && $object->statut < Fichinter::STATUS_CLOSED) { print ''; } @@ -1663,7 +1663,7 @@ else if ($id > 0 || ! empty($ref)) } // Delete - if (($object->statut == 0 && $user->rights->ficheinter->creer) || $user->rights->ficheinter->supprimer) + if (($object->statut == Fichinter::STATUS_DRAFT && $user->rights->ficheinter->creer) || $user->rights->ficheinter->supprimer) { print ''; diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index 6142d87de7a..eaf10c357e4 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -39,7 +39,7 @@ class Fichinter extends CommonObject public $fk_element='fk_fichinter'; public $table_element_line='fichinterdet'; public $picto = 'intervention'; - + /** * {@inheritdoc} */ @@ -62,6 +62,23 @@ class Fichinter extends CommonObject var $lines = array(); + /** + * Draft status + */ + const STATUS_DRAFT = 0; + /** + * Validated status + */ + const STATUS_VALIDATED = 1; + /** + * Billed + */ + const STATUS_BILLED = 2; + /** + * Closed + */ + const STATUS_CLOSED = 3; + /** * Constructor * @@ -361,7 +378,7 @@ class Fichinter extends CommonObject $this->fk_contrat = $obj->fk_contrat; $this->user_creation= $obj->fk_user_author; - + $this->extraparams = (array) json_decode($obj->extraparams, true); if ($this->statut == 0) $this->brouillon = 1; @@ -546,23 +563,23 @@ class Fichinter extends CommonObject */ function getAmount() { global $db; - + $amount = 0; - + $this->author = new User($db); $this->author->fetch($this->user_creation); - + $thm = $this->author->thm; - + foreach($this->lines as &$line) { - + $amount+=$line->qty * $thm; - + } - + return $amount; } - + /** * Returns the label status * @@ -599,7 +616,7 @@ class Fichinter extends CommonObject return ''.$langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]),$this->statuts_logo[$statut]); if ($mode == 6) return ''.$langs->trans($this->statuts[$statut]).' '.img_picto($langs->trans($this->statuts[$statut]),$this->statuts_logo[$statut]); - + return ''; } @@ -949,7 +966,7 @@ class Fichinter extends CommonObject return -2; } - + /** * Load an object from its id and create a new one in database @@ -1001,7 +1018,7 @@ class Fichinter extends CommonObject $this->date_creation = ''; $this->date_validation = ''; $this->ref_client = ''; - + // Create clone $result=$this->create($user); if ($result < 0) $error++; @@ -1013,7 +1030,7 @@ class Fichinter extends CommonObject { $this->addline($user, $this->id, $line->desc, $line->datei, $line->duration); } - + // Hook of thirdparty module if (is_object($hookmanager)) { @@ -1043,8 +1060,8 @@ class Fichinter extends CommonObject return -1; } } - - + + /** * Adding a line of intervention into data base * diff --git a/htdocs/fichinter/list.php b/htdocs/fichinter/list.php index 853506920b3..75f151d0850 100644 --- a/htdocs/fichinter/list.php +++ b/htdocs/fichinter/list.php @@ -249,16 +249,16 @@ $sql.= $db->plimit($limit+1, $offset); $resql=$db->query($sql); if ($resql) { - $num = $db->num_rows($result); - + $num = $db->num_rows($resql); + + $arrayofselected=is_array($toselect)?$toselect:array(); + if ($socid > 0) { $soc = new Societe($db); $soc->fetch($socid); if (empty($search_company)) $search_company = $soc->name; } - - $arrayofselected=is_array($toselect)?$toselect:array(); $param=''; if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage; diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index 7ecd7ba45fe..fcaa024e186 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -494,7 +494,7 @@ if ($resql) if (! GETPOST('cancel')) { - $objecttmp=new FactureFourn($db); + $objecttmp=new FactureFournisseur($db); $listofselectedid=array(); $listofselectedthirdparties=array(); $listofselectedref=array(); diff --git a/htdocs/index.php b/htdocs/index.php index 187273ef2b4..9b190ac1e2b 100644 --- a/htdocs/index.php +++ b/htdocs/index.php @@ -448,7 +448,7 @@ if (! empty($conf->facture->enabled) && $user->rights->facture->lire) } // Number of supplier invoices (has paid) -if (! empty($conf->supplier_invoice->enabled) && ! empty($conf->facture->enabled) && $user->rights->facture->lire) +if (! empty($conf->supplier_invoice->enabled) && ! empty($user->rights->fournisseur->facture->lire)) { include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; $board=new FactureFournisseur($db); diff --git a/htdocs/install/mysql/migration/3.8.0-3.9.0.sql b/htdocs/install/mysql/migration/3.8.0-3.9.0.sql index 03ff8c76d93..48a6b191ebf 100644 --- a/htdocs/install/mysql/migration/3.8.0-3.9.0.sql +++ b/htdocs/install/mysql/migration/3.8.0-3.9.0.sql @@ -611,3 +611,7 @@ INSERT INTO llx_c_tva(rowid,fk_pays,taux,recuperableonly,note,active) VALUES (14 -- VMYSQL4.1 ALTER TABLE llx_c_type_resource CHANGE COLUMN rowid rowid integer NOT NULL AUTO_INCREMENT; ALTER TABLE llx_import_model MODIFY COLUMN type varchar(50); + +-- Negative buying prices + +UPDATE llx_facturedet SET buy_price_ht = ABS(buy_price_ht) diff --git a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql index 6f6df0898e2..b0176244a6f 100644 --- a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql +++ b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql @@ -32,6 +32,18 @@ ALTER TABLE llx_website_page MODIFY COLUMN pageurl varchar(255); ALTER TABLE llx_website_page ADD COLUMN lang varchar(6); ALTER TABLE llx_website_page ADD COLUMN fk_page integer; +ALTER TABLE llx_fichinter ADD COLUMN import_key varchar(14); +ALTER TABLE llx_livraison ADD COLUMN import_key varchar(14); +ALTER TABLE llx_livraison ADD COLUMN extraparams varchar(255); +ALTER TABLE llx_don ADD COLUMN extraparams varchar(255); + +ALTER TABLE llx_accounting_account ADD COLUMN import_key varchar(14); +ALTER TABLE llx_accounting_account ADD COLUMN extraparams varchar(255); +ALTER TABLE llx_accounting_bookkeeping ADD COLUMN import_key varchar(14); +ALTER TABLE llx_accounting_bookkeeping ADD COLUMN extraparams varchar(255); + +ALTER TABLE llx_accounting_bookkeeping ADD COLUMN date_lim_reglement datetime; + ALTER TABLE llx_c_paiement DROP PRIMARY KEY; ALTER TABLE llx_c_paiement ADD COLUMN entity integer DEFAULT 1 NOT NULL AFTER id; ALTER TABLE llx_c_paiement DROP INDEX uk_c_paiement; diff --git a/htdocs/install/mysql/tables/llx_accounting_account.sql b/htdocs/install/mysql/tables/llx_accounting_account.sql index 8abd342cee5..b65863afe3f 100644 --- a/htdocs/install/mysql/tables/llx_accounting_account.sql +++ b/htdocs/install/mysql/tables/llx_accounting_account.sql @@ -35,4 +35,6 @@ create table llx_accounting_account fk_user_author integer DEFAULT NULL, fk_user_modif integer DEFAULT NULL, active tinyint DEFAULT 1 NOT NULL + import_key varchar(14), + extraparams varchar(255) -- for other parameters with json format )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_accounting_bookkeeping.sql b/htdocs/install/mysql/tables/llx_accounting_bookkeeping.sql index f33db4be484..e9a4921a840 100644 --- a/htdocs/install/mysql/tables/llx_accounting_bookkeeping.sql +++ b/htdocs/install/mysql/tables/llx_accounting_bookkeeping.sql @@ -40,14 +40,16 @@ CREATE TABLE llx_accounting_bookkeeping multicurrency_code varchar(255), -- FEC:Idevise lettering_code varchar(255), -- FEC:EcritureLet date_lettering datetime, -- FEC:DateLet + date_lim_reglement datetime, -- | date limite de reglement fk_user_author integer NOT NULL, -- | user creating fk_user_modif integer, -- | user making last change date_creation datetime, -- FEC:EcritureDate | creation date tms timestamp, -- | date last modification - import_key varchar(14), code_journal varchar(32) NOT NULL, -- FEC:JournalCode journal_label varchar(255), -- FEC:JournalLib piece_num integer NOT NULL, -- FEC:EcritureNum validated tinyint DEFAULT 0 NOT NULL, -- | 0 line not validated / 1 line validated (No deleting / No modification) date_validated datetime -- FEC:ValidDate + import_key varchar(14), + extraparams varchar(255) -- for other parameters with json format ) ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.sql b/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.sql index 9ead8c6c6ba..e49c937d6ed 100644 --- a/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.sql +++ b/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.sql @@ -40,6 +40,7 @@ CREATE TABLE llx_accounting_bookkeeping_tmp multicurrency_code varchar(255), -- FEC:Idevise lettering_code varchar(255), -- FEC:EcritureLet date_lettering datetime, -- FEC:DateLet + date_lim_reglement datetime, -- | date limite de reglement fk_user_author integer NOT NULL, -- | user creating fk_user_modif integer, -- | user making last change date_creation datetime, -- FEC:EcritureDate | creation date diff --git a/htdocs/install/mysql/tables/llx_don.sql b/htdocs/install/mysql/tables/llx_don.sql index b7b7c89f9cd..e2fbdba9efb 100644 --- a/htdocs/install/mysql/tables/llx_don.sql +++ b/htdocs/install/mysql/tables/llx_don.sql @@ -51,5 +51,6 @@ create table llx_don note_private text, note_public text, model_pdf varchar(255), - import_key varchar(14) + import_key varchar(14), + extraparams varchar(255) -- for other parameters with json format )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_extrafields.sql b/htdocs/install/mysql/tables/llx_extrafields.sql index aee51524e6f..101254ea186 100644 --- a/htdocs/install/mysql/tables/llx_extrafields.sql +++ b/htdocs/install/mysql/tables/llx_extrafields.sql @@ -37,5 +37,9 @@ create table llx_extrafields param text, -- extra parameters to define possible values of field list integer DEFAULT 0, -- list of values for field that are combo lists langs varchar(24), -- example: fileofmymodule@mymodule - ishidden integer DEFAULT 0 -- ??? example of use case ??? + ishidden integer DEFAULT 0, -- Can be foreign key of external system + fk_user_author integer, -- user making creation + fk_user_modif integer, -- user making last change + datec datetime, -- date de creation + tms timestamp )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_fichinter.sql b/htdocs/install/mysql/tables/llx_fichinter.sql index 926a05a738e..0ec67d6585c 100644 --- a/htdocs/install/mysql/tables/llx_fichinter.sql +++ b/htdocs/install/mysql/tables/llx_fichinter.sql @@ -31,8 +31,8 @@ create table llx_fichinter date_valid datetime, -- date de validation datei date, -- date de livraison du bon d'intervention fk_user_author integer, -- user making creation - fk_user_modif integer, -- user making last change - fk_user_valid integer, -- valideur de la fiche + fk_user_modif integer, -- user making last change + fk_user_valid integer, -- user validating record fk_statut smallint DEFAULT 0, dateo date, -- date de début d'intervention datee date, -- date de fin d'intervention @@ -42,5 +42,6 @@ create table llx_fichinter note_private text, note_public text, model_pdf varchar(255), - extraparams varchar(255) -- for stock other parameters with json format + import_key varchar(14), + extraparams varchar(255) -- for other parameters with json format )ENGINE=innodb; diff --git a/htdocs/install/mysql/tables/llx_livraison.sql b/htdocs/install/mysql/tables/llx_livraison.sql index c999cfdb3c2..6b09303f94d 100644 --- a/htdocs/install/mysql/tables/llx_livraison.sql +++ b/htdocs/install/mysql/tables/llx_livraison.sql @@ -41,6 +41,8 @@ create table llx_livraison note_public text, model_pdf varchar(255), fk_incoterms integer, -- for incoterms - location_incoterms varchar(255) -- for incoterms - + location_incoterms varchar(255), -- for incoterms + + import_key varchar(14), + extraparams varchar(255) -- for other parameters with json format )ENGINE=innodb; diff --git a/htdocs/install/pgsql/functions/functions.sql b/htdocs/install/pgsql/functions/functions.sql index 06ef2ed41e3..e5b9d47a0ba 100644 --- a/htdocs/install/pgsql/functions/functions.sql +++ b/htdocs/install/pgsql/functions/functions.sql @@ -165,6 +165,7 @@ CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_usergroup_extrafield CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_product_price_by_qty FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_website FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_website_page FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); +CREATE TRIGGER update_customer_modtime BEFORE UPDATE ON llx_extrafields FOR EACH ROW EXECUTE PROCEDURE update_modified_column_tms(); -- Add triggers for timestamp fields named date_m diff --git a/htdocs/install/step1.php b/htdocs/install/step1.php index a8d17388d41..bf2caf1b255 100644 --- a/htdocs/install/step1.php +++ b/htdocs/install/step1.php @@ -423,13 +423,11 @@ if (! $error && $db->connected && $action == "set") // Les documents sont en dehors de htdocs car ne doivent pas pouvoir etre telecharges en passant outre l'authentification $dir[0] = $main_data_dir."/mycompany"; $dir[1] = $main_data_dir."/users"; - $dir[2] = $main_data_dir."/custom"; - $dir[3] = $main_data_dir."/facture"; - $dir[4] = $main_data_dir."/propale"; - $dir[5] = $main_data_dir."/ficheinter"; - $dir[6] = $main_data_dir."/produit"; - $dir[7] = $main_data_dir."/doctemplates"; - $dir[7] = $main_data_dir."/extensions"; + $dir[2] = $main_data_dir."/facture"; + $dir[3] = $main_data_dir."/propale"; + $dir[4] = $main_data_dir."/ficheinter"; + $dir[5] = $main_data_dir."/produit"; + $dir[6] = $main_data_dir."/doctemplates"; // Boucle sur chaque repertoire de dir[] pour les creer s'ils nexistent pas $num=count($dir); diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 4f6926b4aed..42bc2ff925a 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -794,6 +794,7 @@ HRAndBank=HR and Bank AutomaticallyCalculated=Automatically calculated TitleSetToDraft=Go back to draft ConfirmSetToDraft=Are you sure you want to go back to Draft status ? +ImportId=Import id # Week day Monday=Monday Tuesday=Tuesday diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 063e1c8d332..9b3ad61a310 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -25,13 +25,13 @@ EnterNameOfObjectToDeleteDesc=You can delete an object. WARNING: All files relat DangerZone=Danger zone BuildPackage=Build package/documentation BuildDocumentation=Build documentation -ModuleIsNotActive=This module was not activated yet. Ggo into %s to make it live or click here: +ModuleIsNotActive=This module was not activated yet. Go into %s to make it live or click here: ModuleIsLive=This module has been activated. Any change on it may break a current active feature. DescriptionLong=Long description EditorName=Name of editor EditorUrl=URL of editor DescriptorFile=Descriptor file of module -ClassFile=File for PHP class +ClassFile=File for PHP DAO CRUD class ApiClassFile=File for PHP API class PageForList=PHP page for list of record PageForCreateEditView=PHP page to create/edit/view a record @@ -50,8 +50,10 @@ HooksFile=File for hooks code WidgetFile=Widget file ReadmeFile=Readme file ChangeLog=ChangeLog file +TestClassFile=File for PHP Unit Test class SqlFile=Sql file SqlFileExtraFields=Sql file for complementary attributes SqlFileKey=Sql file for keys AnObjectAlreadyExistWithThisNameAndDiffCase=An object already exists with this name and a different case -UseAsciiDocFormat=You can use Markdown format, but it is recommanded to use Asciidoc format (Comparison between .md and .asciidoc: http://asciidoctor.org/docs/user-manual/#compared-to-markdown) \ No newline at end of file +UseAsciiDocFormat=You can use Markdown format, but it is recommanded to use Asciidoc format (Comparison between .md and .asciidoc: http://asciidoctor.org/docs/user-manual/#compared-to-markdown) +IsAMeasure=Is a measure \ No newline at end of file diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang index 07d7268a8f0..c62d08412ce 100644 --- a/htdocs/langs/en_US/orders.lang +++ b/htdocs/langs/en_US/orders.lang @@ -118,6 +118,7 @@ SecondApprovalAlreadyDone=Second approval already done SupplierOrderReceivedInDolibarr=Supplier order %s received %s SupplierOrderSubmitedInDolibarr=Supplier order %s submited SupplierOrderClassifiedBilled=Supplier order %s set billed +OtherOrders=Other orders ##### Types de contacts ##### TypeContact_commande_internal_SALESREPFOLL=Representative following-up customer order TypeContact_commande_internal_SHIPPING=Representative following-up shipping diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang index e519f7af405..bd52f5dcaa2 100644 --- a/htdocs/langs/en_US/other.lang +++ b/htdocs/langs/en_US/other.lang @@ -18,6 +18,7 @@ NextMonthOfInvoice=Following month (number 1-12) of invoice date TextNextMonthOfInvoice=Following month (text) of invoice date ZipFileGeneratedInto=Zip file generated into %s. DocFileGeneratedInto=Doc file generated into %s. +JumpToLogin=Disconnected. Go to login page... YearOfInvoice=Year of invoice date PreviousYearOfInvoice=Previous year of invoice date diff --git a/htdocs/langs/en_US/propal.lang b/htdocs/langs/en_US/propal.lang index 61a8d4ff99c..2cbbc509076 100644 --- a/htdocs/langs/en_US/propal.lang +++ b/htdocs/langs/en_US/propal.lang @@ -64,6 +64,7 @@ ProposalLine=Proposal line AvailabilityPeriod=Availability delay SetAvailability=Set availability delay AfterOrder=after order +OtherProposals=Other proposals ##### Availability ##### AvailabilityTypeAV_NOW=Immediate AvailabilityTypeAV_1W=1 week diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 460665255b1..11c013cb768 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -69,6 +69,7 @@ NoPredefinedProductToDispatch=No predefined products for this object. So no disp DispatchVerb=Dispatch StockLimitShort=Limit for alert StockLimit=Stock limit for alert +StockLimitDesc="" (empty) default value means no alert.
"0" can be used with 'Stock can be negative' configuration. PhysicalStock=Physical stock RealStock=Real Stock RealStockDesc=Physical or real stock is the stock you currently have into your internal warehouses/emplacements. @@ -192,4 +193,4 @@ InventoryFlushed=Inventory flushed ExitEditMode=Exit edition inventoryDeleteLine=Delete line RegulateStock=Regulate Stock -ListInventory=List +ListInventory=List \ No newline at end of file diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index 1edc67d582f..090a35d6c83 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -457,9 +457,7 @@ if (! defined('NOLOGIN')) $passwordtotest = GETPOST('password','none',2); $entitytotest = (GETPOST('entity','int') ? GETPOST('entity','int') : (!empty($conf->entity) ? $conf->entity : 1)); - // Validation of login/pass/entity - // If ok, the variable login will be returned - // If error, we will put error message in session under the name dol_loginmesg + // Define if we received data to test the login. $goontestloop=false; if (isset($_SERVER["REMOTE_USER"]) && in_array('http',$authmode)) $goontestloop=true; if ($dolibarr_main_authentication == 'forceuser' && ! empty($dolibarr_auto_user)) $goontestloop=true; @@ -473,6 +471,9 @@ if (! defined('NOLOGIN')) $langs->setDefaultLang($langcode); } + // Validation of login/pass/entity + // If ok, the variable login will be returned + // If error, we will put error message in session under the name dol_loginmesg if ($test && $goontestloop) { $login = checkLoginPassEntity($usertotest,$passwordtotest,$entitytotest,$authmode); @@ -531,9 +532,10 @@ if (! defined('NOLOGIN')) // End test login / passwords if (! $login || (in_array('ldap',$authmode) && empty($passwordtotest))) // With LDAP we refused empty password because some LDAP are "opened" for anonymous access so connexion is a success. { - // We show login page + // No data to test login, so we show the login page dol_syslog("--- Access to ".$_SERVER["PHP_SELF"]." showing the login form and exit"); - dol_loginfunction($langs,$conf,(! empty($mysoc)?$mysoc:'')); + if (defined('NOREDIRECTBYMAINTOLOGIN')) return 'ERROR_NOT_LOGGED'; + else dol_loginfunction($langs,$conf,(! empty($mysoc)?$mysoc:'')); exit; } diff --git a/htdocs/master.inc.php b/htdocs/master.inc.php index fc1c41895a4..a8d068cfd7d 100644 --- a/htdocs/master.inc.php +++ b/htdocs/master.inc.php @@ -160,10 +160,6 @@ else if (defined('DOLENTITY') && is_numeric(DOLENTITY)) // For public page wit { $conf->entity = DOLENTITY; } -else if (!empty($_COOKIE['DOLENTITY'])) // For other application with MultiCompany module (TODO: We should remove this. entity to use should never be stored into client side) -{ - $conf->entity = $_COOKIE['DOLENTITY']; -} // Sanitize entity if (! is_numeric($conf->entity)) $conf->entity=1; diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index f6eea45003d..4298505a18b 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -108,7 +108,11 @@ if ($dirins && $action == 'initmodule' && $modulename) // Delete some files dol_delete_file($destdir.'/myobject_card.php'); + dol_delete_file($destdir.'/myobject_note.php'); + dol_delete_file($destdir.'/myobject_document.php'); + dol_delete_file($destdir.'/myobject_agenda.php'); dol_delete_file($destdir.'/myobject_list.php'); + dol_delete_file($destdir.'/lib/myobject.lib.php'); dol_delete_file($destdir.'/test/phpunit/MyObjectTest.php'); dol_delete_file($destdir.'/sql/llx_myobject.sql'); dol_delete_file($destdir.'/sql/llx_myobject_extrafields.sql'); @@ -132,7 +136,7 @@ if ($dirins && $action == 'initmodule' && $modulename) 'MyModule'=>$modulename, 'MYMODULE'=>strtoupper($modulename), 'My module'=>$modulename, - 'htdocs/modulebuilder/template/'=>'', + 'htdocs/modulebuilder/template/'=>strtolower($modulename), '---Put here your own copyright and developer email---'=>dol_print_date($now,'%Y').' '.$user->getFullName($langs).($user->email?' <'.$user->email.'>':'') ); @@ -188,8 +192,12 @@ if ($dirins && $action == 'initobject' && $module && $objectname) // Delete some files $filetogenerate = array( 'myobject_card.php'=>strtolower($objectname).'_card.php', - 'myobject_list.php'=>strtolower($objectname).'_list.php', - 'test/phpunit/MyObjectTest.php'=>'test/phpunit/'.$objectname.'Test.php', + 'myobject_note.php'=>strtolower($objectname).'_note.php', + 'myobject_document.php'=>strtolower($objectname).'_document.php', + 'myobject_agenda.php'=>strtolower($objectname).'_agenda.php', + 'myobject_list.php'=>strtolower($objectname).'_list.php', + 'lib/myobject.lib.php'=>'lib/'.strtolower($objectname).'.lib.php', + 'test/phpunit/MyObjectTest.php'=>'test/phpunit/'.$objectname.'Test.php', 'sql/llx_myobject.sql'=>'sql/llx_'.strtolower($objectname).'.sql', 'sql/llx_myobject_extrafields.sql'=>'sql/llx_'.strtolower($objectname).'_extrafields.sql', 'sql/llx_myobject.key.sql'=>'sql/llx_'.strtolower($objectname).'.key.sql', @@ -276,7 +284,7 @@ if ($dirins && $action == 'initobject' && $module && $objectname) 'MyModule'=>$module, 'MYMODULE'=>strtoupper($module), 'My module'=>$module, - 'htdocs/modulebuilder/template/'=>'', + 'htdocs/modulebuilder/template/'=>strtolower($modulename), 'myobject'=>strtolower($objectname), 'MyObject'=>$objectname ); @@ -360,7 +368,7 @@ if ($dirins && $action == 'confirm_delete') if ($dirins && $action == 'confirm_deleteobject' && $objectname) { - if (preg_match('/\s/', $objectname)) + if (preg_match('/[^a-z0-9]/i', $objectname)) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); @@ -377,8 +385,12 @@ if ($dirins && $action == 'confirm_deleteobject' && $objectname) // Delete some files $filetogenerate = array( 'myobject_card.php'=>strtolower($objectname).'_card.php', - 'myobject_list.php'=>strtolower($objectname).'_list.php', - 'test/phpunit/MyObjectTest.php'=>'test/phpunit/'.$objectname.'Test.php', + 'myobject_note.php'=>strtolower($objectname).'_note.php', + 'myobject_document.php'=>strtolower($objectname).'_note.php', + 'myobject_agenda.php'=>strtolower($objectname).'_agenda.php', + 'myobject_list.php'=>strtolower($objectname).'_list.php', + 'lib/myobject.lib.php'=>'lib/'.strtolower($objectname).'.lib.php', + 'test/phpunit/MyObjectTest.php'=>'test/phpunit/'.$objectname.'Test.php', 'sql/llx_myobject.sql'=>'sql/llx_'.strtolower($objectname).'.sql', 'sql/llx_myobject_extrafields.sql'=>'sql/llx_'.strtolower($objectname).'_extrafields.sql', 'sql/llx_myobject.key.sql'=>'sql/llx_'.strtolower($objectname).'.key.sql', @@ -604,7 +616,11 @@ if ($action == 'savefile' && empty($cancel)) // Enable module if ($action == 'set' && $user->admin) { - $param='module='.$module; + $param=''; + if ($module) $param.='&module='.$module; + if ($tab) $param.='&tab='.$tab; + if ($tabobj) $param.='&tabobj='.$tabobj; + $value = GETPOST('value','alpha'); $resarray = activateModule($value); if (! empty($resarray['errors'])) setEventMessages('', $resarray['errors'], 'errors'); @@ -635,7 +651,11 @@ if ($action == 'set' && $user->admin) // Disable module if ($action == 'reset' && $user->admin) { - $param='module='.$module; + $param=''; + if ($module) $param.='&module='.$module; + if ($tab) $param.='&tab='.$tab; + if ($tabobj) $param.='&tabobj='.$tabobj; + $value = GETPOST('value','alpha'); $result=unActivateModule($value); if ($result) setEventMessages($result, null, 'errors'); @@ -844,7 +864,11 @@ elseif (! empty($module)) $modulelowercase=strtolower($module); $const_name = 'MAIN_MODULE_'.strtoupper($module); - $param='&tab='.$tab.'&module='.$module; + $param=''; + if ($tab) $param.= '&tab='.$tab; + if ($module) $param.='&module='.$module; + if ($tabobj) $param.='&tabobj='.$tabobj; + $urltomodulesetup=''.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").''; $linktoenabledisable=''; if (! empty($conf->global->$const_name)) // If module is already activated @@ -1198,6 +1222,7 @@ elseif (! empty($module)) $pathtoapi = strtolower($module).'/class/api_'.strtolower($tabobj).'.class.php'; $pathtolist = strtolower($module).'/'.strtolower($tabobj).'_list.php'; $pathtocard = strtolower($module).'/'.strtolower($tabobj).'_card.php'; + $pathtophpunit = strtolower($module).'/test/phpunit/'.$tabobj.'Test.php'; $pathtosql = strtolower($module).'/sql/llx_'.strtolower($tabobj).'.sql'; $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($tabobj).'_extrafields.sql'; $pathtosqlkey = strtolower($module).'/sql/llx_'.strtolower($tabobj).'.key.sql'; @@ -1208,6 +1233,9 @@ elseif (! empty($module)) print ' '.$langs->trans("ApiClassFile").' : '.$pathtoapi.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; + print ' '.$langs->trans("TestClassFile").' : '.$pathtophpunit.''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '
'; print ' '.$langs->trans("SqlFile").' : '.$pathtosql.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; @@ -1256,9 +1284,10 @@ elseif (! empty($module)) print ''.$langs->trans("NotNull").''; //print ''.$langs->trans("DefaultValue").''; print ''.$langs->trans("DatabaseIndex").''; + print ''.$langs->trans("Position").''; print ''.$langs->trans("Enabled").''; print ''.$langs->trans("Visible").''; - print ''.$langs->trans("Position").''; + print ''.$langs->trans("IsAMeasure").''; print ''.$langs->trans("SearchAll").''; print ''.$langs->trans("Comment").''; print ''; @@ -1270,9 +1299,10 @@ elseif (! empty($module)) print ''; //print ''; print ''; + print ''; print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; @@ -1300,13 +1330,14 @@ elseif (! empty($module)) $propname=$propkey; $proplabel=$propval['label']; $proptype=$propval['type']; - $propposition=$propval['position']; $propnotnull=$propval['notnull']; $propsearchall=$propval['searchall']; //$propdefault=$propval['default']; $propindex=$propval['index']; + $propposition=$propval['position']; $propenabled=$propval['enabled']; $propvisible=$propval['visible']; + $propisameasure=$propval['isameasure']; $propcomment=$propval['comment']; print ''; @@ -1329,14 +1360,17 @@ elseif (! empty($module)) print ''; print $propindex?'X':''; print ''; + print ''; + print $propposition; + print ''; print ''; print $propenabled?$propenabled:''; print ''; print ''; print $propvisible?$propvisible:''; print ''; - print ''; - print $propposition; + print ''; + print $propisameasure?$propisameasure:''; print ''; print ''; print $propsearchall?'X':''; diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index a371d5fad8a..85bc84f7458 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -55,20 +55,39 @@ class MyObject extends CommonObject /** * @var string String with name of icon for myobject */ - public $picto = 'myobject'; + public $picto = 'myobject@mymodule'; + /** + * 'type' if the field format, 'label' the translation key, 'enabled' is a condition when the filed must be managed, + * 'visible' says if field is visible in list (-1 means not shown by default but can be aded into list to be viewed) + * 'notnull' if not null in database + * 'index' if we want an index in database + * 'position' is the sort order of field + * '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). + * 'comment' is not used. You can store here any text of your choice. + */ + // BEGIN MODULEBUILDER PROPERTIES /** * @var array Array with all fields and their property */ public $fields=array( - 'ref' =>array('type'=>'varchar(64)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>true, 'index'=>true, 'visible'=>1, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'), - 'entity'=>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'notnull'=>true, 'index'=>true, 'visible'=>0, 'position'=>20), - 'label' =>array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'visible'=>1, 'searchall'=>1), - 'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'visible'=>-1, 'position'=>500), - 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'visible'=>-1, 'position'=>500), - 'status'=>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'index'=>true, 'visible'=>1, 'position'=>1000), + 'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'index'=>true, 'position'=>1, 'comment'=>'Id'), + 'ref' =>array('type'=>'varchar(64)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'notnull'=>true, 'index'=>true, 'position'=>10, 'searchall'=>1, 'comment'=>'Reference of object'), + 'entity' =>array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'notnull'=>true, 'index'=>true, 'position'=>20), + 'label' =>array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'searchall'=>1), + 'amount' =>array('type'=>'double(24,8)', 'label'=>'Amount', 'enabled'=>1, 'visible'=>1, 'position'=>40, 'searchall'=>0, 'isameasure'=>1), + 'status' =>array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>1, 'index'=>true, 'position'=>1000), + 'date_creation' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>500), + 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>500), + //'date_valid' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>500), + 'fk_user_creat' =>array('type'=>'integer', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>500), + 'fk_user_modif' =>array('type'=>'integer', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-1, 'position'=>500), + //'fk_user_valid' =>array('type'=>'integer', 'label'=>'UserValid', 'enabled'=>1, 'visible'=>-1, 'position'=>500), + 'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>true, 'position'=>500), + 'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-1, 'index'=>true, 'position'=>1000, 'nullifempty'=>1), ); // END MODULEBUILDER PROPERTIES @@ -109,18 +128,65 @@ class MyObject extends CommonObject $this->db = $db; } + /** + * 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) + { + return $this->createCommon($user, $notrigger); + } + + /** + * 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) + { + return $this->fetchCommon($id, $ref); + } + + /** + * 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) + { + 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, $trigger); + } /** * 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 - * @param int $notooltip 1=Disable tooltip - * @param int $maxlen Max length of visible user name - * @param string $morecss Add more css on link - * @return string String with URL + * @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 + * @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 */ - function getNomUrl($withpicto=0, $option='', $notooltip=0, $maxlen=24, $morecss='') + function getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1) { global $db, $conf, $langs; global $dolibarr_main_authentication, $dolibarr_main_demo; @@ -131,18 +197,27 @@ class MyObject extends CommonObject $result = ''; $companylink = ''; - $label = '' . $langs->trans("MyModule") . ''; + $label = '' . $langs->trans("MyObject") . ''; $label.= '
'; $label.= '' . $langs->trans('Ref') . ': ' . $this->ref; - $url = DOL_URL_ROOT.'/mymodule/'.$this->table_name.'_card.php?id='.$this->id; + $url=''; + if ($option != 'nolink') + { + $url = dol_buildpath('/mymodule/myobject_card.php',1).'?id='.$this->id; + + // 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("ShowProject"); + $label=$langs->trans("ShowMyObject"); $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"'; } $linkclose.=' title="'.dol_escape_htmltag($label, 1).'"'; @@ -223,6 +298,59 @@ class MyObject extends CommonObject } } + /** + * Charge les informations d'ordre info dans l'objet commande + * + * @param int $id Id of order + * @return void + */ + 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 diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index 3943e1b9314..6d9054af60b 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -129,6 +129,8 @@ class modMyModule extends DolibarrModules // Example: $this->tabs = array('objecttype:+tabname1:Title1:mylangfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1 // 'objecttype:+tabname2:SUBSTITUTION_Title2:mylangfile@mymodule:$user->rights->othermodule->read:/mymodule/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2. Label will be result of calling all substitution functions on 'Title2' key. // 'objecttype:-tabname:NU:conditiontoremove'); // To remove an existing tab identified by code tabname + // Can also be: $this->tabs = array('data'=>'...', 'entity'=>0); + // // where objecttype can be // 'categories_x' to add a tab in category view (replace 'x' by type of category (0=product, 1=supplier, 2=customer, 3=member) // 'contact' to add a tab in contact view diff --git a/htdocs/modulebuilder/template/lib/mymodule.lib.php b/htdocs/modulebuilder/template/lib/mymodule.lib.php index 3c88bcdea67..cec23bd3c11 100644 --- a/htdocs/modulebuilder/template/lib/mymodule.lib.php +++ b/htdocs/modulebuilder/template/lib/mymodule.lib.php @@ -16,11 +16,9 @@ */ /** - * \file lib/mymodule.lib.php + * \file htdocs/modulebuilder/template/lib/mymodule.lib.php * \ingroup mymodule - * \brief Example module library. - * - * Put detailed description here. + * \brief Library files with common functions for MyModule */ /** diff --git a/htdocs/modulebuilder/template/lib/myobject.lib.php b/htdocs/modulebuilder/template/lib/myobject.lib.php new file mode 100644 index 00000000000..25f85052133 --- /dev/null +++ b/htdocs/modulebuilder/template/lib/myobject.lib.php @@ -0,0 +1,70 @@ +. + */ + +/** + * \file htdocs/modulebuilder/template/lib/myobject.lib.php + * \ingroup mymodule + * \brief Library files with common functions for MyObject + */ + +/** + * Prepare array of tabs for MyObject + * + * @param MyObject $object MyObject + * @return array Array of tabs + */ +function myobjectPrepareHead($object) +{ + global $langs, $conf; + + $langs->load("mymodule@mymodule"); + + $h = 0; + $head = array(); + + $head[$h][0] = dol_buildpath("/mymodule/myobject_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_pricate'])) + { + $head[$h][0] = dol_buildpath("/mymodule/myobject_note.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Notes"); + $head[$h][2] = 'note'; + $h++; + } + $head[$h][0] = dol_buildpath("/mymodule/myobject_document.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Documents"); + $head[$h][2] = 'document'; + $h++; + $head[$h][0] = dol_buildpath("/mymodule/myobject_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:@mymodule:/mymodule/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, $object, $head, $h, 'myobject@mymodule'); + + return $head; +} diff --git a/htdocs/modulebuilder/template/mymoduleindex.php b/htdocs/modulebuilder/template/mymoduleindex.php index f1c92659f9b..c6f70b0ba85 100644 --- a/htdocs/modulebuilder/template/mymoduleindex.php +++ b/htdocs/modulebuilder/template/mymoduleindex.php @@ -41,13 +41,13 @@ if (! $res) die("Include of main fails"); require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; -if (! $user->rights->mymodule->read) accessforbidden(); - -$langs->load("mymodule@mymodule"); +$langs->loadLangs(array("mymodule@mymodule")); $action=GETPOST('action', 'alpha'); + // Securite acces client +if (! $user->rights->mymodule->read) accessforbidden(); $socid=GETPOST('socid','int'); if (isset($user->societe_id) && $user->societe_id > 0) { diff --git a/htdocs/modulebuilder/template/myobject_agenda.php b/htdocs/modulebuilder/template/myobject_agenda.php new file mode 100644 index 00000000000..8db9f0877c2 --- /dev/null +++ b/htdocs/modulebuilder/template/myobject_agenda.php @@ -0,0 +1,262 @@ + + * 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 htdocs/modulebuilder/template/myobject_agenda.php + * \ingroup mymodule + * \brief Page of MyObject events + */ + +// 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 caluclated 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('/mymodule/class/myobject.class.php'); +dol_include_once('/mymodule/lib/myobject.lib.php'); + + +// Load traductions files requiredby by page +$langs->loadLangs(array("mymodule@mymodule","other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'alpha'); +$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'); + +// Security check - Protection if external user +//if ($user->societe_id > 0) access_forbidden(); +//if ($user->societe_id > 0) $socid = $user->societe_id; +//$result = restrictedArea($user, 'mymodule', $id); + +$limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit; +$sortfield = GETPOST("sortfield",'alpha'); +$sortorder = GETPOST("sortorder",'alpha'); +$page = 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'; + +// Initialize technical objects +$object=new MyObject($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction=$conf->mymodule->dir_output . '/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('myobjectagenda')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label('myobject'); + +// 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->mymodule->multidir_output[$object->entity] . "/" . $object->id; + + + +/* + * Actions + */ + +$parameters=array('id'=>$socid); +$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") && ! 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 + */ + +$contactstatic = new Contact($db); + +$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 = myobjectPrepareHead($object); + + + dol_fiche_head($head, 'agenda', $langs->trans("MyObject"), -1, 'myobject@mymodule'); + + // 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') . ' : ' . $object->thirdparty->getNomUrl(1); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project') . ' '; + if ($user->rights->mymodule->creer) + { + 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.=''; + $morehtmlref.=$proj->ref; + $morehtmlref.=''; + } else { + $morehtmlref.=''; + } + } + }*/ + $morehtmlref.='
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
'; + print '
'; + + $object->info($object->id); + print dol_print_object_info($object, 1); + + print '
'; + + dol_fiche_end(); + + + + // Actions buttons + + $objthirdparty=$object; + $objcon=new stdClass(); + + $out=''; + $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='&socid='.$socid; + if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage; + if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit; + + + print load_fiche_titre($langs->trans("ActionsOnMyObject"),'',''); + + // List of all actions + $filters=array(); + $filters['search_agenda_label']=$search_agenda_label; + + // TODO Replace this with same code than into listactions.php + //show_actions_done($conf,$langs,$db,$object,null,0,$actioncode, '', $filters, $sortfield, $sortorder); + } +} + + +llxFooter(); + +$db->close(); diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index 994aca35c88..40f9eeb747a 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2017 Laurent Destailleur * Copyright (C) ---Put here your own copyright and developer email--- * * This program is free software; you can redistribute it and/or modify @@ -18,9 +18,8 @@ /** * \file htdocs/modulebuilder/template/myobject_card.php - * \ingroup mymodule othermodule1 othermodule2 - * \brief This file is an example of a php page - * Put here some comments + * \ingroup mymodule + * \brief Page to create/edit/view myobject */ //if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); @@ -53,13 +52,16 @@ if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main if (! $res) die("Include of main fails"); include_once(DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'); +include_once(DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'); dol_include_once('/mymodule/class/myobject.class.php'); +dol_include_once('/mymodule/lib/myobject.lib.php'); // Load traductions files requiredby by page -$langs->loadLangs(array("mymodule","other")); +$langs->loadLangs(array("mymodule@mymodule","other")); // Get parameters $id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); $action = GETPOST('action', 'alpha'); $cancel = GETPOST('cancel', 'aZ09'); $backtopage = GETPOST('backtopage', 'alpha'); @@ -83,11 +85,9 @@ foreach($object->fields as $key => $val) if (empty($action) && empty($id) && empty($ref)) $action='view'; -// Protection if external user -if ($user->societe_id > 0) -{ - //accessforbidden(); -} +// Security check - Protection if external user +//if ($user->societe_id > 0) access_forbidden(); +//if ($user->societe_id > 0) $socid = $user->societe_id; //$result = restrictedArea($user, 'mymodule', $id); // fetch optionals attributes and labels @@ -110,6 +110,8 @@ if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'e if (empty($reshook)) { + $error=0; + if ($cancel) { if ($action != 'addlink') @@ -125,19 +127,11 @@ if (empty($reshook)) // Action to add record if ($action == 'add' && ! empty($user->rights->mymodule->create)) { - if ($cancel) - { - $urltogo=$backtopage?$backtopage:dol_buildpath('/mymodule/myobject_list.php',1); - header("Location: ".$urltogo); - exit; - } - - $error=0; - foreach ($object->fields as $key => $val) { + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; // Ignore special fields + $object->$key=GETPOST($key,'alpha'); - if (in_array($key, array('entity', 'datec', 'tms'))) continue; if ($val['notnull'] && $object->$key == '') { $error++; @@ -172,20 +166,20 @@ if (empty($reshook)) // Action to update record if ($action == 'update' && ! empty($user->rights->mymodule->create)) { - $error=0; - - $object->prop1=GETPOST("field1"); - $object->prop2=GETPOST("field2"); - - if (empty($object->ref)) - { - $error++; - setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired",$langs->transnoentitiesnoconv("Ref")), null, 'errors'); - } + foreach ($object->fields as $key => $val) + { + $object->$key=GETPOST($key,'alpha'); + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; + if ($val['notnull'] && $object->$key == '') + { + $error++; + setEventMessages($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv($val['label'])), null, 'errors'); + } + } if (! $error) { - $result=$object->update($user); + $result=$object->updateCommon($user); if ($result > 0) { $action='view'; @@ -207,7 +201,7 @@ if (empty($reshook)) // Action to delete if ($action == 'confirm_delete' && ! empty($user->rights->mymodule->delete)) { - $result=$object->delete($user); + $result=$object->deleteCommon($user); if ($result > 0) { // Delete OK @@ -233,6 +227,7 @@ if (empty($reshook)) */ $form=new Form($db); +$formfile=new FormFile($db); llxHeader('','MyObject',''); @@ -267,12 +262,14 @@ if ($action == 'create') print ''."\n"; foreach($object->fields as $key => $val) { - if (in_array($key, array('rowid', 'entity', 'datec', 'tms'))) continue; - print ''.$langs->trans($val['label']).''; + print '>'.$langs->trans($val['label']).''; + print ''; + print ''; } print '
'."\n"; @@ -298,8 +295,17 @@ if (($id || $ref) && $action == 'edit') dol_fiche_head(); print ''."\n"; - // print ''; - // LIST_OF_TD_LABEL_FIELDS_EDIT + foreach($object->fields as $key => $val) + { + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; + print ''.$langs->trans($val['label']).''; + print ''; + print ''; + } print '
'.$langs->trans("Label").'
'; dol_fiche_end(); @@ -318,14 +324,14 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea { $res = $object->fetch_optionals($object->id, $extralabels); - $head = mymodule_prepare_head($object); - dol_fiche_head($head, 'order', $langs->trans("CustomerOrder"), -1, 'order'); + $head = myobjectPrepareHead($object); + dol_fiche_head($head, 'card', $langs->trans("MyObject"), -1, 'myobject@mymodule'); $formconfirm = ''; // Confirmation to delete if ($action == 'delete') { - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', '', 0, 1); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteMyObject'), $langs->trans('ConfirmDeleteMyObject'), 'confirm_delete', '', 0, 1); } // Confirmation of action xxxx @@ -353,12 +359,9 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print $formconfirm; - // Object card // ------------------------------------------------------------ - - $linkback = '' . $langs->trans("BackToList") . ''; - + $linkback = '' . $langs->trans("BackToList") . ''; $morehtmlref='
'; /* @@ -412,9 +415,18 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print '
'; print '
'; print ''."\n"; - // print ''; - // LIST_OF_TD_LABEL_FIELDS_VIEW + foreach($object->fields as $key => $val) + { + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; + print ''.$langs->trans($val['label']).''; + print ''; + print ''; + } // Other attributes include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; @@ -426,7 +438,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print '
'; print '
'.$langs->trans("Label").''.$object->label.'
'; - + // ... print '
'; print '
'; @@ -484,7 +496,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Show links to link elements - $linktoelem = $form->showLinkToObjectBlock($object, null, array('order')); + $linktoelem = $form->showLinkToObjectBlock($object, null, array('myobject')); $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); @@ -493,7 +505,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // List of actions on element include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php'; $formactions = new FormActions($db); - $somethingshown = $formactions->showactions($object, 'order', $socid); + $somethingshown = $formactions->showactions($object, 'myobject', $socid); print '
'; } @@ -541,7 +553,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print '
'; print '
'; print '
'; - print load_fiche_titre($langs->trans('SendOrderByMail')); + print load_fiche_titre($langs->trans('SendMyObjectByMail')); dol_fiche_head(''); @@ -569,9 +581,9 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $formmail->withtocc = $liste; $formmail->withtoccc = $conf->global->MAIN_EMAIL_USECCC; if (empty($object->ref_client)) { - $formmail->withtopic = $outputlangs->trans('SendOrderRef', '__ORDERREF__'); + $formmail->withtopic = $outputlangs->trans('SendMyObjectRef', '__REF__'); } else if (! empty($object->ref_client)) { - $formmail->withtopic = $outputlangs->trans('SendOrderRef', '__ORDERREF__ (__REFCLIENT__)'); + $formmail->withtopic = $outputlangs->trans('SendMyObjectRef', '__REF__ (__REFCLIENT__)'); } $formmail->withfile = 2; $formmail->withbody = 1; @@ -579,7 +591,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea $formmail->withcancel = 1; // Tableau des substitutions $formmail->setSubstitFromObject($object); - $formmail->substit ['__ORDERREF__'] = $object->ref; + $formmail->substit ['__REF__'] = $object->ref; $custcontact = ''; $contactarr = array(); @@ -603,9 +615,9 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Tableau des parametres complementaires $formmail->param['action'] = 'send'; - $formmail->param['models'] = 'order_send'; + $formmail->param['models'] = 'myobject_send'; $formmail->param['models_id']=GETPOST('modelmailselected','int'); - $formmail->param['orderid'] = $object->id; + $formmail->param['myobjectid'] = $object->id; $formmail->param['returnurl'] = $_SERVER["PHP_SELF"] . '?id=' . $object->id; // Init list of files diff --git a/htdocs/modulebuilder/template/myobject_document.php b/htdocs/modulebuilder/template/myobject_document.php new file mode 100644 index 00000000000..0f8ce367bb5 --- /dev/null +++ b/htdocs/modulebuilder/template/myobject_document.php @@ -0,0 +1,183 @@ + + * 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 htdocs/modulebuilder/template/myobject_document.php + * \ingroup mymodule + * \brief Tab for documents linked to MyObject + */ + +// 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 caluclated 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('/mymodule/class/myobject.class.php'); +dol_include_once('/mymodule/lib/myobject.lib.php'); + +// Load traductions files requiredby by page +$langs->loadLangs(array("mymodule@mymodule","companies","other")); + + +$action=GETPOST('action','aZ09'); +$confirm=GETPOST('confirm'); +$id=(GETPOST('socid','int') ? GETPOST('socid','int') : GETPOST('id','int')); +$ref = GETPOST('ref', 'alpha'); + +// Security check - Protection if external user +//if ($user->societe_id > 0) access_forbidden(); +//if ($user->societe_id > 0) $socid = $user->societe_id; +//$result = restrictedArea($user, 'mymodule', $id); + +// Get parameters +$sortfield = GETPOST("sortfield",'alpha'); +$sortorder = GETPOST("sortorder",'alpha'); +$page = GETPOST("page",'int'); +if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 +$offset = $conf->liste_limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (! $sortorder) $sortorder="ASC"; +if (! $sortfield) $sortfield="name"; + +// Initialize technical objects +$object=new MyObject($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction=$conf->mymodule->dir_output . '/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('myobjectdocument')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label('myobject'); + +// 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->mymodule->multidir_output[$object->entity] . "/" . $object->id; + + + +/* + * Actions + */ + +include_once DOL_DOCUMENT_ROOT . '/core/actions_linkedfiles.inc.php'; + + +/* + * View + */ + +$form = new Form($db); + +$title=$langs->trans("MyObject").' - '.$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 + */ + if (! empty($conf->notification->enabled)) $langs->load("mails"); + $head = myobjectPrepareHead($object); + + dol_fiche_head($head, 'document', $langs->trans("MyObject"), -1, 'myobject@mymodule'); + + + // Construit liste des fichiers + $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") . ''; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
'; + + print '
'; + print ''; + + // Prefix + if (! empty($conf->global->SOCIETE_USEPREFIX)) // Old not used prefix field + { + print ''; + } + + if ($object->client) + { + print ''; + } + + if ($object->fournisseur) + { + print ''; + } + + // Number of files + print ''; + + // Total size + print ''; + + print '
'.$langs->trans('Prefix').''.$object->prefix_comm.'
'; + print $langs->trans('CustomerCode').''; + print $object->code_client; + if ($object->check_codeclient() <> 0) print ' ('.$langs->trans("WrongCustomerCode").')'; + print '
'; + print $langs->trans('SupplierCode').''; + print $object->code_fournisseur; + if ($object->check_codefournisseur() <> 0) print ' ('.$langs->trans("WrongSupplierCode").')'; + print '
'.$langs->trans("NbOfAttachedFiles").''.count($filearray).'
'.$langs->trans("TotalSizeOfAttachedFiles").''.$totalsize.' '.$langs->trans("bytes").'
'; + + print '
'; + + dol_fiche_end(); + + $modulepart = 'societe'; + $permission = $user->rights->societe->creer; + $permtoedit = $user->rights->societe->creer; + $param = '&id=' . $object->id; + include_once DOL_DOCUMENT_ROOT . '/core/tpl/document_actions_post_headers.tpl.php'; +} +else +{ + accessforbidden('',0,0); +} + + +llxFooter(); +$db->close(); diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index 6430944bec7..81e0612cea5 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -18,9 +18,8 @@ /** * \file htdocs/modulebuilder/template/myobject_list.php - * \ingroup mymodule othermodule1 othermodule2 - * \brief This file is an example of a php page - * Put here some comments + * \ingroup mymodule + * \brief List page for myobject */ //if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); @@ -59,7 +58,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; dol_include_once('/mymodule/class/myobject.class.php'); // Load traductions files requiredby by page -$langs->loadLangs(array("mymodule","other")); +$langs->loadLangs(array("mymodule@mymodule","other")); $action = GETPOST('action','alpha'); $massaction = GETPOST('massaction','alpha'); @@ -217,7 +216,8 @@ if (is_array($extrafields->attribute_label) && count($extrafields->attribute_lab $sql.= " WHERE t.entity IN (".getEntity('myobject').")"; foreach($search as $key => $val) { - if ($search[$key] != '') $sql.=natural_search($key, $search[$key], (($key == 'status')?2:($object->fields[$key]['type'] == 'integer'?1:0))); + $mode=(($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key]))?1:0); + if ($search[$key] != '') $sql.=natural_search($key, $search[$key], (($key == 'status')?2:$mode)); } if ($search_all) $sql.= natural_search(array_keys($fieldstosearchall), $search_all); // Add where from extra fields @@ -227,7 +227,7 @@ foreach ($search_array_options as $key => $val) $tmpkey=preg_replace('/search_options_/','',$key); $typ=$extrafields->attribute_type[$tmpkey]; $mode=0; - if (in_array($typ, array('int','double'))) $mode=1; // Search on a numeric + if (in_array($typ, array('int','double','real'))) $mode=1; // Search on a numeric if ($val && ( ($crit != '' && ! in_array($typ, array('select'))) || ! empty($crit))) { $sql .= natural_search('ef.'.$tmpkey, $crit, $mode); @@ -307,9 +307,10 @@ foreach ($search_array_options as $key => $val) if ($val != '') $param.='&search_options_'.$tmpkey.'='.urlencode($val); } +// List of mass actions available $arrayofmassactions = array( - 'presend'=>$langs->trans("SendByMail"), - 'builddoc'=>$langs->trans("PDFMerge"), + //'presend'=>$langs->trans("SendByMail"), + //'builddoc'=>$langs->trans("PDFMerge"), ); if ($user->rights->mymodule->delete) $arrayofmassactions['delete']=$langs->trans("Delete"); if ($massaction == 'presend') $arrayofmassactions=array(); @@ -325,7 +326,7 @@ print ''; print ''; print ''; -print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_companies', 0, '', '', $limit); +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'title_companies', 0, '', '', $limit); if ($sall) { @@ -363,10 +364,11 @@ print ''; foreach($object->fields as $key => $val) { - if (in_array($key, array('datec','tms','status'))) continue; + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) print ''; } // Extra fields @@ -399,10 +401,11 @@ print $hookmanager->resPrint; // Rest of fields search foreach($object->fields as $key => $val) { - if (! in_array($key, array('datec','tms','status'))) continue; + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) print ''; } // Action column @@ -418,10 +421,11 @@ print ''."\n"; print ''; foreach($object->fields as $key => $val) { - if (in_array($key, array('datec','tms','status'))) continue; + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; } // Extra fields @@ -445,10 +449,11 @@ print $hookmanager->resPrint; // Rest of fields title foreach($object->fields as $key => $val) { - if (! in_array($key, array('datec','tms','status'))) continue; + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; } print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"],"",'','','align="center"',$sortfield,$sortorder,'maxwidthsearch ')."\n"; @@ -472,22 +477,36 @@ while ($i < min($num, $limit)) $obj = $db->fetch_object($resql); if ($obj) { + // Store properties in $object + $object->id = $obj->rowid; + foreach($object->fields as $key => $val) + { + if (isset($obj->$key)) $object->$key = $obj->$key; + } + // Show here line of result print ''; foreach($object->fields as $key => $val) { - if (in_array($key, array('datec','tms','status'))) continue; + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) { print ''; if (in_array($val['type'], array('date','datetime','timestamp'))) print dol_print_date($db->jdate($obj->$key), 'dayhour'); - elseif ($key == 'status') print ''; + elseif ($key == 'ref') print $object->getNomUrl(1, '', 0, '', 1); + elseif ($key == 'status') print $object->getLibStatut(3); else print $obj->$key; print ''; if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key; + $totalarray['val']['t.'.$key] += $obj->$key; + } } } // Extra fields @@ -505,6 +524,11 @@ while ($i < min($num, $limit)) print $extrafields->showOutputField($key, $obj->$tmpkey, '', 1); print ''; if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='ef.'.$tmpkey; + $totalarray['val']['ef.'.$tmpkey] += $obj->$tmpkey; + } } } } @@ -515,18 +539,24 @@ while ($i < min($num, $limit)) // Rest of fields foreach($object->fields as $key => $val) { - if (! in_array($key, array('datec','tms','status'))) continue; + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; $align=''; - if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; - if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align.=($align?' ':'').'center'; + if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; if (! empty($arrayfields['t.'.$key]['checked'])) { print ''; if (in_array($val['type'], array('date','datetime','timestamp'))) print dol_print_date($db->jdate($obj->$key), 'dayhour'); - elseif ($key == 'status') print ''; + elseif ($key == 'status') print $object->getLibStatut(3); else print $obj->$key; print ''; if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key; + $totalarray['val']['t.'.$key] += $obj->$key; + } } } // Action column @@ -546,22 +576,23 @@ while ($i < min($num, $limit)) } // Show total line -if (isset($totalarray['totalhtfield'])) +if (isset($totalarray['pos'])) { print ''; $i=0; while ($i < $totalarray['nbfield']) { $i++; - if ($i == 1) + if (! empty($totalarray['pos'][$i])) print ''; + else { - if ($num < $limit) print ''; - else print ''; + if ($i == 1) + { + if ($num < $limit) print ''; + else print ''; + } + print ''; } - elseif ($totalarray['totalhtfield'] == $i) print ''; - elseif ($totalarray['totalvatfield'] == $i) print ''; - elseif ($totalarray['totalttcfield'] == $i) print ''; - else print ''; } print ''; } diff --git a/htdocs/modulebuilder/template/myobject_note.php b/htdocs/modulebuilder/template/myobject_note.php new file mode 100644 index 00000000000..782be1c5bb9 --- /dev/null +++ b/htdocs/modulebuilder/template/myobject_note.php @@ -0,0 +1,163 @@ + + * 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 htdocs/modulebuilder/template/myobject_note.php + * \ingroup mymodule + * \brief Car with notes on MyObject + */ + +// 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 caluclated 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('/mymodule/class/myobject.class.php'); +dol_include_once('/mymodule/lib/myobject.lib.php'); + +// Load traductions files requiredby by page +$langs->loadLangs(array("mymodule@mymodule","companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object=new MyObject($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction=$conf->mymodule->dir_output . '/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('myobjectnote')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label('myobject'); + +// Security check - Protection if external user +//if ($user->societe_id > 0) access_forbidden(); +//if ($user->societe_id > 0) $socid = $user->societe_id; +//$result = restrictedArea($user, 'mymodule', $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->mymodule->multidir_output[$object->entity] . "/" . $object->id; + +$permissionnote=1; +//$permissionnote=$user->rights->mymodule->creer; // Used by the include of actions_setnotes.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('MyObject'),$help_url); + +if ($id > 0 || ! empty($ref)) +{ + $object->fetch_thirdparty(); + + $head = myobjectPrepareHead($object); + + dol_fiche_head($head, 'note', $langs->trans("MyObject"), -1, 'myobject@mymodule'); + + // 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') . ' : ' . $object->thirdparty->getNomUrl(1); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project') . ' '; + if ($user->rights->mymodule->creer) + { + 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.=''; + $morehtmlref.=$proj->ref; + $morehtmlref.=''; + } 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 '
'; + + dol_fiche_end(); +} + + +llxFooter(); +$db->close(); diff --git a/htdocs/modulebuilder/template/sql/llx_myobject.sql b/htdocs/modulebuilder/template/sql/llx_myobject.sql index b5810f0f227..1c47004f4e7 100644 --- a/htdocs/modulebuilder/template/sql/llx_myobject.sql +++ b/htdocs/modulebuilder/template/sql/llx_myobject.sql @@ -19,8 +19,10 @@ CREATE TABLE llx_myobject( -- BEGIN MODULEBUILDER FIELDS entity INTEGER DEFAULT 1 NOT NULL, label VARCHAR(255), - datec DATETIME NOT NULL, + qty INTEGER, + status INTEGER, + date_creation DATETIME NOT NULL, tms TIMESTAMP NOT NULL, - status INTEGER + import_key VARCHAR(14) -- END MODULEBUILDER FIELDS ) ENGINE=innodb; \ No newline at end of file diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 0a6c9052b91..318d19e10b3 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -990,11 +990,11 @@ else // Stock min level if ($type != 1 && ! empty($conf->stock->enabled)) { - print '
'; // Stock desired level - print ''; } diff --git a/htdocs/product/inventory/card.php b/htdocs/product/inventory/card.php index e47891a6d08..5506bad0fbb 100644 --- a/htdocs/product/inventory/card.php +++ b/htdocs/product/inventory/card.php @@ -1,5 +1,6 @@ +/* Copyright (C) 2007-2017 Laurent Destailleur + * 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 @@ -16,48 +17,78 @@ */ /** - * \file htdocs/inventory/card.php - * \ingroup product - * \brief File of class to manage inventory + * \file product/inventory/card.php + * \ingroup inventory + * \brief This file is an example of a php page + * Put here some comments */ - -require_once '../../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/product/inventory/listview.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; -include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/inventory/class/inventory.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/inventory/lib/inventory.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION','1'); // Do not check anti CSRF attack test +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti CSRF attack test +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check anti CSRF attack test +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK','1'); // Do not check style html tag into posted data +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Do not check anti POST attack test +//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) +// 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 caluclated 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"); -$langs->load('stock'); -$langs->load('inventory'); +include_once(DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'); +dol_include_once('/inventory/class/inventory.class.php'); -$id=GETPOST('id', 'int'); -$ref=GETPOST('ref', 'alpha'); -$action=(GETPOST('action','alpha') ? GETPOST('action','alpha') : 'view'); -$cancel=GETPOST('cancel'); -$confirm=GETPOST('confirm','alpha'); -$socid=GETPOST('socid','int'); -if (! empty($user->societe_id)) $socid=$user->societe_id; +// Load traductions files requiredby by page +$langs->loadLangs(array("inventory","other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$action = GETPOST('action', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object=new Inventory($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction=$conf->inventory->dir_output . '/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('inventorycard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label('inventory'); +$search_array_options=$extrafields->getOptionalsFromPost($extralabels,'','search_'); + +// Initialize array of search criterias +$search_all=trim(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'; // Protection if external user if ($user->societe_id > 0) { - //accessforbidden(); + //accessforbidden(); } -$result = restrictedArea($user, 'stock', $id); - - -$object = new Inventory($db); -$extrafields = new ExtraFields($db); +//$result = restrictedArea($user, 'inventory', $id); // fetch optionals attributes and labels $extralabels = $extrafields->fetch_name_optionals_label($object->table_element); @@ -65,623 +96,526 @@ $extralabels = $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 -// Initialize technical object to manage hooks of modules. Note that conf->hooks_modules contains array array -$hookmanager->initHooks(array('inventorycard')); - /* - * Actions + * ACTIONS + * + * Put here all code to do according to value of "action" parameter */ -$parameters=array('id'=>$id, 'ref'=>$ref, 'objcanvas'=>$objcanvas); +$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)) { - if ($cancel) - { - if ($action != 'addlink') - { - $urltogo=$backtopage?$backtopage:dol_buildpath('/product/inventory/list.php',1); - header("Location: ".$urltogo); - exit; - } - if ($id > 0 || ! empty($ref)) $ret = $object->fetch($id,$ref); - $action=''; - } - - if ($action == 'confirmCreate') - { - if (empty($user->rights->stock->creer)) accessforbidden(); - - if ($cancel) + $error=0; + + if ($cancel) + { + if ($action != 'addlink') { - $urltogo=$backtopage?$backtopage:dol_buildpath('/product/inventory/list.php',1); - header("Location: ".$urltogo); - exit; + $urltogo=$backtopage?$backtopage:dol_buildpath('/inventory/inventory_list.php',1); + header("Location: ".$urltogo); + exit; } - - $error=0; - - $object->setValues($_POST); - - $fk_inventory = $object->create($user); - if ($fk_inventory>0) - { - $fk_category = (int) GETPOST('fk_category'); - $fk_supplier = (int) GETPOST('fk_supplier'); - $fk_warehouse = (int) GETPOST('fk_warehouse'); - $only_prods_in_stock = (int) GETPOST('OnlyProdsInStock'); - - $object->addProductsFor($fk_warehouse,$fk_category,$fk_supplier,$only_prods_in_stock); - $object->update($user); - - header('Location: '.dol_buildpath('/product/inventory/card.php?id='.$object->id.'&action=edit', 1)); - exit; - } - else + if ($id > 0 || ! empty($ref)) $ret = $object->fetch($id,$ref); + $action=''; + } + + // Action to add record + if ($action == 'add' && ! empty($user->rights->inventory->create)) + { + foreach ($object->fields as $key => $val) { - setEventMessage($object->error,'errors'); - header('Location: '.dol_buildpath('/product/inventory/card.php?action=create', 1)); - exit; + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'import_key'))) continue; // Ignore special fields + + $object->$key=GETPOST($key,'alpha'); + if ($val['notnull'] && $object->$key == '') + { + $error++; + setEventMessages($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv($val['label'])), null, 'errors'); + } } - } - - switch($action) { - case 'save': - if (!$user->rights->stock->creer) accessforbidden(); - - - $id = GETPOST('id'); - - $object = new Inventory($db); - $object->fetch($id); - - $object->setValues($_REQUEST); - - if ($object->errors) - { - setEventMessage($object->errors, 'errors'); - $action = 'edit'; - } - else - { - $object->udpate($user); - header('Location: '.dol_buildpath('/product/inventory/card.php?id='.$object->getId().'&action=view', 1)); - exit; - } - - break; - - case 'confirm_regulate': - if (!$user->rights->stock->creer) accessforbidden(); - $id = GETPOST('id'); - - $object = new Inventory($db); - $object->fetch($id); - - if($object->status == 0) { - $object->status = 1; - $object->update($user); - - $action='view'; + + if (! $error) + { + $result=$object->createCommon($user); + if ($result > 0) + { + // Creation OK + $urltogo=$backtopage?$backtopage:dol_buildpath('/inventory/inventory_list.php',1); + header("Location: ".$urltogo); + exit; + } + else + { + // Creation KO + if (! empty($object->errors)) setEventMessages(null, $object->errors, 'errors'); + else setEventMessages($object->error, null, 'errors'); + $action='create'; + } + } + else + { + $action='create'; + } + } + + // Action to update record + if ($action == 'update' && ! empty($user->rights->inventory->create)) + { + foreach ($object->fields as $key => $val) + { + $object->$key=GETPOST($key,'alpha'); + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'import_key'))) continue; + if ($val['notnull'] && $object->$key == '') + { + $error++; + setEventMessages($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv($val['label'])), null, 'errors'); } - else { - $action='view'; - } - - break; - - case 'confirm_changePMP': - - $id = GETPOST('id'); - - $object = new Inventory($db); - $object->fetch( $id ); - - $object->changePMP($user); - - $action='view'; - - break; - - case 'add_line': - if (!$user->rights->stock->creer) accessforbidden(); - - $id = GETPOST('id'); - $fk_warehouse = GETPOST('fk_warehouse'); - - $object = new Inventory($db); - $object->fetch( $id ); - - $fk_product = GETPOST('fk_product'); - if ($fk_product>0) - { - $product = new Product($db); - if($product->fetch($fk_product)<=0 || $product->type != 0) { - setEventMessage($langs->trans('ThisIsNotAProduct'),'errors'); - } - else{ - - //Check product not already exists - $alreadyExists = false; - if(!empty($object->Inventorydet)) { - foreach ($object->Inventorydet as $invdet) - { - if ($invdet->fk_product == $product->id - && $invdet->fk_warehouse == $fk_warehouse) - { - $alreadyExists = true; - break; - } - } - } - if (!$alreadyExists) - { - if($object->addProduct($product->id, $fk_warehouse)) { - setEventMessage($langs->trans('ProductAdded')); - } - } - else - { - setEventMessage($langs->trans('inventoryWarningProductAlreadyExists'), 'warnings'); - } - - } - - $object->update($user); - $object->sortDet(); - } - - $action='edit'; - - break; - - case 'confirm_delete_line': - if (!$user->rights->stock->creer) accessforbidden(); - - - //Cette action devrais se faire uniquement si le status de l'inventaire est à 0 mais aucune vérif - $rowid = GETPOST('rowid'); - $objectdet = new Inventorydet($db); - if($objectdet->fetch($rowid)>0) { - $objectdet->delete($user); - setEventMessage("ProductDeletedFromInventory"); - } - $id = GETPOST('id'); - $object = new Inventory($db); - $object->fetch( $id); - - $action='edit'; - - break; - case 'confirm_flush': - if (!$user->rights->stock->creer) accessforbidden(); - - - $id = GETPOST('id'); - - $object = new Inventory($db); - $object->fetch($id); - - $object->deleteAllLine($user); - - setEventMessage($langs->trans('InventoryFlushed')); - - $action='edit'; - - break; - case 'confirm_delete': - if (!$user->rights->stock->supprimer) accessforbidden(); - - $id = GETPOST('id'); - - $object = new Inventory($db); - $object->fetch($id); - - $object->delete($user); - - setEventMessage($langs->trans('InventoryDeleted')); - - header('Location: '.dol_buildpath('/inventory/list.php', 1)); - exit; - - break; - /*case 'exportCSV': - - $id = GETPOST('id'); - - $object = new Inventory($db); - $object->fetch($id); - - _exportCSV($object); - - exit; - break; - */ - } + } + + if (! $error) + { + $result=$object->updateCommon($user); + if ($result > 0) + { + $action='view'; + } + else + { + // Creation KO + if (! empty($object->errors)) setEventMessages(null, $object->errors, 'errors'); + else setEventMessages($object->error, null, 'errors'); + $action='edit'; + } + } + else + { + $action='edit'; + } + } + + // Action to delete + if ($action == 'confirm_delete' && ! empty($user->rights->inventory->delete)) + { + $result=$object->deleteCommon($user); + if ($result > 0) + { + // Delete OK + setEventMessages("RecordDeleted", null, 'mesgs'); + header("Location: ".dol_buildpath('/inventory/inventory_list.php',1)); + exit; + } + else + { + if (! empty($object->errors)) setEventMessages(null, $object->errors, 'errors'); + else setEventMessages($object->error, null, 'errors'); + } + } } + + /* - * Views + * VIEW + * + * Put here all code to build page */ $form=new Form($db); -llxHeader('',$langs->trans('Inventory'),'',''); - +llxHeader('','Inventory',''); + +// Example : Adding jquery code +print ''; + + +// Part to create if ($action == 'create') { - if (empty($user->rights->stock->creer)) accessforbidden(); + print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("Inventory"))); - print load_fiche_titre($langs->trans("NewInventory")); - - echo '
'; - echo ''; - - dol_fiche_head(); - - $formproduct = new FormProduct($db); - - ?> -
'.$object->getLibStatut(3).''.$object->getLibStatut(3).'
'.price($totalarray['val'][$totalarray['pos'][$i]]).''.$langs->trans("Total").''.$langs->trans("Totalforthispage").''.$langs->trans("Total").''.$langs->trans("Totalforthispage").''.price($totalarray['totalht']).''.price($totalarray['totalvat']).''.price($totalarray['totalttc']).'
'.$langs->trans("StockLimit").''; + print '
'.$form->textwithpicto($langs->trans("StockLimit"), $langs->trans("StockLimitDesc"), 1).''; print ''; print ''.$langs->trans("DesiredStock").''; + print ''.$form->textwithpicto($langs->trans("DesiredStock"), $langs->trans("DesiredStockDesc"), 1).''; print ''; print '
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
trans('Title') ?>
trans('Date') ?>select_date(time(),'date_inventory'); ?>
trans('inventorySelectWarehouse') ?>selectWarehouses('', 'fk_warehouse') ?>
trans('SelectCategory') ?>select_all_categories(0,'', 'fk_category') ?>
trans('SelectFournisseur') ?>select_thirdparty('','fk_supplier','s.fournisseur = 1') ?>
trans('OnlyProdsInStock') ?>
- '; - print ''; - print '     '; - print ''; - print ''; - - echo ''; - + print '
'; + print ''; + print ''; + print ''; + + dol_fiche_head(array(), ''); + + print ''."\n"; + foreach($object->fields as $key => $val) + { + if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'import_key'))) continue; + print ''.$langs->trans($val['label']).''; + } + print '
'."\n"; + + dol_fiche_end(); + + print '
 
'; + + print '
'; } -if ($action == 'view' || $action == 'edit' || empty($action)) + + +// Part to edit record +if (($id || $ref) && $action == 'edit') { - $object = new Inventory($db); - $result = $object->fetch($id); - if ($result < 0) dol_print_error($db, $object->error, $object->errors); - - $warehouse = new Entrepot($db); - $warehouse->fetch($object->fk_warehouse); - - - - if($action == 'changePMP') - { - print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ApplyNewPMP'), $langs->trans('ConfirmApplyNewPMP', $object->getTitle()), 'confirm_changePMP', array(),'no',1); - } - else if($action == 'flush') - { - print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id,$langs->trans('FlushInventory'),$langs->trans('ConfirmFlushInventory',$object->getTitle()),'confirm_flush',array(),'no',1); - } - else if($action == 'delete') - { - print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id,$langs->trans('Delete'),$langs->trans('ConfirmDelete',$object->getTitle()),'confirm_delete',array(),'no',1); - } - else if($action == 'delete_line') - { - print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&rowid='.GETPOST('rowid'),$langs->trans('DeleteLine'),$langs->trans('ConfirmDeleteLine',$object->getTitle()),'confirm_delete_line',array(),'no',1); - } - else if($action == 'regulate') - { - print $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id,$langs->trans('RegulateStock'),$langs->trans('ConfirmRegulateStock',$object->getTitle()),'confirm_regulate',array(),'no',1); - } - - print dol_get_fiche_head(inventoryPrepareHead($object, $langs->trans('inventoryOfWarehouse', $warehouse->libelle), empty($action) ? '': '&action='.$action)); - - $lines = array(); - card_line($object, $lines, $action); - - print $langs->trans('Ref')." ".$object->ref.'
'; - print $langs->trans('Date')." ".$object->getDate('date_inventory').'

'; - - $objectTPL = array( - 'id'=> $object->id - ,'ref'=> $object->ref - ,'date_cre' => $object->getDate('date_cre', 'd/m/Y') - ,'date_maj' => $object->getDate('date_maj', 'd/m/Y H:i') - ,'fk_warehouse' => $object->fk_warehouse - ,'status' => $object->status - ,'entity' => $object->entity - ,'amount' => price( round($object->amount,2) ) - ,'amount_actual'=>price (round($object->amount_actual,2)) - - ); - - $can_validate = !empty($user->rights->stock->validate); - $view_url = dol_buildpath('/product/inventory/card.php', 1); - - $view = array( - 'mode' => $action - ,'url' => dol_buildpath('/product/inventory/card.php', 1) - ,'can_validate' => (int) $user->rights->stock->validate - ,'is_already_validate' => (int) $object->status - ,'token'=>$_SESSION['newtoken'] - ); - - include './tpl/inventory.tpl.php'; + print load_fiche_titre($langs->trans("Inventory")); + + print '
'; + print ''; + print ''; + print ''; + + dol_fiche_head(); + + print ''."\n"; + // print ''; + // LIST_OF_TD_LABEL_FIELDS_EDIT + print '
'.$langs->trans("Label").'
'; + + dol_fiche_end(); + + print '
'; + print '   '; + print '
'; + + print '
'; } + + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) +{ + $res = $object->fetch_optionals($object->id, $extralabels); + + $head = inventory_prepare_head($object); + dol_fiche_head($head, 'order', $langs->trans("CustomerOrder"), -1, 'order'); + + $formconfirm = ''; + + // Confirmation to delete + if ($action == 'delete') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', '', 0, 1); + } + + // Confirmation of action xxxx + if ($action == 'xxx') + { + $formquestion=array(); + /* + $formquestion = array( + // 'text' => $langs->trans("ConfirmClone"), + // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), + // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), + // array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1))); + }*/ + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('XXX'), $text, 'confirm_xxx', $formquestion, 0, 1, 220); + } + + if (! $formconfirm) { + $parameters = array('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 bis + $morehtmlref.=$form->editfieldkey("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->inventory->creer, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->inventory->creer, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
'.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
'.$langs->trans('Project') . ' '; + if ($user->rights->inventory->creer) + { + if ($action != 'classify') + { + $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + 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.=''; + $morehtmlref.=$proj->ref; + $morehtmlref.=''; + } else { + $morehtmlref.=''; + } + } + } + */ + $morehtmlref.='
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
'; + print '
'; + print '
'; + print ''."\n"; + // print ''; + // LIST_OF_TD_LABEL_FIELDS_VIEW + + + // Other attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; + + print '
'.$langs->trans("Label").''.$object->label.'
'; + print '
'; + print '
'; + print '
'; + print '
'; + print ''; + + + + print '
'; + print '
'; + print '
'; + print '
'; + + print '

'; + + dol_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)) + { + // Send + print ''."\n"; + + if ($user->rights->inventory->write) + { + print ''."\n"; + } + + if ($user->rights->inventory->delete) + { + print ''."\n"; + } + } + print '
'."\n"; + } + + + // Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; + } + + if ($action != 'presend') + { + print '
'; + print ''; // ancre + // Documents + $comref = dol_sanitizeFileName($object->ref); + $relativepath = $comref . '/' . $comref . '.pdf'; + $filedir = $conf->inventory->dir_output . '/' . $comref; + $urlsource = $_SERVER["PHP_SELF"] . "?id=" . $object->id; + $genallowed = $user->rights->inventory->creer; + $delallowed = $user->rights->inventory->supprimer; + print $formfile->showdocuments('inventory', $comref, $filedir, $urlsource, $genallowed, $delallowed, $object->modelpdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang); + + + // Show links to link elements + $linktoelem = $form->showLinkToObjectBlock($object, null, array('order')); + $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); + + + print '
'; + + // List of actions on element + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php'; + $formactions = new FormActions($db); + $somethingshown = $formactions->showactions($object, 'order', $socid); + + print '
'; + } + + + /* + * Action presend + */ + /* + if ($action == 'presend') + { + $object->fetch_projet(); + + $ref = dol_sanitizeFileName($object->ref); + include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; + $fileparams = dol_most_recent_file($conf->commande->dir_output . '/' . $ref, preg_quote($ref, '/').'[^\-]+'); + $file = $fileparams['fullname']; + + // Define output language + $outputlangs = $langs; + $newlang = ''; + if ($conf->global->MAIN_MULTILANGS && empty($newlang) && ! empty($_REQUEST['lang_id'])) + $newlang = $_REQUEST['lang_id']; + if ($conf->global->MAIN_MULTILANGS && empty($newlang)) + $newlang = $object->thirdparty->default_lang; + + if (!empty($newlang)) + { + $outputlangs = new Translate('', $conf); + $outputlangs->setDefaultLang($newlang); + $outputlangs->load('commercial'); + } + + // Build document if it not exists + if (! $file || ! is_readable($file)) { + $result = $object->generateDocument(GETPOST('model') ? GETPOST('model') : $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref); + if ($result <= 0) { + dol_print_error($db, $object->error, $object->errors); + exit(); + } + $fileparams = dol_most_recent_file($conf->commande->dir_output . '/' . $ref, preg_quote($ref, '/').'[^\-]+'); + $file = $fileparams['fullname']; + } + + print '
'; + print '
'; + print '
'; + print load_fiche_titre($langs->trans('SendOrderByMail')); + + dol_fiche_head(''); + + // Cree l'objet formulaire mail + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php'; + $formmail = new FormMail($db); + $formmail->param['langsmodels']=(empty($newlang)?$langs->defaultlang:$newlang); + $formmail->fromtype = (GETPOST('fromtype')?GETPOST('fromtype'):(!empty($conf->global->MAIN_MAIL_DEFAULT_FROMTYPE)?$conf->global->MAIN_MAIL_DEFAULT_FROMTYPE:'user')); + + if($formmail->fromtype === 'user'){ + $formmail->fromid = $user->id; + + } + $formmail->trackid='ord'.$object->id; + if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 2)) // If bit 2 is set + { + include DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + $formmail->frommail=dolAddEmailTrackId($formmail->frommail, 'ord'.$object->id); + } + $formmail->withfrom = 1; + $liste = array(); + foreach ($object->thirdparty->thirdparty_and_contact_email_array(1) as $key => $value) + $liste [$key] = $value; + $formmail->withto = GETPOST('sendto') ? GETPOST('sendto') : $liste; + $formmail->withtocc = $liste; + $formmail->withtoccc = $conf->global->MAIN_EMAIL_USECCC; + if (empty($object->ref_client)) { + $formmail->withtopic = $outputlangs->trans('SendOrderRef', '__ORDERREF__'); + } else if (! empty($object->ref_client)) { + $formmail->withtopic = $outputlangs->trans('SendOrderRef', '__ORDERREF__ (__REFCLIENT__)'); + } + $formmail->withfile = 2; + $formmail->withbody = 1; + $formmail->withdeliveryreceipt = 1; + $formmail->withcancel = 1; + // Tableau des substitutions + $formmail->setSubstitFromObject($object); + $formmail->substit ['__ORDERREF__'] = $object->ref; + + $custcontact = ''; + $contactarr = array(); + $contactarr = $object->liste_contact(- 1, 'external'); + + if (is_array($contactarr) && count($contactarr) > 0) + { + foreach ($contactarr as $contact) + { + if ($contact['libelle'] == $langs->trans('TypeContact_commande_external_CUSTOMER')) { // TODO Use code and not label + $contactstatic = new Contact($db); + $contactstatic->fetch($contact ['id']); + $custcontact = $contactstatic->getFullName($langs, 1); + } + } + + if (! empty($custcontact)) { + $formmail->substit['__CONTACTCIVNAME__'] = $custcontact; + } + } + + // Tableau des parametres complementaires + $formmail->param['action'] = 'send'; + $formmail->param['models'] = 'order_send'; + $formmail->param['models_id']=GETPOST('modelmailselected','int'); + $formmail->param['orderid'] = $object->id; + $formmail->param['returnurl'] = $_SERVER["PHP_SELF"] . '?id=' . $object->id; + + // Init list of files + if (GETPOST("mode") == 'init') { + $formmail->clear_attached_files(); + $formmail->add_attached_files($file, basename($file), dol_mimetype($file)); + } + + // Show form + print $formmail->get_form(); + + dol_fiche_end(); + }*/ +} + + // End of page llxFooter(); $db->close(); - - - -function card_line(&$inventory, &$lines, $mode) -{ - global $db,$langs,$user,$conf; - $inventory->amount_actual = 0; - - $TCacheEntrepot = array(); - - foreach ($inventory->Inventorydet as $k => $Inventorydet) - { - $product = & $Inventorydet->product; - $stock = $Inventorydet->qty_stock; - - $pmp = $Inventorydet->pmp; - $pmp_actual = $pmp * $stock; - $inventory->amount_actual+=$pmp_actual; - - $last_pa = $Inventorydet->pa; - $current_pa = $Inventorydet->current_pa; - - $e = new Entrepot($db); - if(!empty($TCacheEntrepot[$Inventorydet->fk_warehouse])) $e = $TCacheEntrepot[$Inventorydet->fk_warehouse]; - elseif($e->fetch($Inventorydet->fk_warehouse) > 0) $TCacheEntrepot[$e->id] = $e; - - $qtytoadd = GETPOST('qty_to_add', 'array'); - $qty = (float) $qtytoadd[$k]; - - $lines[]=array( - 'produit' => $product->getNomUrl(1).' - '.$product->label, - 'entrepot'=>$e->getNomUrl(1), - 'barcode' => $product->barcode, - 'qty' =>($mode == 'edit' ? ' '.img_picto($langs->trans('Add'), 'edit_add').'' : '' ), - 'qty_view' => ($Inventorydet->qty_view ? $Inventorydet->qty_view : 0), - 'qty_stock' => $stock, - 'qty_regulated' => ($Inventorydet->qty_regulated ? $Inventorydet->qty_regulated : 0), - 'action' => ($user->rights->stock->write && $mode=='edit' ? ''.img_picto($langs->trans('inventoryDeleteLine'), 'delete').'' : ''), - 'pmp_stock'=>round($pmp_actual,2), - 'pmp_actual'=> round($pmp * $Inventorydet->qty_view,2), - 'pmp_new'=>(!empty($user->rights->stock->changePMP) && $mode == 'edit' ? ' '.img_picto($langs->trans('Save'), 'bt-save.png@inventory').'' : price($Inventorydet->new_pmp)), - 'pa_stock'=>round($last_pa * $stock,2), - 'pa_actual'=>round($last_pa * $Inventorydet->qty_view,2), - 'current_pa_stock'=>round($current_pa * $stock,2), - 'current_pa_actual'=>round($current_pa * $Inventorydet->qty_view,2), - 'k'=>$k, - 'id'=>$Inventorydet->id - ); - } - -} - - -/* -function _exportCSV(&$inventory) -{ - global $conf; - - header('Content-Type: application/octet-stream'); - header('Content-disposition: attachment; filename=inventory-'. $inventory->getId().'-'.date('Ymd-His').'.csv'); - header('Pragma: no-cache'); - header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0'); - header('Expires: 0'); - - echo 'Ref;Label;barcode;qty theorique;PMP;dernier PA;'; - if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) echo 'PA courant;'; - echo 'qty réelle;PMP;dernier PA;'; - if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) echo 'PA courant;'; - echo 'qty regulée;'."\r\n"; - - foreach ($inventory->Inventorydet as $k => $Inventorydet) - { - $product = & $Inventorydet->product; - $stock = $Inventorydet->qty_stock; - - $pmp = $Inventorydet->pmp; - $pmp_actual = $pmp * $stock; - $inventory->amount_actual+=$pmp_actual; - - $last_pa = $Inventorydet->pa; - $current_pa = $Inventorydet->current_pa; - - if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) { - $row=array( - 'produit' => $product->ref - ,'label'=>$product->label - ,'barcode' => $product->barcode - ,'qty_stock' => $stock - ,'pmp_stock'=>round($pmp_actual,2) - ,'pa_stock'=>round($last_pa * $stock,2) - ,'current_pa_stock'=>round($current_pa * $stock,2) - ,'qty_view' => $Inventorydet->qty_view ? $Inventorydet->qty_view : 0 - ,'pmp_actual'=>round($pmp * $Inventorydet->qty_view,2) - ,'pa_actual'=>round($last_pa * $Inventorydet->qty_view,2) - ,'current_pa_actual'=>round($current_pa * $Inventorydet->qty_view,2) - ,'qty_regulated' => $Inventorydet->qty_regulated ? $Inventorydet->qty_regulated : 0 - - ); - - } - else{ - $row=array( - 'produit' => $product->ref - ,'label'=>$product->label - ,'barcode' => $product->barcode - ,'qty_stock' => $stock - ,'pmp_stock'=>round($pmp_actual,2) - ,'pa_stock'=>round($last_pa * $stock,2) - ,'qty_view' => $Inventorydet->qty_view ? $Inventorydet->qty_view : 0 - ,'pmp_actual'=>round($pmp * $Inventorydet->qty_view,2) - ,'pa_actual'=>round($last_pa * $Inventorydet->qty_view,2) - - ,'qty_regulated' => $Inventorydet->qty_regulated ? $Inventorydet->qty_regulated : 0 - - ); - - } - - - echo '"'.implode('";"', $row).'"'."\r\n"; - - } - - exit; -} -*/ - -function _footerList($view,$total_pmp,$total_pmp_actual,$total_pa,$total_pa_actual, $total_current_pa,$total_current_pa_actual) -{ - global $conf,$user,$langs; - - if ($view['can_validate'] == 1) { ?> - -   - barcode->enabled)) { ?> -   - - - - global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ - echo ''.price($total_current_pa).''; - } - ?> -   - - rights->stock->changePMP)) { - echo ' '; - } - ?> - - global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ - echo ''.price($total_current_pa_actual).''; - } - ?> - -   - -   - - - - - trans('Product'); ?> - trans('Warehouse'); ?> - barcode->enabled)) { ?> - trans('Barcode'); ?> - - - trans('TheoricalQty'); ?> - global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ - echo ''.$langs->trans('TheoricalValue').''; - } - else { - echo ''.$langs->trans('TheoricalValue').''; - } - - ?> - - - trans('RealQty'); ?> - - - global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) $colspan++; - if(!empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) $colspan++; - - echo ''.$langs->trans('RealValue').''; - - ?> - - trans('RegulatedQty'); ?> - - - # - - - - - -   - trans('PMP'); ?> - trans('LastPA'); ?> - global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ - echo ''.$langs->trans('CurrentPA').''; - } - - ?> -   - trans('PMP'); ?> - rights->stock->changePMP)) { - echo ''.$langs->trans('ColumnNewPMP').''; - } - ?> - trans('LastPA'); ?> - global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)){ - echo ''.$langs->trans('CurrentPA').''; - } - - ?> -   - -   - - - +/* Copyright (C) 2007-2017 Laurent Destailleur + * Copyright (C) 2014-2016 Juanjo Menent + * Copyright (C) 2015 Florian Henry + * Copyright (C) 2015 Raphaël Doursenaud + * 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 @@ -16,698 +20,271 @@ */ /** - * \file htdocs/inventory/class/product.class.php - * \ingroup product - * \brief File of class to manage predefined products stock + * \file product/inventory/class/inventory.class.php + * \ingroup inventory + * \brief This file is a CRUD class file for Inventory (Create/Read/Update/Delete) */ - -require_once DOL_DOCUMENT_ROOT.'/core/class/coreobject.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; + +// 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 to manage inventories + * Class for Inventory */ -class Inventory extends CoreObject +class Inventory extends CommonObject { - public $element='inventory'; - public $table_element='inventory'; - public $fk_element='fk_inventory'; - protected $childtables=array('inventorydet'); // To test if we can delete object - protected $isnolinkedbythird = 1; // No field fk_soc - protected $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe - /** - * Warehouse Id - * @var int + * @var string ID to identify managed object */ - public $fk_warehouse; + public $element = 'inventory'; /** - * Entity Id - * @var int + * @var string Name of table without prefix where object is stored */ + public $table_element = 'inventory'; + + /** + * @var array Does this field is linked to a thirdparty ? + */ + protected $isnolinkedbythird = 1; + /** + * @var array Does inventory support multicompany module ? 0=No test on entity, 1=Test with field entity, 2=Test with link by societe + */ + protected $ismultientitymanaged = 1; + /** + * @var string String with name of icon for inventory + */ + public $picto = 'inventory'; + + + /** + * 'type' if the field format, 'label' the translation key, 'enabled' is a condition when the filed must be managed, + * 'visible' says if field is visible in list (-1 means not shown by default but can be aded into list to be viewed) + * 'notnull' if not null in database + * 'index' if we want an index in database + * 'position' is the sort order of field + * '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). + * 'comment' is not used. You can store here any text of your choice. + */ + + // BEGIN MODULEBUILDER PROPERTIES + /** + * @var array Array with all fields and their property + */ + public $fields=array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'visible'=>-1, 'enabled'=>1, 'position'=>1, 'notnull'=>1, 'index'=>1, 'comment'=>'Id',), + 'ref' => array('type'=>'varchar(64)', 'label'=>'Ref', 'visible'=>1, 'enabled'=>1, 'position'=>10, 'notnull'=>1, 'index'=>1, 'searchall'=>1, 'comment'=>'Reference of object',), + 'entity' => array('type'=>'integer', 'label'=>'Entity', 'visible'=>0, 'enabled'=>1, 'position'=>20, 'notnull'=>1, 'index'=>1,), + 'fk_warehouse' => array('type'=>'integer', 'label'=>'', 'visible'=>1, 'enabled'=>1, 'index'=>1,), + 'date_inventory' => array('type'=>'date', 'label'=>'', 'visible'=>1, 'enabled'=>1,), + 'title' => array('type'=>'varchar(255)', 'label'=>'', 'visible'=>1, 'enabled'=>1,), + 'status' => array('type'=>'integer', 'label'=>'Status', 'visible'=>1, 'enabled'=>1, 'position'=>1000, 'index'=>1,), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'visible'=>-1, 'enabled'=>1, 'position'=>500,), + 'date_validation' => array('type'=>'datetime', 'label'=>'DateValidation', 'visible'=>-1, 'enabled'=>1, 'position'=>500,), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'visible'=>-1, 'enabled'=>1, 'position'=>500, 'notnull'=>1,), + 'fk_user_creat' => array('type'=>'integer', 'label'=>'UserAuthor', 'visible'=>-1, 'enabled'=>1, 'position'=>500,), + 'fk_user_modif' => array('type'=>'integer', 'label'=>'UserModif', 'visible'=>-1, 'enabled'=>1, 'position'=>500,), + 'fk_user_valid' => array('type'=>'integer', 'label'=>'UserValid', 'visible'=>-1, 'enabled'=>1, 'position'=>500,), + 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'visible'=>-1, 'enabled'=>1, 'position'=>1000, 'index'=>1,), + ); + + public $rowid; + public $ref; public $entity; - - /** - * Status - * @var int - */ - public $status; - /** - * Inventory Date - * @var date - */ + public $fk_warehouse; public $date_inventory; - /** - * Inventory Title - * @var string - */ public $title; + public $status; + public $date_creation; + public $date_validation; + public $tms; + public $fk_user_creat; + public $fk_user_modif; + public $fk_user_valid; + public $import_key; + // END MODULEBUILDER PROPERTIES - /** - * Attribute object linked with database - * @var array - */ - protected $fields=array( - 'fk_warehouse'=>array('type'=>'integer','index'=>true) - ,'ref'=>array('type'=>'string','index'=>true) - ,'entity'=>array('type'=>'integer','index'=>true) - ,'status'=>array('type'=>'integer','index'=>true) - ,'date_inventory'=>array('type'=>'date') - ,'title'=>array('type'=>'string') - ); - /** - * Constructor - * - * @param DoliDB $db Database handler - */ - public function __construct(DoliDB &$db) + + // If this object has a subtable with lines + + /** + * @var int Name of subtable line + */ + //public $table_element_line = 'inventorydet'; + /** + * @var int Field with ID of parent key if this field has a parent + */ + //public $fk_element = 'fk_inventory'; + /** + * @var int Name of subtable class that manage subtable lines + */ + //public $class_element_line = 'Inventoryline'; + /** + * @var array Array of child tables (child tables to delete before deleting a record) + */ + //protected $childtables=array('inventorydet'); + /** + * @var InventoryLine[] Array of subtable lines + */ + //public $lines = array(); + + + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) { - global $conf; - - parent::__construct($db); - parent::init(); - - $this->status = 0; - $this->entity = $conf->entity; - $this->errors = array(); - $this->amount = 0; + $this->db = $db; } - /** - * Function to sort children object - */ - public function sortDet() + + /** + * 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 + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @return string String with URL + */ + function getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='') { - if(!empty($this->Inventorydet)) usort($this->Inventorydet, array('Inventory', 'customSort')); - } + global $db, $conf, $langs; + global $dolibarr_main_authentication, $dolibarr_main_demo; + global $menumanager; - /** - * Get object and children from database - * - * @param int $id Id of object to load - * @param bool $loadChild used to load children from database - * @return int >0 if OK, <0 if KO, 0 if not found - */ - public function fetch($id, $loadChild = true) - { - if(!$loadChild) $this->withChild = false; - - $res = parent::fetch($id, $loadChild); + if (! empty($conf->dol_no_mouse_hover)) $notooltip=1; // Force disable tooltips - if ($res > 0) - { - $this->sortDet(); - $this->amount = 0; - if(!empty($this->Inventorydet )) - { - foreach($this->Inventorydet as &$det) - { - $this->amount += $det->qty_view * $det->pmp; - } - } - } - - return $res; - } + $result = ''; + $companylink = ''; - /** - * Custom function call by usort - * - * @param Inventorydet $objA first Inventorydet object - * @param Inventorydet $objB second Inventorydet object - * @return int - */ - private function customSort(&$objA, &$objB) - { - $r = strcmp(strtoupper(trim($objA->product->ref)), strtoupper(trim($objB->product->ref))); - - if ($r < 0) $r = -1; - elseif ($r > 0) $r = 1; - else $r = 0; - - return $r; - } + $label = '' . $langs->trans("Inventory") . ''; + $label.= '
'; + $label.= '' . $langs->trans('Ref') . ': ' . $this->ref; - /** - * @param User $user user object - * @return int - */ - public function changePMP(User &$user) - { - $error = 0; - $this->db->begin(); + $url = $url = dol_buildpath('/inventory/m_card.php',1).'?id='.$this->id; - if(!empty($this->Inventorydet)) - { - foreach ($this->Inventorydet as $k => &$Inventorydet) - { - if($Inventorydet->new_pmp>0) - { - $Inventorydet->pmp = $Inventorydet->new_pmp; - $Inventorydet->new_pmp = 0; - - $res = $this->db->query('UPDATE '.MAIN_DB_PREFIX.'product as p SET pmp = '.$Inventorydet->pmp.' WHERE rowid = '.$Inventorydet->fk_product ); - if (!$res) - { - $error++; - $this->error = $this->db->lasterror(); - $this->errors[] = $this->db->lasterror(); - } - } - } - } - - $res = parent::update($user); - if (!$res) + $linkclose=''; + if (empty($notooltip)) { - $error++; - $this->error = $this->db->lasterror(); - $this->errors[] = $this->db->lasterror(); - } - - - if (!$error) - { - $this->db->commit(); - return 1; - } - else - { - $this->db->rollback(); - return -1; - } - } - - /** - * Function to update object or create or delete if needed - * - * @param User $user user object - * @return < 0 if ko, > 0 if ok - */ - public function update(User &$user) - { - $error = 0; - $this->db->begin(); - - // if we valid the inventory we save the stock at the same time - if ($this->status) - { - $res = $this->regulate(); - if ($res < 0) + if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { - $error++; - $this->error = $this->db->lasterror(); - $this->errors[] = $this->db->lasterror(); + $label=$langs->trans("ShowInventory"); + $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=''; + + if ($withpicto) + { + $result.=($linkstart.img_object(($notooltip?'':$label), 'label', ($notooltip?'':'class="classfortooltip"')).$linkend); + if ($withpicto != 2) $result.=' '; } - - $res = parent::update($user); - if (!$res) - { - $error++; - $this->error = $this->db->lasterror(); - $this->errors[] = $this->db->lasterror(); - } - - if (!$error) - { - $this->db->commit(); - return $this->id; - } - else - { - $this->db->rollback(); - return -1; - } + $result.= $linkstart . $this->ref . $linkend; + return $result; } - /** - * Function to update current object - * - * @param array $Tab Array of values - * @return int - */ - public function setValues(&$Tab) + /** + * Retourne le libelle du status d'un user (actif, inactif) + * + * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto + * @return string Label of status + */ + function getLibStatut($mode=0) + { + return $this->LibStatut($this->status,$mode); + } + + /** + * 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, 5=Long label + Picto + * @return string Label of status + */ + static function LibStatut($status,$mode=0) { global $langs; - - if (isset($Tab['qty_to_add'])) + + if ($mode == 0) { - foreach ($Tab['qty_to_add'] as $k => $qty) - { - $qty = (float) price2num($qty); - - if ($qty < 0) - { - $this->errors[] = $langs->trans('inventoryErrorQtyAdd'); - return -1; - } - - $product = new Product($this->db); - $product->fetch($this->Inventorydet[$k]->fk_product); - - $this->Inventorydet[$k]->pmp = $product->pmp; - $this->Inventorydet[$k]->qty_view += $qty; - } + $prefix=''; + if ($status == 1) return $langs->trans('Enabled'); + if ($status == 0) return $langs->trans('Disabled'); + } + if ($mode == 1) + { + if ($status == 1) return $langs->trans('Enabled'); + if ($status == 0) return $langs->trans('Disabled'); + } + if ($mode == 2) + { + if ($status == 1) return img_picto($langs->trans('Enabled'),'statut4').' '.$langs->trans('Enabled'); + if ($status == 0) return img_picto($langs->trans('Disabled'),'statut5').' '.$langs->trans('Disabled'); + } + if ($mode == 3) + { + if ($status == 1) return img_picto($langs->trans('Enabled'),'statut4'); + if ($status == 0) return img_picto($langs->trans('Disabled'),'statut5'); + } + if ($mode == 4) + { + if ($status == 1) return img_picto($langs->trans('Enabled'),'statut4').' '.$langs->trans('Enabled'); + if ($status == 0) return img_picto($langs->trans('Disabled'),'statut5').' '.$langs->trans('Disabled'); + } + if ($mode == 5) + { + if ($status == 1) return $langs->trans('Enabled').' '.img_picto($langs->trans('Enabled'),'statut4'); + if ($status == 0) return $langs->trans('Disabled').' '.img_picto($langs->trans('Disabled'),'statut5'); + } + if ($mode == 6) + { + if ($status == 1) return $langs->trans('Enabled').' '.img_picto($langs->trans('Enabled'),'statut4'); + if ($status == 0) return $langs->trans('Disabled').' '.img_picto($langs->trans('Disabled'),'statut5'); } - - return parent::setValues($Tab); } - /** - * Function to delete all Inventorydet - * - * @param User $user user object - * @return < 0 if ko, > 0 if ok - */ - public function deleteAllLine(User &$user) - { - foreach($this->Inventorydet as &$det) - { - $det->to_delete = true; - } - - $res = $this->update($user); - if ($res > 0) $this->Inventorydet = array(); - else return -1; - } - - /** - * Function to add Inventorydet - * - * @param int $fk_product fk_product of Inventorydet - * @param int $fk_warehouse fk_warehouse target - * @return bool - */ - public function addProduct($fk_product, $fk_warehouse=0) - { - $k = $this->addChild('Inventorydet'); - $det = &$this->Inventorydet[$k]; - - $det->fk_inventory = $this->id; - $det->fk_product = $fk_product; - $det->fk_warehouse = empty($fk_warehouse) ? $this->fk_warehouse : $fk_warehouse; - - $det->load_product(); - - $date = $this->getDate('date_inventory', 'Y-m-d'); - if(empty($date)) $date = $this->getDate('datec', 'Y-m-d'); - $det->setStockDate($date, $fk_warehouse); - - return true; - } - - /** - * Duplication method product to add datem - * Adjust stock in a warehouse for product - * - * @param int $fk_product id of product - * @param int $fk_warehouse id of warehouse - * @param double $nbpiece nb of units - * @param int $movement 0 = add, 1 = remove - * @param string $label Label of stock movement - * @param double $price Unit price HT of product, used to calculate average weighted price (PMP in french). If 0, average weighted price is not changed. - * @param string $inventorycode Inventory code - * @return int <0 if KO, >0 if OK - */ - public function correctStock($fk_product, $fk_warehouse, $nbpiece, $movement, $label='', $price=0, $inventorycode='') + /** + * Initialise object with example values + * Id must be 0 if object instance is a specimen + * + * @return void + */ + public function initAsSpecimen() { - global $conf, $user; - - if ($fk_warehouse) - { - $this->db->begin(); - - require_once DOL_DOCUMENT_ROOT .'/product/stock/class/mouvementstock.class.php'; - - $op[0] = "+".trim($nbpiece); - $op[1] = "-".trim($nbpiece); - - $datem = empty($conf->global->INVENTORY_USE_INVENTORY_DATE_FROM_DATEMVT) ? dol_now() : $this->date_inventory; - - $movementstock=new MouvementStock($this->db); - $movementstock->origin = new stdClass(); - $movementstock->origin->element = 'inventory'; - $movementstock->origin->id = $this->id; - $result=$movementstock->_create($user,$fk_product,$fk_warehouse,$op[$movement],$movement,$price,$label,$inventorycode, $datem); - - if ($result >= 0) - { - $this->db->commit(); - return 1; - } - else - { - $this->error=$movementstock->error; - $this->errors=$movementstock->errors; - - $this->db->rollback(); - return -1; - } - } + $this->initAsSpecimenCommon(); } - /** - * Function to regulate stock - * - * @return int - */ - public function regulate() - { - global $langs,$conf; - - if($conf->global->INVENTORY_DISABLE_VIRTUAL) - { - $pdt_virtuel = false; - // Test if virtual product is enabled - if($conf->global->PRODUIT_SOUSPRODUITS) - { - $pdt_virtuel = true; - $conf->global->PRODUIT_SOUSPRODUITS = 0; - } - } - - foreach ($this->Inventorydet as $k => $Inventorydet) - { - $product = new Product($this->db); - $product->fetch($Inventorydet->fk_product); - - if ($Inventorydet->qty_view != $Inventorydet->qty_stock) - { - $Inventorydet->qty_regulated = $Inventorydet->qty_view - $Inventorydet->qty_stock; - $nbpiece = abs($Inventorydet->qty_regulated); - $movement = (int) ($Inventorydet->qty_view < $Inventorydet->qty_stock); // 0 = add ; 1 = remove - - //$href = dol_buildpath('/inventory/inventory.php?id='.$this->id.'&action=view', 1); - - $res = $this->correctStock($product->id, $Inventorydet->fk_warehouse, $nbpiece, $movement, $langs->trans('inventoryMvtStock')); - if ($res < 0) return -1; - } - } - - if($conf->global->INVENTORY_DISABLE_VIRTUAL) - { - // Test if virtual product was enabled before regulate - if($pdt_virtuel) $conf->global->PRODUIT_SOUSPRODUITS = 1; - } - - return 1; - } - - /** - * Get the title - * @return string - */ - public function getTitle() - { - global $langs; - - return !empty($this->title) ? $this->title : $langs->trans('inventoryTitle').' '.$this->id; - } - - - /** - * Return clicable link of object (with eventually picto) - * - * @param int $withpicto Add picto into link - * @return string - */ - public function getNomUrl($withpicto = 1) - { - return ''.($withpicto ? img_picto('','object_list.png','',0).' ' : '').$this->getTitle().''; - } - - /** - * Function to add products by default from warehouse and children - * - * @param int $fk_warehouse id of warehouse - * @param int $fk_category id of category - * @param int $fk_supplier id of supplier - * @param int $only_prods_in_stock only product with stock - * - * @return int - */ - public function addProductsFor($fk_warehouse,$fk_category=0,$fk_supplier=0,$only_prods_in_stock=0) - { - $warehouse = new Entrepot($this->db); - $warehouse->fetch($fk_warehouse); - $TChildWarehouses = array($fk_warehouse); - $warehouse->get_children_warehouses($fk_warehouse, $TChildWarehouses); - - $sql = 'SELECT ps.fk_product, ps.fk_entrepot'; - $sql.= ' FROM '.MAIN_DB_PREFIX.'product_stock ps'; - $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'product p ON (p.rowid = ps.fk_product)'; - $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product cp ON (cp.fk_product = p.rowid)'; - $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_fournisseur_price pfp ON (pfp.fk_product = p.rowid)'; - $sql.= ' WHERE ps.fk_entrepot IN ('.implode(', ', $TChildWarehouses).')'; - - if ($fk_category>0) $sql.= ' AND cp.fk_categorie='.$fk_category; - if ($fk_supplier>0) $sql.= ' AND pfp.fk_soc = '.$fk_supplier; - if (!empty($only_prods_in_stock)) $sql.= ' AND ps.reel > 0'; - - $sql.=' GROUP BY ps.fk_product, ps.fk_entrepot ORDER BY p.ref ASC,p.label ASC'; - - $res = $this->db->query($sql); - if($res) - { - while($obj = $this->db->fetch_object($res)) - { - $this->addProduct($obj->fk_product, $obj->fk_entrepot); - } - - return 1; - } - else - { - $this->error = $this->db->lasterror(); - $this->errors[] = $this->db->lasterror(); - return -1; - } - } - - /** - * Return clicable link of inventory object - * - * @param int $id id of inventory - * @param int $withpicto Add picto into link - * @return string - */ - static function getLink($id, $withpicto=1) - { - global $langs,$db; - - $inventory = new Inventory($db); - if($inventory->fetch($id, false) > 0) return $inventory->getNomUrl($withpicto); - else return $langs->trans('InventoryUnableToFetchObject'); - } - - /** - * Function to get the sql select of inventory - * - * @param string $type 'All' to get all data - * @return string - */ - static function getSQL($type) - { - global $conf; - - $sql = ''; - if($type == 'All') - { - $sql = 'SELECT i.rowid,i.title, e.label, i.date_inventory, i.fk_warehouse, i.datec, i.tms, i.status'; - $sql.= ' FROM '.MAIN_DB_PREFIX.'inventory i'; - $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'entrepot e ON (e.rowid = i.fk_warehouse)'; - $sql.= ' WHERE i.entity IN ('.getEntity('inventory').')'; - } - - return $sql; - } } -class Inventorydet extends CoreObject +/** + * Class InventoryObjectLine + */ +class InventoryObjectLine { - public $element='inventorydet'; - public $table_element='inventorydet'; - protected $isnolinkedbythird = 1; // No field fk_soc - protected $ismultientitymanaged = 0; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe - - public $fk_inventory; - public $fk_warehouse; - public $fk_product; - public $entity; - public $qty_view; - public $qty_stock; - public $qty_regulated; - public $pmp; - public $pa; - public $new_pmp; - - protected $fields=array( - 'fk_inventory'=>array('type'=>'int') - ,'fk_warehouse'=>array('type'=>'int') - ,'fk_product'=>array('type'=>'int') - ,'entity'=>array('type'=>'int') - ,'qty_view'=>array('type'=>'float') - ,'qty_stock'=>array('type'=>'float') - ,'qty_regulated'=>array('type'=>'float') - ,'pmp'=>array('type'=>'float') - ,'pa'=>array('type'=>'float') - ,'new_pmp'=>array('type'=>'float') - ); - - /** - * Constructor - * - * @param DoliDB $db Database handler - */ - function __construct(DoliDB &$db) - { - global $conf; - - parent::__construct($db); - parent::init(); - - $this->entity = $conf->entity; - $this->errors = array(); - - $this->product = null; - $this->current_pa = 0; - } - - /** - * Get object and children from database - * - * @param int $id id of inventorydet object - * @param bool $loadChild load children - * @return int - */ - function fetch($id, $loadChild = true) - { - $res = parent::fetch($id); - $this->load_product(); - $this->fetch_current_pa(); - - return $res; - } - - /** - * Function to get the unit buy price - * - * @return bool - */ - function fetch_current_pa() - { - global $db,$conf; - - if(empty($conf->global->INVENTORY_USE_MIN_PA_IF_NO_LAST_PA)) return false; - - if($this->pa > 0) - { - $this->current_pa = $this->pa; - } - else - { - dol_include_once('/fourn/class/fournisseur.product.class.php'); - $p= new ProductFournisseur($db); - $p->find_min_price_product_fournisseur($this->fk_product); - - if($p->fourn_qty>0) $this->current_pa = $p->fourn_price / $p->fourn_qty; - } - - return true; - } - - /** - * Function to set pa attribute from date en fk_warehouse - * - * @param date $date date value - * @param int $fk_warehouse fk_warehouse target - */ - function setStockDate($date, $fk_warehouse) - { - list($pmp, $stock) = $this->getPmpStockFromDate($date, $fk_warehouse); - - $this->qty_stock = $stock; - $this->pmp = $pmp; - - $last_pa = 0; - $sql = 'SELECT price FROM '.MAIN_DB_PREFIX.'stock_mouvement'; - $sql.= ' WHERE fk_entrepot = '.$fk_warehouse; - $sql.= ' AND fk_product = '.$this->fk_product; - $sql.= ' AND (origintype=\'order_supplier\' || origintype=\'invoice_supplier\')'; - $sql.= ' AND price > 0'; - $sql.= ' AND datem <= \''.$date.' 23:59:59\''; - $sql.= ' ORDER BY datem DESC LIMIT 1'; - - $res = $this->db->query($sql); - if($res && $obj = $this->db->fetch_object($res)) - { - $last_pa = $obj->price; - } - - $this->pa = $last_pa; - } - - - /** - * Get the last pmp and last stock from date and warehouse - * - * @param date $date date to check - * @param int $fk_warehouse id of warehouse - * @return array - */ - function getPmpStockFromDate($date, $fk_warehouse) - { - $res = $this->product->load_stock(); - - if($res>0) - { - $stock = isset($this->product->stock_warehouse[$fk_warehouse]->real) ? $this->product->stock_warehouse[$fk_warehouse]->real : 0; - $pmp = $this->product->pmp; - } - - //All Stock mouvement between now and inventory date - $sql = 'SELECT value, price'; - $sql.= ' FROM '.MAIN_DB_PREFIX.'stock_mouvement'; - $sql.= ' WHERE fk_product = '.$this->product->id; - $sql.= ' AND fk_entrepot = '.$fk_warehouse; - $sql.= ' AND datem > \''.date('Y-m-d 23:59:59', strtotime($date)).'\''; - $sql.= ' ORDER BY datem DESC'; - - $res = $this->db->query($sql); - - $laststock = $stock; - $lastpmp = $pmp; - - if($res) - { - while($mouvement = $this->db->fetch_object($res)) - { - $price = ($mouvement->price > 0 && $mouvement->value > 0) ? $mouvement->price : $lastpmp; - $stock_value = $laststock * $lastpmp; - $laststock -= $mouvement->value; - $last_stock_value = $stock_value - ($mouvement->value * $price); - $lastpmp = ($laststock != 0) ? $last_stock_value / $laststock : $lastpmp; - } - } - - return array($lastpmp, $laststock); - } - - /** - * Fetch the product linked with the line - * @return void - */ - function load_product() - { - global $db; - - if($this->fk_product>0) - { - $this->product = new Product($db); - $this->product->fetch($this->fk_product); - } - } + /** + * @var int ID + */ + public $id; + /** + * @var mixed Sample line property 1 + */ + public $prop1; + /** + * @var mixed Sample line property 2 + */ + public $prop2; } diff --git a/htdocs/product/inventory/list.php b/htdocs/product/inventory/list.php index c8d570a6fd7..2a8d9861e5a 100644 --- a/htdocs/product/inventory/list.php +++ b/htdocs/product/inventory/list.php @@ -1,5 +1,6 @@ +/* Copyright (C) 2007-2017 Laurent Destailleur + * 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 @@ -16,119 +17,623 @@ */ /** - * \file htdocs/inventory/list.php - * \ingroup product - * \brief File of class to manage inventory + * \file product/inventory/list.php + * \ingroup inventory + * \brief List page for monmodule */ - -require_once '../../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/product/inventory/listview.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/ajax.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; -include_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/inventory/class/inventory.class.php'; -require_once DOL_DOCUMENT_ROOT.'/product/inventory/lib/inventory.lib.php'; +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION','1'); // Do not check anti CSRF attack test +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti CSRF attack test +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check anti CSRF attack test +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK','1'); // Do not check style html tag into posted data +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Do not check anti POST attack test +//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) -$langs->load("stock"); -$langs->load("inventory"); +// 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 caluclated 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'; +dol_include_once('/inventory/class/inventory.class.php'); + +// Load traductions files requiredby by page +$langs->loadLangs(array("inventory","other")); + +$action = GETPOST('action','alpha'); +$massaction = GETPOST('massaction','alpha'); +$show_files = GETPOST('show_files','int'); +$confirm = GETPOST('confirm','alpha'); +$cancel = GETPOST('cancel', 'alpha'); +$toselect = GETPOST('toselect', 'array'); +$contextpage= GETPOST('contextpage','aZ')?GETPOST('contextpage','aZ'):'inventorylist'; // To manage different context of search + +$id = GETPOST('id','int'); +$backtopage = GETPOST('backtopage'); +$optioncss = GETPOST('optioncss','alpha'); + +// Load variable for pagination $limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit; -$sortfield = GETPOST("sortfield",'alpha'); -$sortorder = GETPOST("sortorder",'alpha'); -$page = (GETPOST("page",'int')?GETPOST("page", 'int'):0); +$sortfield = GETPOST('sortfield','alpha'); +$sortorder = GETPOST('sortorder','alpha'); +$page = 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="i.title"; + +// Initialize technical objects +$object=new Inventory($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction=$conf->inventory->dir_output . '/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('inventorylist')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label('inventory'); +$search_array_options=$extrafields->getOptionalsFromPost($extralabels,'','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"; -if (empty($user->rights->stock->lire)) accessforbidden(); - - -/* - * Actions - */ - -// None - - -/* - * View - */ - -llxHeader('',$langs->trans('inventoryListTitle'),'',''); - -echo '
'; - -$inventory = new Inventory($db); -$list = new ListView($db, 'listInventory'); - -$THide = array('label','title'); - -echo $list->render(Inventory::getSQL('All'), array( - 'param' => array( - 'limit' => $limit, - 'offset' => $offset, - 'sortfield' => $sortfield, - 'sortorder'=> $sortorder, - 'page'=>$page - ), - 'limit' => array( - 'nbLine' => $limit, - ), - 'allow-field-select' => true, - 'link'=>array( - 'fk_warehouse'=>''.img_picto('','object_stock.png','',0).' @label@' - ), - 'translate'=>array(), - 'hide'=>$THide, - 'type'=>array( - 'datec'=>'date', - 'tms'=>'datetime', - 'date_inventory'=>'date' - ), - 'list'=>array( - 'title'=>$langs->trans('inventoryListTitle'), - 'messageNothing'=>$langs->trans('inventoryListEmpty'), - 'image' => 'title_products.png' - ), - 'title'=>array( - 'rowid'=>$langs->trans('Title'), - 'date_inventory'=>$langs->trans('InventoryDate'), - 'fk_warehouse'=>$langs->trans('Warehouse'), - 'datec'=>$langs->trans('DateCreation'), - 'tms'=>$langs->trans('DateModification'), - 'status'=>$langs->trans('Status') - ), - 'eval'=>array( - 'status' => '(@val@ ? img_picto("'.$langs->trans("inventoryValidate").'", "statut4") : img_picto("'.$langs->trans("inventoryDraft").'", "statut3"))', - 'rowid'=>'Inventory::getLink(@val@)' - ), - 'position' => array( - 'text-align' => array('status' => 'right') - - ), - 'search'=>array( - 'rowid' => array('search_type' => true, 'table' => array('i'), 'field' => array('title')), - 'date_inventory'=>array('search_type' => 'calendars', 'table' => array('i'), 'field' => array('date_inventory')), - 'status'=>array('search_type' => array(1=>$langs->trans("inventoryValidate"), 0=>$langs->trans("inventoryDraft"))) - ) -)); - - -/*if (!empty($user->rights->stock->create)) +// Protection if external user +$socid=0; +if ($user->societe_id > 0) { - print '
'; - print ''.$langs->trans('inventoryCreate').''; + //$socid = $user->societe_id; + accessforbidden(); +} + +// Initialize array of search criterias +$search_all=trim(GETPOST("search_all",'alpha')); +$search=array(); +foreach($object->fields as $key => $val) +{ + if (GETPOST('search_'.$key,'alpha')) $search[$key]=GETPOST('search_'.$key,'alpha'); +} + +// 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 fields for list +$arrayfields=array(); +foreach($object->fields as $key => $val) +{ + // If $val['visible']==0, then we never show the field + if (! empty($val['visible'])) $arrayfields['t.'.$key]=array('label'=>$val['label'], 'checked'=>(($val['visible']<0)?0:1), 'enabled'=>$val['enabled']); +} +// Extra fields +if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) +{ + foreach($extrafields->attribute_label as $key => $val) + { + $arrayfields["ef.".$key]=array('label'=>$extrafields->attribute_label[$key], 'checked'=>$extrafields->attribute_list[$key], 'position'=>$extrafields->attribute_pos[$key], 'enabled'=>$extrafields->attribute_perms[$key]); + } +} + + + + +/* + * ACTIONS + * + * Put here all code to do according to value of "$action" parameter + */ + +if (GETPOST('cancel')) { $action='list'; $massaction=''; } +if (! GETPOST('confirmmassaction') && $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]=''; + } + $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='Inventory'; + $objectlabel='Inventory'; + $permtoread = $user->rights->inventory->read; + $permtodelete = $user->rights->inventory->delete; + $uploaddir = $conf->inventory->dir_output; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; +} + + + +/* + * VIEW + * + * Put here all code to build page + */ + +$form=new Form($db); + +$now=dol_now(); + +//$help_url="EN:Module_Inventory|FR:Module_Inventory_FR|ES:Módulo_Inventory"; +$help_url=''; +$title = $langs->trans('ListOf', $langs->transnoentitiesnoconv("Inventorys")); + + +// Build and execute select +// -------------------------------------------------------------------- +$sql = 'SELECT '; +foreach($object->fields as $key => $val) +{ + $sql.='t.'.$key.', '; +} +// Add fields from extrafields +foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ", ef.".$key.' as options_'.$key : ''); +// Add fields from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListSelect',$parameters); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; +$sql=preg_replace('/, $/','', $sql); +$sql.= " FROM ".MAIN_DB_PREFIX."inventory as t"; +if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."inventory_extrafields as ef on (t.rowid = ef.fk_object)"; +$sql.= " WHERE t.entity IN (".getEntity('inventory').")"; +foreach($search as $key => $val) +{ + if ($search[$key] != '') $sql.=natural_search($key, $search[$key], (($key == 'status')?2:($object->fields[$key]['type'] == 'integer'?1:0))); +} +if ($search_all) $sql.= natural_search(array_keys($fieldstosearchall), $search_all); +// Add where from extra fields +foreach ($search_array_options as $key => $val) +{ + $crit=$val; + $tmpkey=preg_replace('/search_options_/','',$key); + $typ=$extrafields->attribute_type[$tmpkey]; + $mode=0; + if (in_array($typ, array('int','double','real'))) $mode=1; // Search on a numeric + if ($val && ( ($crit != '' && ! in_array($typ, array('select'))) || ! empty($crit))) + { + $sql .= natural_search('ef.'.$tmpkey, $crit, $mode); + } +} +// Add where from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListWhere',$parameters); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; +$sql.=$db->order($sortfield,$sortorder); + +// Count total nb of records +$nbtotalofrecords = ''; +if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) +{ + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); +} + +$sql.= $db->plimit($limit+1, $offset); + +dol_syslog($script_file, LOG_DEBUG); +$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) +{ + $obj = $db->fetch_object($resql); + $id = $obj->rowid; + header("Location: ".DOL_URL_ROOT.'/inventory/inventory_card.php?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='.$contextpage; +if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit; +foreach($search as $key => $val) +{ + $param.= '&search_'.$key.'='.urlencode($search[$key]); +} +if ($optioncss != '') $param.='&optioncss='.$optioncss; +// Add $param from extra fields +foreach ($search_array_options as $key => $val) +{ + $crit=$val; + $tmpkey=preg_replace('/search_options_/','',$key); + if ($val != '') $param.='&search_options_'.$tmpkey.'='.urlencode($val); +} + +$arrayofmassactions = array( + 'presend'=>$langs->trans("SendByMail"), + 'builddoc'=>$langs->trans("PDFMerge"), +); +if ($user->rights->inventory->delete) $arrayofmassactions['delete']=$langs->trans("Delete"); +if ($massaction == 'presend') $arrayofmassactions=array(); +$massactionbutton=$form->selectMassAction('', $arrayofmassactions); + +print ''; +if ($optioncss != '') print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_companies', 0, '', '', $limit); + +if ($sall) +{ + foreach($fieldstosearchall as $key => $val) $fieldstosearchall[$key]=$langs->trans($val); + print $langs->trans("FilterOnInto", $sall) . join(', ',$fieldstosearchall); +} + +$moreforfilter = ''; +$moreforfilter.='
'; +$moreforfilter.= $langs->trans('MyFilter') . ': '; +$moreforfilter.= '
'; + +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldPreListTitle',$parameters); // 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 '
'; -}*/ +} -echo ''; +$varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; +$selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields.=$form->showCheckAddButtons('checkforselect', 1); -llxFooter(''); -$db->close(); \ No newline at end of file +print '
'; +print ''."\n"; + + +// Fields title search +// -------------------------------------------------------------------- +print ''; +foreach($object->fields as $key => $val) +{ + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; + $align=''; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; + if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; + if (! empty($arrayfields['t.'.$key]['checked'])) print ''; +} +// Extra fields +if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) +{ + foreach($extrafields->attribute_label as $key => $val) + { + if (! empty($arrayfields["ef.".$key]['checked'])) + { + $align=$extrafields->getAlignFlag($key); + $typeofextrafield=$extrafields->attribute_type[$key]; + print ''; + } + } +} +// Fields from hook +$parameters=array('arrayfields'=>$arrayfields); +$reshook=$hookmanager->executeHooks('printFieldListOption',$parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Rest of fields search +foreach($object->fields as $key => $val) +{ + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; + $align=''; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; + if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; + if (! empty($arrayfields['t.'.$key]['checked'])) print ''; +} +// Action column +print ''; +print ''."\n"; + + +// Fields title label +// -------------------------------------------------------------------- +print ''; +foreach($object->fields as $key => $val) +{ + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; + $align=''; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; + if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; + if (! empty($arrayfields['t.'.$key]['checked'])) print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; +} +// Extra fields +if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) +{ + foreach($extrafields->attribute_label as $key => $val) + { + if (! empty($arrayfields["ef.".$key]['checked'])) + { + $align=$extrafields->getAlignFlag($key); + $sortonfield = "ef.".$key; + if (! empty($extrafields->attribute_computed[$key])) $sortonfield=''; + print getTitleFieldOfList($langs->trans($extralabels[$key]), 0, $_SERVER["PHP_SELF"], $sortonfield, "", $param, ($align?'align="'.$align.'"':''), $sortfield, $sortorder)."\n"; + } + } +} +// Hook fields +$parameters=array('arrayfields'=>$arrayfields); +$reshook=$hookmanager->executeHooks('printFieldListTitle',$parameters); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Rest of fields title +foreach($object->fields as $key => $val) +{ + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; + $align=''; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; + if (in_array($val['type'], array('timestamp'))) $align.=' nowrap'; + if (! empty($arrayfields['t.'.$key]['checked'])) print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($align?'class="'.$align.'"':''), $sortfield, $sortorder, $align.' ')."\n"; +} +print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"],"",'','','align="center"',$sortfield,$sortorder,'maxwidthsearch ')."\n"; +print ''."\n"; + + +// Detect if we need a fetch on each output line +$needToFetchEachLine=0; +foreach ($extrafields->attribute_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 < min($num, $limit)) +{ + $obj = $db->fetch_object($resql); + if ($obj) + { + // Store properties in $object + $object->id = $obj->rowid; + foreach($object->fields as $key => $val) + { + if (isset($obj->$key)) $object->$key = $obj->$key; + } + + // Show here line of result + print ''; + foreach($object->fields as $key => $val) + { + if (in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; + $align=''; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align='center'; + if (in_array($val['type'], array('timestamp'))) $align.='nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; + if (! empty($arrayfields['t.'.$key]['checked'])) + { + print ''; + if (in_array($val['type'], array('date','datetime','timestamp'))) print dol_print_date($db->jdate($obj->$key), 'dayhour'); + elseif ($key == 'ref') print $object->getNomUrl(1); + elseif ($key == 'status') print $object->getLibStatut(3); + else print $obj->$key; + print ''; + if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key; + $totalarray['val']['t.'.$key] += $obj->$key; + } + } + } + // Extra fields + if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) + { + foreach($extrafields->attribute_label as $key => $val) + { + if (! empty($arrayfields["ef.".$key]['checked'])) + { + print 'getAlignFlag($key); + if ($align) print ' align="'.$align.'"'; + print '>'; + $tmpkey='options_'.$key; + print $extrafields->showOutputField($key, $obj->$tmpkey, '', 1); + print ''; + if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='ef.'.$tmpkey; + $totalarray['val']['ef.'.$tmpkey] += $obj->$tmpkey; + } + } + } + } + // Fields from hook + $parameters=array('arrayfields'=>$arrayfields, 'obj'=>$obj); + $reshook=$hookmanager->executeHooks('printFieldListValue',$parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Rest of fields + foreach($object->fields as $key => $val) + { + if (! in_array($key, array('date_creation', 'tms', 'import_key', 'status'))) continue; + $align=''; + if (in_array($val['type'], array('date','datetime','timestamp'))) $align.=($align?' ':'').'center'; + if (in_array($val['type'], array('timestamp'))) $align.=($align?' ':'').'nowrap'; + if ($key == 'status') $align.=($align?' ':'').'center'; + if (! empty($arrayfields['t.'.$key]['checked'])) + { + print ''; + if (in_array($val['type'], array('date','datetime','timestamp'))) print dol_print_date($db->jdate($obj->$key), 'dayhour'); + elseif ($key == 'status') print $object->getLibStatut(3); + else print $obj->$key; + print ''; + if (! $i) $totalarray['nbfield']++; + if (! empty($val['isameasure'])) + { + if (! $i) $totalarray['pos'][$totalarray['nbfield']]='t.'.$key; + $totalarray['val']['t.'.$key] += $obj->$key; + } + } + } + // Action column + print ''; + if (! $i) $totalarray['nbfield']++; + + print ''; + } + $i++; +} + +// Show total line +if (isset($totalarray['pos'])) +{ + print ''; + $i=0; + while ($i < $totalarray['nbfield']) + { + $i++; + if (! empty($totalarray['pos'][$i])) print ''; + else + { + if ($i == 1) + { + if ($num < $limit) print ''; + else print ''; + } + print ''; + } + } + print ''; +} + +// 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); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print '
'; + if (in_array($typeofextrafield, array('varchar', 'int', 'double', 'select')) && empty($extrafields->attribute_computed[$key])) + { + $crit=$val; + $tmpkey=preg_replace('/search_options_/','',$key); + $searchclass=''; + if (in_array($typeofextrafield, array('varchar', 'select'))) $searchclass='searchstring'; + if (in_array($typeofextrafield, array('int', 'double'))) $searchclass='searchnum'; + print ''; + } + print ''; +$searchpicto=$form->showFilterButtons(); +print $searchpicto; +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($obj->rowid, $arrayofselected)) $selected=1; + print ''; + } + print '
'.price($totalarray['val'][$totalarray['pos'][$i]]).''.$langs->trans("Total").''.$langs->trans("Totalforthispage").'
'.$langs->trans("NoRecordFound").'
'."\n"; +print '
'."\n"; + +print ''."\n"; + +if ($nbtotalofrecords === '' || $nbtotalofrecords) +{ + if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) + { + 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=$user->rights->inventory->read; + $delallowed=$user->rights->inventory->read; + + print $formfile->showdocuments('massfilesarea_inventory','',$filedir,$urlsource,0,$delallowed,'',1,1,0,48,1,$param,$title,''); + } + else + { + print '
'.$langs->trans("ShowTempMassFilesArea").''; + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/htdocs/product/inventory/listview.class.php b/htdocs/product/inventory/listview.class.php deleted file mode 100644 index 3dddac44516..00000000000 --- a/htdocs/product/inventory/listview.class.php +++ /dev/null @@ -1,1083 +0,0 @@ - - - This program and all files within this directory and sub directory - 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 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 . - */ - -/** - * Class to manage the lists view - */ -class Listview -{ - /** - * Constructor - * - * @param DoliDB $db Database handler - * @param string $id html id - */ - function __construct(&$db, $id) - { - $this->db = &$db; - $this->id = $id; - $this->TTotalTmp=array(); - $this->sql = ''; - $this->form = null; - $this->totalRowToShow=0; - $this->totalRow=0; - - $this->TField=array(); - - require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; - $this->extrafields = new ExtraFields($this->db); - $this->extralabels = $this->extrafields->fetch_name_optionals_label('product'); - $this->search_array_options=$this->extrafields->getOptionalsFromPost($this->extralabels,'','search_'); - } - - /** - * Function to init fields - * - * @param array $TParam array of configuration of list - * @return bool - */ - private function init(&$TParam) - { - global $conf, $langs, $user; - - if(!isset($TParam['hide'])) $TParam['hide']=array(); - if(!isset($TParam['link'])) $TParam['link']=array(); - if(!isset($TParam['type'])) $TParam['type']=array(); - if(!isset($TParam['orderby']['noOrder'])) $TParam['orderby']['noOrder']=array(); - if(!isset($TParam['allow-fields-select'])) $TParam['allow-fields-select'] = 0; - - if(!isset($TParam['list']))$TParam['list']=array(); - $TParam['list'] = array_merge(array( - 'messageNothing'=>$langs->trans('ListMessageNothingToShow') - ,'noheader'=>0 - ,'useBottomPagination'=>0 - ,'image'=>'' - ,'title'=>$langs->trans('List') - ,'orderDown'=>'' - ,'orderUp'=>'' - ,'id'=>$this->id - ,'head_search'=>'' - ,'export'=>array() - ,'view_type'=>'' - ,'massactions'=>array() - ),$TParam['list']); - - if (empty($TParam['limit'])) $TParam['limit'] = array(); - - $page = GETPOST('page'); - if (!empty($page)) $TParam['limit']['page'] = $page; - - $TParam['limit'] = array_merge(array('page'=>0, 'nbLine' => $conf->liste_limit, 'global'=>0), $TParam['limit']); - - if (GETPOST('sortfield')) - { - $TParam['sortfield'] = GETPOST('sortfield'); - $TParam['sortorder'] = GETPOST('sortorder'); - } - - include_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; - $this->form = new Form($this->db); - } - - - /** - * Function to know if we can search on null value - * @param string $key field name - * @param array $TParam array of configuration - * @return bool - */ - private function getSearchNull($key, &$TParam) - { - return !empty($TParam['search'][$key]['allow_is_null']); - } - - /** - * @param string $key field name - * @param string $TParam array of configuration - * @return array - */ - private function getSearchKey($key, &$TParam) - { - $TPrefixe = array(); - if(!empty($TParam['search'][$key]['table'])) - { - if (!is_array($TParam['search'][$key]['table'])) $TParam['search'][$key]['table'] = array($TParam['search'][$key]['table']); - - foreach ($TParam['search'][$key]['table'] as $prefix_table) - { - $TPrefixe[] = $prefix_table.'.'; - } - } - - $TKey=array(); - if(!empty($TParam['search'][$key]['field'])) - { - if (!is_array($TParam['search'][$key]['field'])) $TParam['search'][$key]['field'] = array($TParam['search'][$key]['field']); - - foreach ($TParam['search'][$key]['field'] as $i => $field) - { - $prefixe = !empty($TPrefixe[$i]) ? $TPrefixe[$i] : $TPrefixe[0]; - $TKey[] = $prefixe. $field ; - } - } - else - { - $TKey[] = $TPrefixe[0].$key; - } - - return $TKey; - } - /** - * @param string $TSQLMore contain some additional sql instructions - * @param string $value date with read format - * @param string $sKey field name - */ - private function addSqlFromTypeDate(&$TSQLMore, &$value, $sKey) - { - if(is_array($value)) - { - $TSQLDate=array(); - if(!empty($value['start'])) - { - $TSQLDate[]=$sKey." >= '".$value['start']."'" ; - } - - if(!empty($value['end'])) - { - $TSQLDate[]=$sKey." <= '".$value['end']."'" ; - } - - if(!empty($TSQLDate)) $TSQLMore[] = implode(' AND ', $TSQLDate); - } - else - { - $TSQLMore[]=$sKey." LIKE '".$value."%'" ; - } - } - - - /** - * @param string $TSQLMore contain some additional sql instructions - * @param string $value value to filter - * @param string $TParam array of configuration - * @param string $sKey field name - * @param string $key reference of sKey to find value into TParam - * @return bool - */ - private function addSqlFromOther(&$TSQLMore, &$value, &$TParam, $sKey, $key) - { - // Do not use empty() function, statut 0 exist - if ($value == '') return false; - elseif($value==-1) return false; - - if(isset($TParam['operator'][$key])) - { - if($TParam['operator'][$key] == '<' || $TParam['operator'][$key] == '>' || $TParam['operator'][$key]=='=') - { - $TSQLMore[] = $sKey . ' ' . $TParam['operator'][$key] . ' "' . $value . '"'; - } - elseif ($TParam['operator'][$key]=='IN') - { - $TSQLMore[] = $sKey . ' ' . $TParam['operator'][$key] . ' (' . $value . ')'; - } - else - { - if(strpos($value,'%')===false) $value = '%'.$value.'%'; - $TSQLMore[]=$sKey." LIKE '".addslashes($value)."'" ; - } - } - else - { - if(strpos($value,'%')===false) $value = '%'.$value.'%'; - $TSQLMore[]=$sKey." LIKE '".addslashes($value)."'" ; - } - - return true; - } - - - /** - * @param string $sql standard select sql - * @param string $TParam array of configuration - * @return string - */ - private function search($sql, &$TParam) - { - if (empty($TParam['no-auto-sql-search']) && !GETPOST('button_removefilter_x','alpha') && !GETPOST('button_removefilter.x','alpha') && !GETPOST('button_removefilter','alpha')) - { - foreach ($TParam['search'] as $field => $info) - { - $TsKey = $this->getSearchKey($field, $TParam); - $TSQLMore = array(); - $allow_is_null = $this->getSearchNull($field,$TParam); - - $fieldname = !empty($info['fieldname']) ? $info['fieldname'] : 'Listview_'.$this->id.'_search_'.$field; - - foreach ($TsKey as $i => &$sKey) - { - $value = GETPOST($fieldname); - $value_null = GETPOST('Listview_'.$this->id.'_search_on_null_'.$field); - - if ($allow_is_null && !empty($value_null)) - { - $TSQLMore[] = $sKey.' IS NULL '; - $value = ''; - } - - if (isset($TParam['type'][$field]) && ($TParam['type'][$field]==='date' || $TParam['type'][$field]==='datetime')) - { - $k = $fieldname; - if ($info['search_type'] === 'calendars') - { - $value = array(); - - $timestart = dol_mktime(0, 0, 0, GETPOST($k.'_startmonth'), GETPOST($k.'_startday'), GETPOST($k.'_startyear')); - if ($timestart) $value['start'] = date('Y-m-d', $timestart); - - $timeend = dol_mktime(23, 59, 59, GETPOST($k.'_endmonth'), GETPOST($k.'_endday'), GETPOST($k.'_endyear')); - if ($timeend) $value['end'] = date('Y-m-d', $timeend); - } - else - { - $time = dol_mktime(12, 0, 0, GETPOST($k.'month'), GETPOST($k.'day'), GETPOST($k.'year')); - if ($time) $value = date('Y-m-d', $time); - } - - if (!empty($value)) $this->addSqlFromTypeDate($TSQLMore, $value, $sKey); - } - else - { - $this->addSqlFromOther($TSQLMore, $value, $TParam, $sKey, $field); - } - } - - if (!empty($TSQLMore)) - { - $sql.=' AND ( '.implode(' OR ',$TSQLMore).' ) '; - } - } - } - - if ($sqlGROUPBY!='') $sql.=' GROUP BY '.$sqlGROUPBY; - - return $sql; - } - - /** - * @param string $sql standard select sql - * @param string $TParam array of configuration - * @return string - */ - public function render($sql, $TParam=array()) - { - global $conf; - - $TField= & $this->TField; - - $this->init($TParam); - - $THeader = $this->initHeader($TParam); - - $sql = $this->search($sql,$TParam); - $sql.= $this->db->order($TParam['sortfield'], $TParam['sortorder']); - - if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) - { - $result = $this->db->query($sql); - $this->totalRow = $this->db->num_rows($result); - } - - $this->parse_sql($THeader, $TField, $TParam, $sql); - list($TTotal, $TTotalGroup)=$this->get_total($TField, $TParam); - - return $this->renderList($THeader, $TField, $TTotal, $TTotalGroup, $TParam); - } - - /** - * @param string $THeader the configuration of header - * @param string $TParam array of configuration - * @return array - */ - private function setSearch(&$THeader, &$TParam) - { - global $langs, $form; - - if(empty($TParam['search'])) return array(); - - $TSearch=array(); - - $nb_search_in_bar = 0; - - foreach($THeader as $key => $libelle) - { - if(empty($TSearch[$key]))$TSearch[$key]=''; - } - - $removeFilter = (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha')); - foreach($TParam['search'] as $key => $param_search) - { - if ($removeFilter) $value = ''; - - $typeRecherche = (is_array($param_search) && isset($param_search['search_type'])) ? $param_search['search_type'] : $param_search; - - $fieldname = !empty($param_search['fieldname']) ? $param_search['fieldname'] : 'Listview_'.$this->id.'_search_'.$key; - $value = $removeFilter ? '' : GETPOST($fieldname); - - if(is_array($typeRecherche)) - { - $fsearch=$form->selectarray($fieldname, $typeRecherche,$value,1); - } - else if($typeRecherche==='calendar') - { - if (!$removeFilter) $value = GETPOST($fieldname) ? mktime(0,0,0, (int) GETPOST($fieldname.'month'), (int) GETPOST($fieldname.$key.'day'), (int) GETPOST($fieldname.'year') ) : ''; - - $fsearch = $form->select_date($value, $fieldname,0, 0, 1, "", 1, 0, 1); - } - else if($typeRecherche==='calendars') - { - $value_start = $value_end = ''; - if (!$removeFilter) - { - $value_start = GETPOST($fieldname.'_start') ? mktime(0,0,0, (int) GETPOST($fieldname.'_startmonth'), (int) GETPOST($fieldname.'_startday'), (int) GETPOST($fieldname.'_startyear') ) : ''; - $value_end = GETPOST($fieldname.'_end') ? mktime(0,0,0, (int) GETPOST($fieldname.'_endmonth'), (int) GETPOST($fieldname.'_endday'), (int) GETPOST($fieldname.'_endyear') ) : ''; - } - - $fsearch = $form->select_date($value_start,$fieldname.'_start',0, 0, 1, "", 1, 0, 1) - . $form->select_date($value_end, $fieldname.'_end',0, 0, 1, "", 1, 0, 1); - - } - else if(is_string($typeRecherche)) - { - $fsearch=$TParam['search'][$key]; - } - else - { - $fsearch=''; - } - - if(!empty($param_search['allow_is_null'])) - { - $valueNull = GETPOST($fieldname.'search_on_null_'.$key) ? 1 : 0; - $fsearch.=' '.$form->checkbox1('', $fieldname.'search_on_null_'.$key,1, $valueNull,' onclick=" if($(this).is(\':checked\')){ $(this).prev().val(\'\'); }" ').img_help(1, $langs->trans('SearchOnNUllValue')); - } - - if(!empty($THeader[$key])) - { - $TSearch[$key] = $fsearch; - $nb_search_in_bar++; - } - } - - $search_button = ' '.img_search().''; - $search_button .= ' '.img_searchclear().''; - - if($nb_search_in_bar>0) - { - end($TSearch); - list($key,$v) = each($TSearch); - $TSearch[$key].=$search_button; - } - else - { - $TSearch=array(); - } - - return $TSearch; - } - - /** - * Function to analyse and calculate the total from a column - * - * @param string $TField TField - * @param string $TParam TParam - * @return array - */ - private function get_total(&$TField, &$TParam) - { - $TTotal=$TTotalGroup=array(); - - if(!empty($TParam['math']) && !empty($TField[0])) - { - foreach($TField[0] as $field=>$value) - { - $TTotal[$field]=''; - $TTotalGroup[$field] = ''; - } - - foreach($TParam['math'] as $field=>$typeMath) - { - if(is_array($typeMath)) - { - $targetField = $typeMath[1]; - $typeMath = $typeMath[0]; - } - else - { - $targetField = $field; - } - - if($typeMath == 'groupsum') - { - $TTotalGroup[$field] = array('target'=>$targetField, 'values'=> $this->TTotalTmp['@groupsum'][$targetField]); - } - else if($typeMath=='average') - { - $TTotal[$field]=array_sum($this->TTotalTmp[$targetField]) / count($this->TTotalTmp[$targetField]); - } - elseif($typeMath=='count') - { - $TTotal[$field]=count($this->TTotalTmp[$targetField]); - } - else - { - $TTotal[$field]=array_sum($this->TTotalTmp[$targetField]); - } - } - } - - return array($TTotal,$TTotalGroup); - } - - /** - * @return string - */ - /* - private function getJS() - { - $javaScript = ''; - - return $javaScript; - } - */ - - /** - * @param string $TParam TParam - * @param string $TField TField - * @param string $THeader THeader - * @return array - */ - private function setExport(&$TParam, $TField, $THeader) - { - global $langs; - - $Tab=array(); - if(!empty($TParam['export'])) - { - $token = GETPOST('token'); - if(empty($token)) $token = md5($this->id.time().rand(1,9999)); - - $_SESSION['token_list_'.$token] = gzdeflate( serialize( array( - 'title'=>$this->title, - 'sql'=>$this->sql, - 'TBind'=>$this->TBind, - 'TChamps'=>$TField, - 'TEntete'=>$THeader - ))); - - foreach($TParam['export'] as $mode_export) - { - $Tab[] = array( - 'label'=>$langs->trans('Export'.$mode_export), - 'url'=>dol_buildpath('/abricot/downlist.php',1), - 'mode'=>$mode_export, - 'token'=>$token, - 'session_name'=>session_name() - ); - } - - } - - return $Tab; - } - - /** - * @param string $TField TField - * @param string $TTotalGroup TTotalGroup - * @return array - */ - private function addTotalGroup($TField, $TTotalGroup) - { - global $langs; - - $Tab=array(); - $proto_total_line = array(); - $tagbase = $old_tagbase = null; - $addGroupLine = false; - - foreach($TField as $k=>&$line) - { - if(empty($proto_total_line)) - { - foreach($line as $field=>$value) - { - $proto_total_line[$field] = ''; - } - $group_line = $proto_total_line; - } - - $addGroupLine = false; - - $tagbase = ''; - foreach($line as $field=>$value) - { - if(!empty($TTotalGroup[$field])) - { - $tagbase.=$value.'|'; - $group_line[$field] = '
'.(empty($value) ? $langs->trans('Empty') : $value ).' :
'; - $group_line[$TTotalGroup[$field]['target']] = '
'.price($TTotalGroup[$field]['values'][$value]).'
'; - $addGroupLine = true; - } - } - - if(!is_null($old_tagbase) && $old_tagbase!=$tagbase && $addGroupLine) - { - $Tab[] = $previous_group_line; - } - - $old_tagbase = $tagbase; - $previous_group_line = $group_line; - $group_line = $proto_total_line; - - $Tab[] = $line; - } - - if($addGroupLine) - { - $Tab[] = $previous_group_line; - } - - return $Tab; - } - - /** - * @param string $THeader THeader - * @param string $TField TField - * @param string $TTotal TTotal - * @param string $TTotalGroup TTotalGroup - * @param string $TParam TParam - * @return string - */ - private function renderList(&$THeader, &$TField, &$TTotal, &$TTotalGroup, &$TParam) - { - global $bc,$form; - - $TSearch = $this->setSearch($THeader, $TParam); - $TExport = $this->setExport($TParam, $TField, $THeader); - $TField = $this->addTotalGroup($TField,$TTotalGroup); - - //$out = $this->getJS(); - - $massactionbutton= empty($TParam['list']['massactions']) ? '' : $form->selectMassAction('', $TParam['list']['massactions']); - - $dolibarr_decalage = $this->totalRow > $this->totalRowToShow ? 1 : 0; - ob_start(); - print_barre_liste($TParam['list']['title'], $TParam['limit']['page'], $_SERVER["PHP_SELF"], '&'.$TParam['list']['param_url'], $TParam['sortfield'], $TParam['sortorder'], $massactionbutton, $this->totalRowToShow+$dolibarr_decalage, $this->totalRow, $TParam['list']['image'], 0, '', '', $TParam['limit']['nbLine']); - $out .= ob_get_clean(); - - $classliste='liste'; - if(!empty($TParam['head_search'])) { - $out.='
'; - $out.=$TParam['head_search']; - $out.='
'; - - $classliste.=' listwithfilterbefore'; - } - - $out.= '
'; - $out.= ''; - - if(count($TSearch)>0) - { - $out.=''; - - foreach ($THeader as $field => $head) - { - if ($field === 'selectedfields') - { - $out.= ''; - } - else - { - $moreattrib = 'style="width:'.$head['width'].';text-align:'.$head['text-align'].'"'; - $out .= ''; - } - } - - $out.=''; - } - - $out.= ''; - foreach($THeader as $field => $head) - { - $moreattrib = ''; - $search = ''; - $prefix = ''; - - $label = $head['label']; - - if ($field === 'selectedfields') - { - $moreattrib = 'align="right" '; - $prefix = 'maxwidthsearch '; - - if(!empty($TParam['list']['massactions'])) { - $label.=$form->showCheckAddButtons('checkforselect', 1); - } - - } - - if (empty($head['width'])) $head['width'] = 'auto'; - if (!empty($head['width']) && !empty($head['text-align'])) $moreattrib .= 'style="width:'.$head['width'].';text-align:'.$head['text-align'].'"'; - - if (isset($TParam['search'][$field]['search_type']) && $TParam['search'][$field]['search_type'] !== false) - { - $TsKey = $this->getSearchKey($field, $TParam); - if (!empty($TsKey)) $search = implode(',', $TsKey); - else $search = $field; - } - - $out .= getTitleFieldOfList($label, 0, $_SERVER["PHP_SELF"], $search, '', $moreparam, $moreattrib, $TParam['sortfield'], $TParam['sortorder'], $prefix); - $out .= $head['more']; - } - - //$out .= ''; - $out .= ''; - - $out.=''; - - if(empty($TField)) - { - if (!empty($TParam['list']['messageNothing'])) $out .= ''; - } - else - { - $line_number = 0; - foreach($TField as $fields) - { - if($this->in_view($TParam, $line_number)) - { - $out.=''; - - foreach ($THeader as $field => $head) - { - $value_aff =(isset($fields[$field]) ? $fields[$field] : ' '); - - if ($field === 'selectedfields') - { - $head['text-align']='center'; - if(!empty($TParam['list']['massactions'])) { - $arrayofselected=array(); // TODO get in param - $selected=0; - if (in_array($obj->rowid, $arrayofselected)) $selected=1; - $value_aff.=''; - } - } - - $moreattrib = 'style="width:'.$head['width'].';text-align:'.$head['text-align'].'"'; - $out.=''; - } - - $out.=''; - } - - $line_number++; - } - - $out.=''; - - if (!empty($TParam['list']['haveTotal'])) - { - $out.=''; - - foreach ($THeader as $field => $head) - { - if (isset($TTotal[$field])) - { - $moreattrib = 'style="width:'.$head['width'].';text-align:'.$head['text-align'].'"'; - $out.=''; - } - } - - $out.=''; - } - } - - $out .= '
--
'.$TParam['list']['messageNothing'].'
'.$value_aff.'
'.price($TTotal[$field]).'
'; - $out .= '
'; - - return $out; - } - - /** - * @param string $db Db - * @param string $TField TField - * @param string $TParam TParam - */ - public function renderArray(&$db, $TField, $TParam=array()) - { - $this->typeRender = 'array'; - - $TField=array(); - - $this->init($TParam); - $THeader = $this->initHeader($TParam); - - $this->parse_array($THeader, $TField, $TParam); - list($TTotal, $TTotalGroup)=$this->get_total($TField, $TParam); - - $this->renderList($THeader, $TField, $TTotal, $TTotalGroup, $TParam); - } - - - /** - * @param string $THeader THeader - * @param string $TField TField - * @param string $TParam TParam - * @return bool - */ - private function parse_array(&$THeader, &$TField, &$TParam) - { - $this->totalRow = count($TField); - - $this->THideFlip = array_flip($TParam['hide']); - $this->TTotalTmp=array(); - - if (empty($TField)) return false; - - foreach($TField as $row) - { - $this->set_line($THeader, $TField, $TParam, $row); - } - } - - - private function initHeader(&$TParam) - { - global $user,$conf; - - $THeader = array(); - - $TField=$TFieldVisibility=array(); - foreach ($TParam['title'] as $field => $value) - { - $TField[$field]=true; - } - - $contextpage=md5($_SERVER['PHP_SELF']); - if(!empty($TParam['allow-fields-select'])) - { - $selectedfields = GETPOST('Listview'.$this->id.'_selectedfields'); - - if(!empty($selectedfields)) - { - include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; - $tabparam['MAIN_SELECTEDFIELDS_'.$contextpage] = $selectedfields; - $result=dol_set_user_param($this->db, $conf, $user, $tabparam); - } - - $tmpvar='MAIN_SELECTEDFIELDS_'.$contextpage; - if (! empty($user->conf->{$tmpvar})) - { - $tmparray = explode(',', $user->conf->{$tmpvar}); - $TParam['hide'] = array(); - foreach($TField as $field => $dummy) - { - $label = $TParam['title'][$field]; - if(!in_array($field, $tmparray)) - { - $TParam['hide'][] = $field; - $visible = 0; - } - else - { - // Overrive search from extrafields - // for the type as 'checkbox', 'chkbxlst', 'sellist' we should use code instead of id (example: I declare a 'chkbxlst' to have a link with dictionnairy, I have to extend it with the 'code' instead 'rowid') - if (isset($this->extralabels[$field])) $TParam['search'][$field] = $this->extrafields->showInputField($field, $this->search_array_options['search_options_'.$field], '', '', 'search_'); - $visible = 1; - } - - $TFieldVisibility[$field] = array( - 'label'=>$label - ,'checked'=>$visible - ); - } - } - else - { - foreach($TField as $field=>$dummy) - { - $label = isset($TParam['title'][$field]) ? $TParam['title'][$field] : $field; - $visible = (!in_array($field, $TParam['hide'])) ? 1 : 0; - $TFieldVisibility[$field]=array( - 'label'=>$label, - 'checked'=>$visible - ); - } - } - - $selectedfields = $this->form->multiSelectArrayWithCheckbox('Listview'.$this->id.'_selectedfields', $TFieldVisibility, $contextpage); // This also change content of $arrayfields_0 - } - - foreach ($TParam['title'] as $field => $label) - { - $visible = (!in_array($field, $TParam['hide'])) ? 1 : 0; - if($visible) - { - $THeader[$field] = array( - 'label'=>$label, - 'order'=>(in_array($field, $TParam['orderby']['noOrder']) ? 0 : 1), - 'width'=>(!empty($TParam['size']['width'][$field]) ? $TParam['size']['width'][$field] : 'auto'), - 'text-align'=>(!empty($TParam['position']['text-align'][$field]) ? $TParam['position']['text-align'][$field] : 'auto'), - 'rank'=>(!empty($TParam['position']['rank'][$field]) ? $TParam['position']['rank'][$field] : 0), - 'more'=>'' - ); - } - } - - uasort($THeader,array('Listview','sortHeaderRank')); - - $THeader['selectedfields']['label']=$selectedfields; - - return $THeader; - } - - public function sortHeaderRank(&$a, &$b) { - if($a['rank']>$b['rank']) return 1; - else if($a['rank']<$b['rank']) return -1; - else return 0; - - } - - /** - * @param string $TParam TParam - * @param string $line_number aaa - * @return bool - */ - private function in_view(&$TParam, $line_number) - { - global $conf; - - if(!empty($_REQUEST['get-all-for-export'])) return true; - - $page_number = !empty($TParam['limit']['page']) ? $TParam['limit']['page'] : 1; - $line_per_page = !empty($TParam['limit']['nbLine']) ? $TParam['limit']['nbLine'] : $conf->liste_limit; - - $start = ($page_number-1) * $line_per_page; - $end = ($page_number* $line_per_page) -1; - - if($line_number>=$start && $line_number<=$end) return true; - else return false; - } - - /** - * Apply function to result and set fields array - * - * @param string $THeader array of headers - * @param string $TField array of fields - * @param string $TParam array of parameters - * @param string $currentLine object containing current sql result - */ - private function set_line(&$THeader, &$TField, &$TParam, $currentLine) - { - global $conf; - - $line_number = count($TField); - - if($this->in_view($TParam,$line_number)) - { - $this->totalRowToShow++; - $row=array(); - $trans = array(); - foreach($currentLine as $kF=>$vF)$trans['@'.$kF.'@'] = addslashes($vF); - - foreach($THeader as $field=>$dummy) - { - $value = isset($currentLine->{$field}) ? $currentLine->{$field}: ''; - - if(is_object($value)) - { - if(get_class($value)=='stdClass') {$value=print_r($value, true);} - else $value=(string) $value; - } - - $trans['@'.$field.'@'] = addslashes($value); - - if(!empty($TParam['math'][$field])) - { - $float_value = (double) strip_tags($value); - $this->TTotalTmp[$field][] = $float_value; - } - - if(!in_array($field,$TParam['hide'])) - { - $row[$field]=$value; - - if(isset($TParam['eval'][$field]) && in_array($field,array_keys($row))) - { - $strToEval = 'return '.strtr( $TParam['eval'][$field], array_merge( $trans, array('@val@'=>addslashes( $row[$field] )) )).';'; - $row[$field] = eval($strToEval); - - } - - if(isset($TParam['type'][$field]) && !isset($TParam['eval'][$field])) - { - if($TParam['type'][$field]=='date' || $TParam['type'][$field]=='datetime' ) - { - - if($row[$field] != '0000-00-00 00:00:00' && $row[$field] != '1000-01-01 00:00:00' && $row[$field] != '0000-00-00' && !empty($row[$field])) - { - if($TParam['type'][$field]=='datetime')$row[$field] = dol_print_date(strtotime($row[$field]),'dayhour'); - else $row[$field] = dol_print_date(strtotime($row[$field]),'day'); - } - else - { - $row[$field] = ''; - } - } - - if($TParam['type'][$field]=='hour') { $row[$field] = date('H:i', strtotime($row[$field])); } - if($TParam['type'][$field]=='money') { $row[$field] = '
'.price($row[$field],0,'',1,-1,2).'
'; } - if($TParam['type'][$field]=='number') { $row[$field] = '
'.price($row[$field]).'
'; } - if($TParam['type'][$field]=='integer') { $row[$field] = '
'.((int) $row[$field]).'
'; } - } - - if(isset($TParam['link'][$field])) - { - if(empty($row[$field]) && $row[$field]!==0 && $row[$field]!=='0')$row[$field]='(vide)'; - $row[$field]= strtr( $TParam['link'][$field], array_merge( $trans, array('@val@'=>$row[$field]))) ; - } - - if(isset($TParam['translate'][$field])) - { - if(isset($TParam['translate'][$field][''])) unset($TParam['translate'][$field]['']); - - $row[$field] = strtr( $row[$field], $TParam['translate'][$field]); - } - } - } - } - else - { - $row = array(); - - foreach($currentLine as $field=>&$value) - { - if(!isset($this->THideFlip[$field])) - { - if(isset($TParam['math'][$field]) && !empty($TParam['math'][$field])) - { - $float_value = (double) strip_tags($value); - $this->TTotalTmp[$field][] = $float_value; - } - - $row[$field] = $value; - } - } - } - - if(!empty($TParam['math'][$field])) - { - foreach($row as $field=>$value) - { - if(!empty($TParam['math'][$field]) && is_array($TParam['math'][$field])) - { - $toField = $TParam['math'][$field][1]; - $float_value = (double) strip_tags($row[$toField]); - $this->TTotalTmp['@groupsum'][$toField][ $row[$field] ] += $float_value; - } - } - } - - $TField[] = $row; - } - - /** - * @param string $sql sql - * @param string $TParam TParam - * @return string - */ - private function limitSQL($sql, &$TParam) - { - if(!empty($TParam['limit']['global']) && strpos($sql,'LIMIT ')===false ) - { - $sql.=' LIMIT '.(int) $TParam['limit']['global']; - } - else if(!empty($TParam['limit'])) $sql.= $this->db->plimit($TParam['limit']['nbLine']+1, $TParam['limit']['page'] * $TParam['limit']['nbLine']); - - - return $sql; - } - - /** - * @param string $THeader THeader - * @param string $TField TField - * @param string $TParam TParam - * @param string $sql sql - */ - private function parse_sql(&$THeader, &$TField, &$TParam, $sql) - { - $this->sql = $this->limitSQL($sql, $TParam); - - $this->TTotalTmp=array(); - $this->THideFlip = array_flip($TParam['hide']); - - $res = $this->db->query($this->sql); - if($res!==false) - { - dol_syslog(get_class($this)."::parse_sql id=".$this->id." sql=".$this->sql, LOG_DEBUG); - - if(empty($this->totalRow))$this->totalRow = $this->db->num_rows($res); - - while($currentLine = $this->db->fetch_object($res)) - { - $this->set_line($THeader, $TField, $TParam, $currentLine); - } - } - else - { - dol_syslog(get_class($this)."::parse_sql id=".$this->id." sql=".$this->sql, LOG_ERR); - } - } - - static function getCachedOjbect($class_name, $fk_object) { - global $db, $TCacheListObject; - - if(!class_exists($class_name)) return false; - - if(empty($TCacheListObject)) $TCacheListObject = array(); - if(empty($TCacheListObject[$class_name])) $TCacheListObject[$class_name] =array(); - - if(empty($TCacheListObject[$class_name][$fk_object])) { - $TCacheListObject[$class_name][$fk_object]= new $class_name($db); - if( $TCacheListObject[$class_name][$fk_object]->fetch($fk_object)<0) { - return false; - } - } - - return $TCacheListObject[$class_name][$fk_object]; - } - -} diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index 1daff124764..db462411fe7 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -614,7 +614,7 @@ if ($id > 0 || $ref) } // Stock alert threshold - print ''.$form->editfieldkey("StockLimit",'seuil_stock_alerte',$object->seuil_stock_alerte,$object,$user->rights->produit->creer).''; + print ''.$form->editfieldkey($form->textwithpicto($langs->trans("StockLimit"), $langs->trans("StockLimitDesc"), 1),'seuil_stock_alerte',$object->seuil_stock_alerte,$object,$user->rights->produit->creer).''; print $form->editfieldval("StockLimit",'seuil_stock_alerte',$object->seuil_stock_alerte,$object,$user->rights->produit->creer,'string'); print ''; diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index 67398674a2f..af55063c66a 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -971,6 +971,7 @@ class Project extends CommonObject $label .= ($label?'
':'').'' . $langs->trans('DateEnd') . ': ' . dol_print_date($this->datee, 'day'); // The space must be after the : to not being explode when showing the title in img_picto if ($moreinpopup) $label.='
'.$moreinpopup; + $url=''; if ($option != 'nolink') { if (preg_match('/\.php$/',$option)) { @@ -1000,7 +1001,7 @@ class Project extends CommonObject } $linkclose.=' title="'.dol_escape_htmltag($label, 1).'"'; $linkclose.=' class="classfortooltip"'; - + if (! is_object($hookmanager)) { include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; $hookmanager=new HookManager($this->db); @@ -1008,8 +1009,8 @@ class Project extends CommonObject $hookmanager->initHooks(array('projectdao')); $parameters=array('id'=>$this->id); // Note that $action and $object may have been modified by some hooks - $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action); - if ($reshook > 0) + $reshook=$hookmanager->executeHooks('getnomurltooltip',$parameters,$this,$action); + if ($reshook > 0) $linkclose = $hookmanager->resPrint; } diff --git a/htdocs/user/logout.php b/htdocs/user/logout.php index 37ff691fdcc..4421c6d6298 100644 --- a/htdocs/user/logout.php +++ b/htdocs/user/logout.php @@ -50,13 +50,6 @@ if ($result < 0) { $error++; } // Define url to go after disconnect $urlfrom=empty($_SESSION["urlfrom"])?'':$_SESSION["urlfrom"]; -// Destroy some cookies -// TODO external module -if (! empty($conf->phenix->enabled) && ! empty($conf->phenix->cookie)) -{ - setcookie($conf->phenix->cookie, '', 1, "/"); -} - // Define url to go $url=DOL_URL_ROOT."/index.php"; // By default go to login page if ($urlfrom) $url=DOL_URL_ROOT.$urlfrom; diff --git a/htdocs/websites/class/websitepage.class.php b/htdocs/websites/class/websitepage.class.php index 73158fac7be..7d5e59830e1 100644 --- a/htdocs/websites/class/websitepage.class.php +++ b/htdocs/websites/class/websitepage.class.php @@ -500,9 +500,10 @@ class WebsitePage extends CommonObject * @param string $newref New ref/alias of page * @param string $newlang New language * @param int $istranslation 1=New page is a translation of the cloned page. + * @param int $newwebsite 0=Same web site, 1=New web site * @return int New id of clone */ - public function createFromClone($fromid, $newref, $newlang='', $istranslation=0) + public function createFromClone($fromid, $newref, $newlang='', $istranslation=0, $newwebsite=0) { global $user, $langs; @@ -525,6 +526,7 @@ class WebsitePage extends CommonObject if (! empty($newlang)) $object->lang=$newlang; if ($istranslation) $object->fk_page = $fromid; else $object->fk_page = 0; + if (! empty($newwebsite)) $object->fk_website=$newwebsite; // Create clone $result = $object->create($user); diff --git a/htdocs/websites/index.php b/htdocs/websites/index.php index d692295d2a5..0f1e813e3ed 100644 --- a/htdocs/websites/index.php +++ b/htdocs/websites/index.php @@ -66,12 +66,12 @@ function llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, } - require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formwebsite.class.php'; require_once DOL_DOCUMENT_ROOT.'/websites/class/website.class.php'; require_once DOL_DOCUMENT_ROOT.'/websites/class/websitepage.class.php'; @@ -138,6 +138,8 @@ global $dolibarr_main_data_root; $pathofwebsite=$dolibarr_main_data_root.'/websites/'.$website; $filehtmlheader=$pathofwebsite.'/htmlheader.html'; $filecss=$pathofwebsite.'/styles.css.php'; +$filerobot=$pathofwebsite.'/robots.txt'; +$filehtaccess=$pathofwebsite.'/.htaccess'; $filetpl=$pathofwebsite.'/page'.$pageid.'.tpl.php'; $fileindex=$pathofwebsite.'/index.php'; @@ -174,10 +176,11 @@ if ($action == 'add') $error++; $action='create'; } - else if (! preg_match('/^[a-z0-9]+$/i', $objectpage->pageurl)) + else if (! preg_match('/^[a-z0-9\-\_]+$/i', $objectpage->pageurl)) { - $error++; setEventMessages($langs->transnoentities("ErrorFieldCanNotContainSpecialCharacters", $langs->transnoentities('WEBSITE_PAGENAME')), null, 'errors'); + $error++; + $action='create'; } if (empty($objectpage->title)) { @@ -310,7 +313,6 @@ if ($action == 'updatecss') $csscontent.= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp);'."\n"; $csscontent.= "// END PHP ?>"."\n"; - dol_syslog("Save file css into ".$filecss); dol_mkdir($pathofwebsite); @@ -325,6 +327,70 @@ if ($action == 'updatecss') } + // Css file + $robotcontent =''; + + /*$robotcontent.= "\n";*/ + + $robotcontent.= GETPOST('WEBSITE_ROBOT'); + + /*$robotcontent.= "\n".'"."\n";*/ + + dol_syslog("Save file robot into ".$filerobot); + + dol_mkdir($pathofwebsite); + $result = file_put_contents($filerobot, $robotcontent); + if (! empty($conf->global->MAIN_UMASK)) + @chmod($filerobot, octdec($conf->global->MAIN_UMASK)); + + if (! $result) + { + $error++; + setEventMessages('Failed to write file '.$filerobot, null, 'errors'); + } + + + // Css file + $htaccesscontent =''; + + /*$robotcontent.= "\n";*/ + + $htaccesscontent.= GETPOST('WEBSITE_HTACCESS'); + + /*$robotcontent.= "\n".'"."\n";*/ + + dol_syslog("Save file htaccess into ".$filehtaccess); + + dol_mkdir($pathofwebsite); + $result = file_put_contents($filehtaccess, $htaccesscontent); + if (! empty($conf->global->MAIN_UMASK)) + @chmod($filehtaccess, octdec($conf->global->MAIN_UMASK)); + + if (! $result) + { + $error++; + setEventMessages('Failed to write file '.$filehtaccess, null, 'errors'); + } + + // Message if no error if (! $error) { setEventMessages($langs->trans("Saved"), null, 'mesgs'); @@ -549,7 +615,7 @@ if (($action == 'updatesource' || $action == 'updatecontent' || $action == 'conf if (! $error) { $objectpage = new WebsitePage($db); - $result = $objectpage->createFromClone($pageid, GETPOST('pageurl','aZ09'), (GETPOST('newlang','aZ09')?GETPOST('newlang','aZ09'):''), $istranslation); + $result = $objectpage->createFromClone($pageid, GETPOST('pageurl','aZ09'), (GETPOST('newlang','aZ09')?GETPOST('newlang','aZ09'):''), $istranslation, GETPOST('newwebsite','int')); if ($result < 0) { $error++; @@ -745,6 +811,7 @@ if (($action == 'updatesource' || $action == 'updatecontent' || $action == 'conf $form = new Form($db); $formadmin = new FormAdmin($db); +$formwebsite = new FormWebsite($db); $help_url=''; @@ -958,7 +1025,9 @@ if (count($object->records) > 0) $formquestion = array( array('type' => 'text', 'name' => 'pageurl', 'label'=> $langs->trans("WEBSITE_PAGENAME") ,'value'=> 'copy_of_'.$objectpage->pageurl), array('type' => 'checkbox', 'name' => 'is_a_translation', 'label' => $langs->trans("PageIsANewTranslation"), 'value' => 0), - array('type' => 'other','name' => 'newlang','label' => $langs->trans("Language"), 'value' => $formadmin->select_language(GETPOST('newlang', 'az09')?GETPOST('newlang', 'az09'):$langs->defaultlang, 'newlang', 0, null, '', 0, 0, 'minwidth200'))); + array('type' => 'other','name' => 'newlang','label' => $langs->trans("Language"), 'value' => $formadmin->select_language(GETPOST('newlang', 'az09')?GETPOST('newlang', 'az09'):$langs->defaultlang, 'newlang', 0, null, '', 0, 0, 'minwidth200')), + array('type' => 'other','name' => 'newwebsite','label' => $langs->trans("Website"), 'value' => $formwebsite->selectWebsite($object->id, 'newwebsite', 0)) + ); $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?pageid=' . $pageid, $langs->trans('ClonePage'), '', 'confirm_createpagefromclone', $formquestion, 0, 1, 250); @@ -1094,30 +1163,49 @@ if ($action == 'editcss') $csscontent = @file_get_contents($filecss); // Clean the php css file to remove php code and get only css part $csscontent = preg_replace('/<\?php \/\/ BEGIN PHP.*END PHP \?>\n*/ims', '', $csscontent); - $csscontent.= GETPOST('WEBSITE_CSS_INLINE'); - if (! trim($csscontent)) $csscontent='/* CSS content (all pages) */'."\n".'body.bodywebsite { margin: 0; }'; - $htmlheader = @file_get_contents($filehtmlheader); // Clean the php htmlheader file to remove php code and get only html part $htmlheader = preg_replace('/<\?php \/\/ BEGIN PHP.*END PHP \?>\n*/ims', '', $htmlheader); - if (! trim($htmlheader)) $htmlheader=''."\n".''."\n".''; else $htmlheader=''."\n".$htmlheader."\n".''; + $robotcontent = @file_get_contents($filerobot); + // Clean the php htmlheader file to remove php code and get only html part + $robotcontent = preg_replace('/<\?php \/\/ BEGIN PHP.*END PHP \?>\n*/ims', '', $robotcontent); + if (! trim($robotcontent)) + { + $robotcontent.="# Robot file. Generated with ".DOL_APPLICATION_TITLE."\n"; + $robotcontent.="User-agent: *\n"; + $robotcontent.="Allow: /public/\n"; + $robotcontent.="Disallow: /administrator/\n"; + } + + $htaccesscontent = @file_get_contents($filehtaccess); + // Clean the php htmlheader file to remove php code and get only html part + $htaccesscontent = preg_replace('/<\?php \/\/ BEGIN PHP.*END PHP \?>\n*/ims', '', $htaccesscontent); + if (! trim($htaccesscontent)) + { + $htaccesscontent.="# Order allow,deny\n"; + $htaccesscontent.="# Deny from all\n"; + } + //else $htaccesscontent=''."\n".$htaccesscontent."\n".'';*/ + dol_fiche_head(); print ''."\n"; print ''; + // Website print ''; + // CSS file print ''; + // Common HTML header print ''; + + // Robot file + print ''; + + // .htaccess + print ''; print '
'; print $langs->trans('WebSite'); print ''; print $website; print '
'; print $langs->trans('WEBSITE_CSS_INLINE'); print ''; @@ -1125,11 +1213,9 @@ if ($action == 'editcss') $doleditor=new DolEditor('WEBSITE_CSS_INLINE', $csscontent, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); print $doleditor->Create(1, '', true, 'CSS', 'css'); - /*print '';*/ print '
'; print $langs->trans('WEBSITE_HTML_HEADER'); print ''; @@ -1137,9 +1223,26 @@ if ($action == 'editcss') $doleditor=new DolEditor('WEBSITE_HTML_HEADER', $htmlheader, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); print $doleditor->Create(1, '', true, 'HTML Header', 'html'); - /*print '';*/ + print '
'; + print $langs->trans('WEBSITE_ROBOT'); + print ''; + + $doleditor=new DolEditor('WEBSITE_ROBOT', $robotcontent, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); + print $doleditor->Create(1, '', true, 'Robot file', 'txt'); + + print '
'; + print $langs->trans('WEBSITE_HTACCESS'); + print ''; + + $doleditor=new DolEditor('WEBSITE_HTACCESS', $htaccesscontent, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); + print $doleditor->Create(1, '', true, $langs->trans("File").' .htaccess', 'txt'); + print '
'; @@ -1238,7 +1341,7 @@ if ($action == 'editsource') * Editing global variables not related to a specific theme */ - $csscontent = @file_get_contents($filecss); + //$csscontent = @file_get_contents($filecss); $contentforedit = ''; /*$contentforedit.='