diff --git a/htdocs/accountancy/admin/productaccount.php b/htdocs/accountancy/admin/productaccount.php index 3e3fb104e70..d88800016a8 100644 --- a/htdocs/accountancy/admin/productaccount.php +++ b/htdocs/accountancy/admin/productaccount.php @@ -57,6 +57,7 @@ $changeaccount_sell = GETPOST('changeaccount_sell', 'array'); $search_ref = GETPOST('search_ref', 'alpha'); $search_label = GETPOST('search_label', 'alpha'); $search_desc = GETPOST('search_desc', 'alpha'); +$search_vat = GETPOST('search_vat', 'alpha'); $search_current_account = GETPOST('search_current_account', 'alpha'); $search_current_account_valid = GETPOST('search_current_account_valid', 'alpha'); if ($search_current_account_valid == '') $search_current_account_valid = 'withoutvalidaccount'; @@ -102,6 +103,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x' $search_ref = ''; $search_label = ''; $search_desc = ''; + $search_vat = ''; $search_onsell = ''; $search_onpurchase = ''; $search_current_account = ''; @@ -136,7 +138,7 @@ if ($action == 'update') { if (!empty($chk_prod)) { $accounting = new AccountingAccount($db); - //$msg .= '
' . count($chk_prod) . ' ' . $langs->trans("SelectedLines") . '
'; + //$msg .= '
' . count($chk_prod) . ' ' . $langs->trans("SelectedLines") . '
'; $arrayofdifferentselectedvalues = array(); $cpt = 0; $ok = 0; $ko = 0; @@ -243,7 +245,7 @@ $pcgverid = $conf->global->CHARTOFACCOUNTS; $pcgvercode = dol_getIdFromCode($db, $pcgverid, 'accounting_system', 'rowid', 'pcg_version'); if (empty($pcgvercode)) $pcgvercode = $pcgverid; -$sql = "SELECT p.rowid, p.ref, p.label, p.description, p.tosell, p.tobuy,"; +$sql = "SELECT p.rowid, p.ref, p.label, p.description, p.tosell, p.tobuy, p.tva_tx,"; $sql .= " p.accountancy_code_sell, p.accountancy_code_sell_intra, p.accountancy_code_sell_export,"; $sql .= " p.accountancy_code_buy, p.accountancy_code_buy_intra, p.accountancy_code_buy_export,"; $sql .= " p.tms, p.fk_product_type as product_type,"; @@ -311,6 +313,9 @@ if (strlen(trim($search_label))) { if (strlen(trim($search_desc))) { $sql .= natural_search("p.description", $search_desc); } +if (strlen(trim($search_vat))) { + $sql .= natural_search("p.tva_tx", price2num($search_vat), 1); +} if ($search_onsell != '' && $search_onsell != '-1') $sql .= natural_search('p.tosell', $search_onsell, 1); if ($search_onpurchase != '' && $search_onpurchase != '-1') $sql .= natural_search('p.tobuy', $search_onpurchase, 1); @@ -343,6 +348,7 @@ if ($result) if ($search_ref > 0) $param .= "&search_desc=".urlencode($search_ref); if ($search_label > 0) $param .= "&search_desc=".urlencode($search_label); if ($search_desc > 0) $param .= "&search_desc=".urlencode($search_desc); + if ($search_vat > 0) $param .= '&search_vat='.urlencode($search_vat); if ($search_current_account > 0) $param .= "&search_current_account=".urlencode($search_current_account); if ($search_current_account_valid && $search_current_account_valid != '-1') $param .= "&search_current_account_valid=".urlencode($search_current_account_valid); if ($accounting_product_mode) $param .= '&accounting_product_mode='.urlencode($accounting_product_mode); @@ -411,6 +417,8 @@ if ($result) print ''; print ''; print ''; + print ''; + if (!empty($conf->global->ACCOUNTANCY_SHOW_PROD_DESC)) print ''; // On sell if ($accounting_product_mode == 'ACCOUNTANCY_SELL' || $accounting_product_mode == 'ACCOUNTANCY_SELL_INTRA' || $accounting_product_mode == 'ACCOUNTANCY_SELL_EXPORT') { @@ -437,7 +445,8 @@ if ($result) print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder); if (!empty($conf->global->ACCOUNTANCY_SHOW_PROD_DESC)) print_liste_field_titre("Description", $_SERVER["PHP_SELF"], "p.description", "", $param, '', $sortfield, $sortorder); - // On sell / On purchase + print_liste_field_titre("VATRate", $_SERVER["PHP_SELF"], "p.tva_tx", "", $param, '', $sortfield, $sortorder, 'right '); + // On sell / On purchase if ($accounting_product_mode == 'ACCOUNTANCY_SELL') { print_liste_field_titre("OnSell", $_SERVER["PHP_SELF"], "p.tosell", "", $param, '', $sortfield, $sortorder, 'center '); $fieldtosortaccount = "p.accountancy_code_sell"; @@ -553,11 +562,16 @@ if ($result) { // TODO ADJUST DESCRIPTION SIZE // print '' . $obj->description . ''; - // TODO: we shoul set a user defined value to adjust user square / wide screen size - $trunclengh = empty($conf->global->ACCOUNTING_LENGTH_DESCRIPTION) ? 32 : $conf->global->ACCOUNTING_LENGTH_DESCRIPTION; - print ''.nl2br(dol_trunc($obj->description, $trunclengh)).''; + // TODO: we should set a user defined value to adjust user square / wide screen size + $trunclength = empty($conf->global->ACCOUNTING_LENGTH_DESCRIPTION) ? 32 : $conf->global->ACCOUNTING_LENGTH_DESCRIPTION; + print ''.nl2br(dol_trunc($obj->description, $trunclength)).''; } + // VAT + print ''; + print vatrate($obj->tva_tx); + print ''; + if ($accounting_product_mode == 'ACCOUNTANCY_SELL' || $accounting_product_mode == 'ACCOUNTANCY_SELL_INTRA' || $accounting_product_mode == 'ACCOUNTANCY_SELL_EXPORT') print ''.$product_static->getLibStatut(3, 0).''; @@ -602,7 +616,7 @@ if ($result) // Accounting account buy intra (In EEC) print ''; //$defaultvalue=GETPOST('codeventil_' . $product_static->id,'alpha'); This is id and we need a code - if (empty($defaultvalue)) $defaultvalue = $compta_prodbuy_intra; + if (empty($defaultvalue)) $defaultvalue = $compta_prodbuy; $codesell = length_accountg($obj->accountancy_code_buy_intra); //var_dump($defaultvalue.' - '.$codesell.' - '.$compta_prodsell); if (!empty($obj->aaid)) $defaultvalue = ''; // Do not suggest default new value is code is already valid @@ -612,7 +626,7 @@ if ($result) // Accounting account buy export (Out of EEC) print ''; //$defaultvalue=GETPOST('codeventil_' . $product_static->id,'alpha'); This is id and we need a code - if (empty($defaultvalue)) $defaultvalue = $compta_prodbuy_export; + if (empty($defaultvalue)) $defaultvalue = $compta_prodbuy; $codesell = length_accountg($obj->accountancy_code_buy_export); //var_dump($defaultvalue.' - '.$codesell.' - '.$compta_prodsell); if (!empty($obj->aaid)) $defaultvalue = ''; // Do not suggest default new value is code is already valid diff --git a/htdocs/admin/emailcollector_card.php b/htdocs/admin/emailcollector_card.php index 9d5dcbc32e3..1420cc0263e 100644 --- a/htdocs/admin/emailcollector_card.php +++ b/htdocs/admin/emailcollector_card.php @@ -496,6 +496,8 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea 'X3'=>'---', 'withtrackingid'=>array('label'=>'WithDolTrackingID', 'data-noparam'=>1), 'withouttrackingid'=>array('label'=>'WithoutDolTrackingID', 'data-noparam'=>1), + 'withtrackingidinmsgid'=>array('label'=>'WithDolTrackingIDInMsgId', 'data-noparam'=>1), + 'withouttrackingidinmsgid'=>array('label'=>'WithoutDolTrackingIDInMsgId', 'data-noparam'=>1), 'X4'=>'---', 'isnotanswer'=>array('label'=>'IsNotAnAnswer', 'data-noparam'=>1), 'isanswer'=>array('label'=>'IsAnAnswer', 'data-noparam'=>1) @@ -538,7 +540,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print ''; print ''.$rulefilter['rulevalue'].''; print ''; - print ' '.img_delete().''; + print ' '.img_delete().''; print ''; print ''; } @@ -630,7 +632,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Delete print ''; print ''.img_edit().''; - print ' '.img_delete().''; + print ' '.img_delete().''; print ''; print ''; $i++; @@ -677,7 +679,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea print '
'.$langs->trans("CollectNow").'
'; } - print '
'.$langs->trans('Delete').'
'; + print '
'.$langs->trans('Delete').'
'; } print ''."\n"; } diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php index feca9bf582e..8971f5a69d4 100644 --- a/htdocs/admin/mails.php +++ b/htdocs/admin/mails.php @@ -773,11 +773,17 @@ if ($action == 'edit') if ($conf->global->MAIN_MAIL_SENDMODE == 'mail') { - // MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS is list of IPs where email is sent from. Example: '1.2.3.4, [aaaa:bbbb:cccc:dddd]'. - if (!empty($conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS)) + if (!empty($conf->global->MAIN_EXTERNAL_MAIL_SPF_STRING_TO_ADD)) { - // List of IP show as record to add in SPF if we use the mail method - $text .= ($text ? '

' : '').$langs->trans("WarningPHPMailSPF", $conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS); + // List of string to add in SPF if the setup use the mail method + $text .= ($text ? '

' : '').$langs->trans("WarningPHPMailSPF", $conf->global->MAIN_EXTERNAL_MAIL_SPF_STRING_TO_ADD); + } else { + // MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS is list of IPs where email is sent from. Example: '1.2.3.4, [aaaa:bbbb:cccc:dddd]'. + if (!empty($conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS)) + { + // List of IP show as record to add in SPF if we use the mail method + $text .= ($text ? '

' : '').$langs->trans("WarningPHPMailSPF", $conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS); + } } } else { if (!empty($conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS)) @@ -785,7 +791,7 @@ if ($action == 'edit') // List of IP show as record to add as allowed IP if we use the smtp method $text .= ($text ? '

' : '').$langs->trans("WarningPHPMail2", $conf->global->MAIN_EXTERNAL_SMTP_CLIENT_IP_ADDRESS); } - if (!empty($conf->global->MAIN_EXTERNAL_SMTP_SPF_STRING_TO_ADD)) + if (!empty($conf->global->MAIN_EXTERNAL_SMTP_SPF_STRING_TO_ADD)) // Should be required only if you have set to use your own SMTP and wat to warn users to update their domain name to match your SMTP server. { // List of string to add in SPF if we use the smtp method $text .= ($text ? '

' : '').$langs->trans("WarningPHPMailSPF", $conf->global->MAIN_EXTERNAL_SMTP_SPF_STRING_TO_ADD); diff --git a/htdocs/admin/pdf.php b/htdocs/admin/pdf.php index 95487fc0bc3..363edca6c80 100644 --- a/htdocs/admin/pdf.php +++ b/htdocs/admin/pdf.php @@ -89,18 +89,6 @@ if ($action == 'update') exit; } -if ($action == 'activate_pdfsecurity') -{ - dolibarr_set_const($db, "PDF_SECURITY_ENCRYPTION", "1", 'chaine', 0, '', $conf->entity); - header("Location: ".$_SERVER["PHP_SELF"]."?mainmenu=home&leftmenu=setup"); - exit; -} elseif ($action == 'disable_pdfsecurity') -{ - dolibarr_del_const($db, "PDF_SECURITY_ENCRYPTION", $conf->entity); - header("Location: ".$_SERVER["PHP_SELF"]."?mainmenu=home&leftmenu=setup"); - exit; -} - /* diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index 7bb252394c3..b8d0304c5eb 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -185,6 +185,13 @@ class BlockedLog // $conf->global->BANK_ENABLE_POS_CASHCONTROL must be set to 1 by all POS modules $moduleposenabled = ($conf->cashdesk->enabled || $conf->takepos->enabled || !empty($conf->global->BANK_ENABLE_POS_CASHCONTROL)); if ($moduleposenabled) $this->trackedevents['CASHCONTROL_VALIDATE'] = 'logCASHCONTROL_VALIDATE'; + + if (!empty($conf->global->BLOCKEDLOG_ADD_ACTIONS_SUPPORTED)) { + $tmparrayofmoresupportedevents = explode(',', $conf->global->BLOCKEDLOG_ADD_ACTIONS_SUPPORTED); + foreach ($tmparrayofmoresupportedevents as $val) { + $this->trackedevents[$val] = 'log'.$val; + } + } } /** diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 1230a0e3269..1e59943a794 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2017-2020 Laurent Destailleur * Copyright (C) 2019 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -181,6 +181,8 @@ if (empty($reshook)) unset($_POST['qty']); unset($_POST['qty_frozen']); unset($_POST['disable_stock_change']); + + $object->fetchLines(); } } } diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 0fe69fa10ea..3818f459893 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -48,7 +48,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; // Load translation files required by the page -$langs->loadLangs(array("companies", "other", "commercial", "bills", "orders", "agenda")); +$langs->loadLangs(array("companies", "other", "commercial", "bills", "orders", "agenda", "mails")); $action = GETPOST('action', 'aZ09'); $cancel = GETPOST('cancel', 'alpha'); @@ -393,31 +393,36 @@ if (empty($reshook) && $action == 'add') $moreparam = ''; if ($user->id != $object->userownerid) $moreparam = "filtert=-1"; // We force to remove filter so created record is visible when going back to per user view. - //Create eminder + //Create reminders if ($addreminder == 'on'){ $actionCommReminder = new ActionCommReminder($db); - $dateremind = dol_time_plus_duree($datep, -$offsetvalue, 'i'); + $dateremind = dol_time_plus_duree($datep, -$offsetvalue, $offsetunit); $actionCommReminder->dateremind = $dateremind; $actionCommReminder->typeremind = $remindertype; - $actionCommReminder->fk_user = $user; $actionCommReminder->offsetunit = $offsetunit; $actionCommReminder->offsetvalue = $offsetvalue; $actionCommReminder->status = $actionCommReminder::STATUS_TODO; $actionCommReminder->fk_actioncomm = $object->id; if ($remindertype == 'email') $actionCommReminder->fk_email_template = $modelmail; - $res = $actionCommReminder->create($user); + // the notification must be created for every user assigned to the event + foreach ($object->userassigned as $userassigned) + { + $actionCommReminder->fk_user = $userassigned['id']; + $res = $actionCommReminder->create($user); - if ($res <= 0){ - // If error - $error++; - $langs->load("errors"); - $error = $langs->trans('ErrorReminderActionCommCreation').' '.$actionCommReminder->error; - setEventMessages($error, $actionCommReminder->errors, 'errors'); - $action = 'create'; $donotclearsession = 1; - } + if ($res <= 0){ + // If error + $db->rollback(); + $langs->load("errors"); + $error = $langs->trans('ErrorReminderActionCommCreation'); + setEventMessages($error, null, 'errors'); + $action = 'create'; $donotclearsession = 1; + break; + } + } } if ($error) { @@ -634,9 +639,51 @@ if (empty($reshook) && $action == 'update') $categories = GETPOST('categories', 'array'); $object->setCategories($categories); + $object->loadReminders(); + if (!empty($object->reminders) && $object->datep > dol_now()) + { + foreach ($object->reminders as $reminder) + { + $reminder->delete($user); + } + $object->reminders = array(); + } + + //Create reminders + if ($addreminder == 'on' && $object->datep > dol_now()){ + $actionCommReminder = new ActionCommReminder($db); + + $dateremind = dol_time_plus_duree($datep, -$offsetvalue, $offsetunit); + + $actionCommReminder->dateremind = $dateremind; + $actionCommReminder->typeremind = $remindertype; + $actionCommReminder->offsetunit = $offsetunit; + $actionCommReminder->offsetvalue = $offsetvalue; + $actionCommReminder->status = $actionCommReminder::STATUS_TODO; + $actionCommReminder->fk_actioncomm = $object->id; + if ($remindertype == 'email') $actionCommReminder->fk_email_template = $modelmail; + + // the notification must be created for every user assigned to the event + foreach ($object->userassigned as $userassigned) + { + $actionCommReminder->fk_user = $userassigned['id']; + $res = $actionCommReminder->create($user); + + if ($res <= 0){ + // If error + $langs->load("errors"); + $error = $langs->trans('ErrorReminderActionCommCreation'); + setEventMessages($error, null, 'errors'); + $action = 'create'; $donotclearsession = 1; + break; + } + } + } + unset($_SESSION['assignedtouser']); - $db->commit(); + if (!$error) $db->commit(); + else $db->rollback(); } else { setEventMessages($object->error, $object->errors, 'errors'); $db->rollback(); @@ -1236,7 +1283,7 @@ if ($action == 'create') } }); - $("#selectremindertype").click(function(){ + $("#selectremindertype").change(function(){ var selected_option = $("#selectremindertype option:selected").val(); if(selected_option == "email") { $("#select_actioncommsendmodel_mail").closest("tr").show(); @@ -1664,41 +1711,82 @@ if ($id > 0) { $filtreuserid = $user->id; if ($user->rights->agenda->allactions->read) $filtreuserid = 0; - $object->loadReminders('', $filteruserid); + $object->loadReminders('', $filteruserid, false); print '
'; - print ''; - - print ''; + + print '
'; + + print '
'.$langs->trans("Reminders").''; - if (count($object->reminders) > 0) { - if (count($object->reminders) > 0) { - $tmpuserstatic = new User($db); + $checked = 'checked'; + $keys = array_keys($object->reminders); + $firstreminderId = array_shift($keys); - foreach ($object->reminders as $actioncommreminderid => $actioncommreminder) { - print $TRemindTypes[$actioncommreminder->typeremind]; - if ($actioncommreminder->fk_user > 0) { - $tmpuserstatic->fetch($actioncommreminder->fk_user); - print ' ('.$tmpuser->getNomUrl(0, '', 0, 0, 16).')'; - } - print ' - '.$actioncommreminder->offsetvalue.' '.$TDurationTypes[$actioncommreminder->offsetunit]; - if ($actioncommreminder->status == $actioncommreminder::STATUS_TODO) { - print ' - '; - print $langs->trans("NotSent"); - print ' '; - } elseif ($actioncommreminder->status == $actioncommreminder::STATUS_DONE) { - print ' - '; - print $langs->trans("Done"); - print ' '; - } - } - } + $actionCommReminder = $object->reminders[$firstreminderId]; + + } + else + { + $checked = ''; + $actionCommReminder = new ActionCommReminder($db); + $actionCommReminder->offsetvalue = 10; + $actionCommReminder->offsetunit = 'i'; + $actionCommReminder->typeremind = 'email'; } + print '
'.$langs->trans("AddReminder").'
'; + + //Reminder + print ''; + + //Time Type + print ''; + + //Reminder Type + $TRemindTypes = array(); + if (!empty($conf->global->AGENDA_REMINDER_EMAIL)) $TRemindTypes['email'] = $langs->trans('EMail'); + if (!empty($conf->global->AGENDA_REMINDER_BROWSER)) $TRemindTypes['browser'] = $langs->trans('BrowserPush'); + print ''; + + $hide = ''; + if ($actionCommReminder->typeremind == 'browser') $hide = 'style="display:none;"'; + + //Mail Model + print ''; print '
'.$langs->trans("ReminderTime").''; + print ''; + print '
'.$langs->trans("TimeType").''; + print $form->selectTypeDuration('offsetunit', $actionCommReminder->offsetunit); + print '
'.$langs->trans("ReminderType").''; + print $form->selectarray('selectremindertype', $TRemindTypes, $actionCommReminder->typeremind); + print '
'.$langs->trans("EMailTemplates").''; + print $form->selectModelMail('actioncommsend', 'actioncomm_send', 1); print '
'; + + print "\n".''."\n"; } dol_fiche_end(); @@ -1980,7 +2068,7 @@ if ($id > 0) { $filtreuserid = $user->id; if ($user->rights->agenda->allactions->read) $filtreuserid = 0; - $object->loadReminders('', $filteruserid); + $object->loadReminders('', $filteruserid, false); print ''.$langs->trans("Reminders").''; @@ -1991,7 +2079,7 @@ if ($id > 0) print $TRemindTypes[$actioncommreminder->typeremind]; if ($actioncommreminder->fk_user > 0) { $tmpuserstatic->fetch($actioncommreminder->fk_user); - print ' ('.$tmpuser->getNomUrl(0, '', 0, 0, 16).')'; + print ' ('.$tmpuserstatic->getNomUrl(0, '', 0, 0, 16).')'; } print ' - '.$actioncommreminder->offsetvalue.' '.$TDurationTypes[$actioncommreminder->offsetunit]; if ($actioncommreminder->status == $actioncommreminder::STATUS_TODO) { @@ -2003,6 +2091,7 @@ if ($id > 0) print $langs->trans("Done"); print ' '; } + print '
'; } } diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index a5084bfac74..c6fd2183459 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -925,6 +925,18 @@ class ActionComm extends CommonObject } } + if (!$error) + { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_reminder"; + $sql .= " WHERE fk_actioncomm = ".$this->id; + + $res = $this->db->query($sql); + if (!$res) { + $this->error = $this->db->lasterror(); + $error++; + } + } + // Removed extrafields if (!$error) { $result = $this->deleteExtraFields(); @@ -1958,9 +1970,10 @@ class ActionComm extends CommonObject * * @param string $type Type of reminder 'browser' or 'email' * @param int $fk_user Id of user + * @param bool $onlypast true = get only past reminder, false = get all reminders linked to this * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK) */ - public function loadReminders($type = '', $fk_user = 0) + public function loadReminders($type = '', $fk_user = 0, $onlypast = true) { global $conf, $langs, $user; @@ -1971,7 +1984,10 @@ class ActionComm extends CommonObject //Select all action comm reminders for event $sql = "SELECT rowid as id, typeremind, dateremind, status, offsetvalue, offsetunit, fk_user"; $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm_reminder"; - $sql .= " WHERE fk_actioncomm = ".$this->id." AND dateremind <= '".$this->db->idate(dol_now())."'"; + $sql .= " WHERE fk_actioncomm = ".$this->id; + if ($onlypast) { + $sql .= " AND dateremind <= '".$this->db->idate(dol_now())."'"; + } if ($type) { $sql .= " AND typeremind ='".$this->db->escape($type)."'"; } diff --git a/htdocs/compta/bank/line.php b/htdocs/compta/bank/line.php index 7502d4644f5..4e2998792d8 100644 --- a/htdocs/compta/bank/line.php +++ b/htdocs/compta/bank/line.php @@ -32,6 +32,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; // Load translation files required by the page $langs->loadLangs(array('banks', 'categories', 'compta', 'bills', 'other')); @@ -246,16 +247,7 @@ foreach ($cats as $cat) { $arrayselected[] = $cat->id; } -$tabs = array( - array( - DOL_URL_ROOT.'/compta/bank/line.php?rowid='.$rowid, - $langs->trans('BankTransaction') - ), - array( - DOL_URL_ROOT.'/compta/bank/info.php?rowid='.$rowid, - $langs->trans('Info') - ) -); +$head = bankline_prepare_head($rowid); $sql = "SELECT b.rowid,b.dateo as do,b.datev as dv, b.amount, b.label, b.rappro,"; @@ -296,7 +288,7 @@ if ($result) print ''; print ''; - dol_fiche_head($tabs, 0, $langs->trans('LineRecord'), 0, 'accountline', 0); + dol_fiche_head($head, 'bankline', $langs->trans('LineRecord'), 0, 'accountline', 0); $linkback = ''.$langs->trans("BackToList").''; diff --git a/htdocs/compta/facture/class/facture-rec.class.php b/htdocs/compta/facture/class/facture-rec.class.php index 67dd4e304ea..c288251f56a 100644 --- a/htdocs/compta/facture/class/facture-rec.class.php +++ b/htdocs/compta/facture/class/facture-rec.class.php @@ -155,7 +155,7 @@ class FactureRec extends CommonInvoice 'note_private' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>105), 'note_public' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>110), 'modelpdf' =>array('type'=>'varchar(255)', 'label'=>'Modelpdf', 'enabled'=>1, 'visible'=>-1, 'position'=>115), - 'last_gen' =>array('type'=>'varchar(7)', 'label'=>'Last gen', 'enabled'=>1, 'visible'=>-1, 'position'=>120), + 'date_last_gen' =>array('type'=>'varchar(7)', 'label'=>'Last gen', 'enabled'=>1, 'visible'=>-1, 'position'=>120), 'unit_frequency' =>array('type'=>'varchar(2)', 'label'=>'Unit frequency', 'enabled'=>1, 'visible'=>-1, 'position'=>125), 'date_when' =>array('type'=>'datetime', 'label'=>'Date when', 'enabled'=>1, 'visible'=>-1, 'position'=>130), 'date_last_gen' =>array('type'=>'datetime', 'label'=>'Date last gen', 'enabled'=>1, 'visible'=>-1, 'position'=>135), diff --git a/htdocs/compta/paiement/card.php b/htdocs/compta/paiement/card.php index 85f56d298df..dd7651a6147 100644 --- a/htdocs/compta/paiement/card.php +++ b/htdocs/compta/paiement/card.php @@ -306,7 +306,7 @@ dol_fiche_end(); * List of invoices */ -$sql = 'SELECT f.rowid as facid, f.ref, f.type, f.total_ttc, f.paye, f.fk_statut, pf.amount, s.nom as name, s.rowid as socid'; +$sql = 'SELECT f.rowid as facid, f.ref, f.type, f.total_ttc, f.paye, f.entity, f.fk_statut, pf.amount, s.nom as name, s.rowid as socid'; $sql .= ' FROM '.MAIN_DB_PREFIX.'paiement_facture as pf,'.MAIN_DB_PREFIX.'facture as f,'.MAIN_DB_PREFIX.'societe as s'; $sql .= ' WHERE pf.fk_facture = f.rowid'; $sql .= ' AND f.fk_soc = s.rowid'; diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index 4d4c12ce473..cee75415eee 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -141,8 +141,13 @@ if ($action == 'update' && !empty($permissiontoadd)) if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; // Set value to update - if (in_array($object->fields[$key]['type'], array('text', 'html'))) { - $value = GETPOST($key, 'restricthtml'); + if (preg_match('/^(text|html)/', $object->fields[$key]['type'])) { + $tmparray = explode(':', $object->fields[$key]['type']); + if (!empty($tmparray[1])) { + $value = GETPOST($key, $tmparray[1]); + } else { + $value = GETPOST($key, 'restricthtml'); + } } elseif ($object->fields[$key]['type'] == 'date') { $value = dol_mktime(12, 0, 0, GETPOST($key.'month'), GETPOST($key.'day'), GETPOST($key.'year')); } elseif ($object->fields[$key]['type'] == 'datetime') { diff --git a/htdocs/core/class/CMailFile.class.php b/htdocs/core/class/CMailFile.class.php index 10c539a48de..bb8086f9b90 100644 --- a/htdocs/core/class/CMailFile.class.php +++ b/htdocs/core/class/CMailFile.class.php @@ -1544,6 +1544,7 @@ class CMailFile $i = 0; foreach ($arrayaddress as $val) { + $regs = array(); if (preg_match('/^(.*)<(.*)>$/i', trim($val), $regs)) { $name = trim($regs[1]); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 384c778d602..46567edf369 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -5800,7 +5800,7 @@ abstract class CommonObject } elseif (in_array($type, array('mail', 'phone', 'url'))) { $out = ''; - } elseif ($type == 'text') + } elseif (preg_match('/^text/', $type)) { if (!preg_match('/search_/', $keyprefix)) // If keyprefix is search_ or search_options_, we must just use a simple text field { @@ -5810,7 +5810,7 @@ abstract class CommonObject } else { $out = ''; } - } elseif ($type == 'html') + } elseif (preg_match('/^html/', $type)) { if (!preg_match('/search_/', $keyprefix)) // If keyprefix is search_ or search_options_, we must just use a simple text field { @@ -6584,7 +6584,7 @@ abstract class CommonObject return 'Error bad setup of extrafield'; } } else $value = ''; - } elseif ($type == 'text' || $type == 'html') + } elseif (preg_match('/^(text|html)/', $type)) { $value = dol_htmlentitiesbr($value); } elseif ($type == 'password') diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index fcd7199137c..e2749c5e183 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -653,7 +653,7 @@ class FormMail extends Form $out .= ' <'.$this->tomail.'>'; if ($this->withtofree) { - $out .= '
'.$langs->trans("and").' withto) : "").'" />'; + $out .= '
'.$langs->trans("and").' withto) : "").'" />'; } } else { // Note withto may be a text like 'AllRecipientSelected' @@ -663,7 +663,7 @@ class FormMail extends Form // The free input of email if (!empty($this->withtofree)) { - $out .= 'withto) : "")).'" />'; + $out .= 'withto) : "")).'" />'; } // The select combo if (!empty($this->withto) && is_array($this->withto)) @@ -675,7 +675,9 @@ class FormMail extends Form { $tmparray[$key] = dol_htmlentities($tmparray[$key], null, 'UTF-8', true); } - $withtoselected = GETPOST("receiver", 'restricthtml'); // Array of selected value + + $withtoselected = GETPOST("receiver", 'array'); // Array of selected value + if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action', 'aZ09') == 'presend') { $withtoselected = array_keys($tmparray); @@ -699,7 +701,7 @@ class FormMail extends Form { $tmparray[$key] = dol_htmlentities($tmparray[$key], null, 'UTF-8', true); } - $withtoselected = GETPOST("receiveruser", 'restricthtml'); // Array of selected value + $withtoselected = GETPOST("receiveruser", 'array'); // Array of selected value if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action', 'aZ09') == 'presend') { $withtoselected = array_keys($tmparray); @@ -743,7 +745,7 @@ class FormMail extends Form { $tmparray[$key] = dol_htmlentities($tmparray[$key], null, 'UTF-8', true); } - $withtoccselected = GETPOST("receivercc"); // Array of selected value + $withtoccselected = GETPOST("receivercc", 'array'); // Array of selected value $out .= $form->multiselectarray("receivercc", $tmparray, $withtoccselected, null, null, 'inline-block minwidth500', null, ""); } } @@ -763,7 +765,7 @@ class FormMail extends Form { $tmparray[$key] = dol_htmlentities($tmparray[$key], null, 'UTF-8', true); } - $withtoselected = GETPOST("receiverccuser", 'restricthtml'); // Array of selected value + $withtoselected = GETPOST("receiverccuser", 'array'); // Array of selected value if (empty($withtoselected) && count($tmparray) == 1 && GETPOST('action', 'aZ09') == 'presend') { $withtoselected = array_keys($tmparray); @@ -1060,7 +1062,7 @@ class FormMail extends Form if (!empty($this->withtocccreadonly)) { $out .= (!is_array($this->withtoccc) && !is_numeric($this->withtoccc)) ? $this->withtoccc : ""; } else { - $out .= 'withtoccc) && !is_numeric($this->withtoccc)) ? $this->withtoccc : '')).'" />'; + $out .= 'withtoccc) && !is_numeric($this->withtoccc)) ? $this->withtoccc : '')).'" />'; if (!empty($this->withtoccc) && is_array($this->withtoccc)) { $out .= " ".$langs->trans("and")."/".$langs->trans("or")." "; // multiselect array convert html entities into options tags, even if we dont want this, so we encode them a second time @@ -1068,7 +1070,7 @@ class FormMail extends Form foreach ($tmparray as $key => $val) { $tmparray[$key] = dol_htmlentities($tmparray[$key], null, 'UTF-8', true); } - $withtocccselected = GETPOST("receiverccc"); // Array of selected value + $withtocccselected = GETPOST("receiverccc", 'array'); // Array of selected value $out .= $form->multiselectarray("receiverccc", $tmparray, $withtocccselected, null, null, null, null, "90%"); } } diff --git a/htdocs/core/class/ldap.class.php b/htdocs/core/class/ldap.class.php index 06c3106a5dc..a1de5813b46 100644 --- a/htdocs/core/class/ldap.class.php +++ b/htdocs/core/class/ldap.class.php @@ -476,7 +476,7 @@ class Ldap // For better compatibility with Samba4 AD if ($this->serverType == "activedirectory") { - unset($info['cn']); // For avoid error : Operation not allowed on RDN (Code 67) + unset($info['cn']); // To avoid error : Operation not allowed on RDN (Code 67) } $result = @ldap_modify($this->connection, $dn, $info); diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index f4e8a06920b..aecf488d2b7 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -2847,8 +2847,12 @@ function dol_check_secure_access_document($modulepart, $original_file, $entity, $partofdirinoriginalfile = $partsofdirinoriginalfile[0]; if ($partofdirinoriginalfile && ($fuser->rights->$modulepart->$partofdirinoriginalfile->{$lire} || $fuser->rights->$modulepart->$partofdirinoriginalfile->{$read})) $accessallowed = 1; if ($fuser->rights->$modulepart->{$lire} || $fuser->rights->$modulepart->{$read}) $accessallowed = 1; - $original_file = $conf->$modulepart->dir_output.'/'.$original_file; - //var_dump($original_file); + + if (is_array($conf->$modulepart->multidir_output) && !empty($conf->$modulepart->multidir_output[$entity])) { + $original_file = $conf->$modulepart->multidir_output[$entity].'/'.$original_file; + } else { + $original_file = $conf->$modulepart->dir_output.'/'.$original_file; + } } // For modules who wants to manage different levels of permissions for documents diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index f34f2997af2..4fe156b249b 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -545,12 +545,18 @@ function GETPOST($paramname, $check = 'alphanohtml', $method = 0, $filter = null } // Check rule - if ($check == 'array') { + if (preg_match('/^array/', $check)) { // If 'array' or 'array:restricthtml' or 'array:aZ09' if (!is_array($out) || empty($out)) { $out = array(); } else { + $tmparray = explode(':', $check); + if (!empty($tmparray[1])) { + $tmpcheck = $tmparray[1]; + } else { + $tmpcheck = 'alphanohtml'; + } foreach ($out as $outkey => $outval) { - $out[$outkey] = checkVal($outval, 'alphanohtml', $filter, $options); + $out[$outkey] = checkVal($outval, $tmpcheck, $filter, $options); } } } diff --git a/htdocs/core/lib/payments.lib.php b/htdocs/core/lib/payments.lib.php index 969eb05328c..02b5727e174 100644 --- a/htdocs/core/lib/payments.lib.php +++ b/htdocs/core/lib/payments.lib.php @@ -2,6 +2,7 @@ /** * Copyright (C) 2013 Marcos García * Copyright (C) 2018 Frédéric France + * Copyright (C) 2020 Abbes Bahfir * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,15 +29,15 @@ function payment_prepare_head(Paiement $object) { - global $langs, $conf; + global $langs, $conf; - $h = 0; - $head = array(); + $h = 0; + $head = array(); - $head[$h][0] = DOL_URL_ROOT.'/compta/paiement/card.php?id='.$object->id; - $head[$h][1] = $langs->trans("Payment"); - $head[$h][2] = 'payment'; - $h++; + $head[$h][0] = DOL_URL_ROOT.'/compta/paiement/card.php?id='.$object->id; + $head[$h][1] = $langs->trans("Payment"); + $head[$h][2] = 'payment'; + $h++; // Show more tabs from modules // Entries must be declared in modules descriptor with line @@ -44,14 +45,50 @@ function payment_prepare_head(Paiement $object) // $this->tabs = array('entity:-tabname); to remove a tab complete_head_from_modules($conf, $langs, $object, $head, $h, 'payment'); - $head[$h][0] = DOL_URL_ROOT.'/compta/paiement/info.php?id='.$object->id; - $head[$h][1] = $langs->trans("Info"); - $head[$h][2] = 'info'; - $h++; + $head[$h][0] = DOL_URL_ROOT.'/compta/paiement/info.php?id='.$object->id; + $head[$h][1] = $langs->trans("Info"); + $head[$h][2] = 'info'; + $h++; - complete_head_from_modules($conf, $langs, $object, $head, $h, 'payment', 'remove'); + complete_head_from_modules($conf, $langs, $object, $head, $h, 'payment', 'remove'); - return $head; + return $head; +} + +/** + * Returns an array with the tabs for the "Bannkline" section + * It loads tabs from modules looking for the entity payment + * + * @param Bankline $object Current payment object + * @return array Tabs for the Bankline section + */ +function bankline_prepare_head($id) +{ + + global $langs, $conf; + + $h = 0; + $head = array(); + + $head[$h][0] = DOL_URL_ROOT.'/compta/bank/line.php?rowid='.$id; + $head[$h][1] = $langs->trans('BankTransaction'); + $head[$h][2] = 'bankline'; + $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); to remove a tab + complete_head_from_modules($conf, $langs, null, $head, $h, 'bankline'); + + $head[$h][0] = DOL_URL_ROOT.'/compta/bank/info.php?rowid='.$id; + $head[$h][1] = $langs->trans("Info"); + $head[$h][2] = 'info'; + $h++; + + complete_head_from_modules($conf, $langs, null, $head, $h, 'bankline', 'remove'); + + return $head; } /** diff --git a/htdocs/core/modules/modEmailCollector.class.php b/htdocs/core/modules/modEmailCollector.class.php index befebc84fea..86bf582edf2 100644 --- a/htdocs/core/modules/modEmailCollector.class.php +++ b/htdocs/core/modules/modEmailCollector.class.php @@ -306,23 +306,26 @@ class modEmailCollector extends DolibarrModules } } else dol_print_error($this->db); - $tmpsql = "SELECT rowid FROM ".MAIN_DB_PREFIX."emailcollector_emailcollector WHERE ref = 'Collect_Ticket_Answers' and entity = ".$conf->entity; + $tmpsql = "SELECT rowid FROM ".MAIN_DB_PREFIX."emailcollector_emailcollector WHERE ref = 'Collect_Responses_Out' and entity = ".$conf->entity; $tmpresql = $this->db->query($tmpsql); if ($tmpresql) { if ($this->db->num_rows($tmpresql) == 0) { - $descriptionA1 = 'This collector will scan your mailbox "Sent" directory to find emails that was sent as an answer of a Ticket (Module Ticket must be enabled) directly from your email browser instead of from Dolibarr. If such an email is found, the event of answer is recorded into Dolibarr.'; + $descriptionA1 = 'This collector will scan your mailbox "Sent" directory to find emails that was sent as an answer of another email directly from your email software and not from Dolibarr. If such an email is found, the event of answer is recorded into Dolibarr.'; $sqlforexampleA1 = "INSERT INTO ".MAIN_DB_PREFIX."emailcollector_emailcollector (entity, ref, label, description, source_directory, date_creation, fk_user_creat, status)"; - $sqlforexampleA1 .= " VALUES (".$conf->entity.", 'Collect_Ticket_Answers', 'Example to collect answers to tickets', '".$this->db->escape($descriptionA1)."', 'Sent', '".$this->db->idate(dol_now())."', ".$user->id.", 0)"; - /* - $sqlforexampleA2 = "INSERT INTO ".MAIN_DB_PREFIX."emailcollector_emailcollectorfilter (fk_emailcollector, type, date_creation, fk_user_creat, status)"; - $sqlforexampleA2 .= " VALUES ((SELECT rowid FROM ".MAIN_DB_PREFIX."emailcollector_emailcollector WHERE ref = 'Collect_Ticket_Requets' and entity = ".$conf->entity."), 'withouttrackingid', '".$this->db->idate(dol_now())."', ".$user->id.", 1)"; - $sqlforexampleA3 = "INSERT INTO ".MAIN_DB_PREFIX."emailcollector_emailcollectorfilter (fk_emailcollector, type, rulevalue, date_creation, fk_user_creat, status)"; - $sqlforexampleA3 .= " VALUES ((SELECT rowid FROM ".MAIN_DB_PREFIX."emailcollector_emailcollector WHERE ref = 'Collect_Ticket_Requets' and entity = ".$conf->entity."), 'to', 'support@example.com', '".$this->db->idate(dol_now())."', ".$user->id.", 1)"; - $sqlforexampleA4 = "INSERT INTO ".MAIN_DB_PREFIX."emailcollector_emailcollectoraction (fk_emailcollector, type, date_creation, fk_user_creat, status)"; - $sqlforexampleA4 .= " VALUES ((SELECT rowid FROM ".MAIN_DB_PREFIX."emailcollector_emailcollector WHERE ref = 'Collect_Ticket_Requets' and entity = ".$conf->entity."), 'ticket', '".$this->db->idate(dol_now())."', ".$user->id.", 1)"; - */ + $sqlforexampleA1 .= " VALUES (".$conf->entity.", 'Collect_Responses_Out', 'Example to collect answers to emails done from email software', '".$this->db->escape($descriptionA1)."', 'Sent', '".$this->db->idate(dol_now())."', ".$user->id.", 0)"; + + $sqlforexampleFilterA1 = "INSERT INTO ".MAIN_DB_PREFIX."emailcollector_emailcollectorfilter (fk_emailcollector, type, date_creation, fk_user_creat, status)"; + $sqlforexampleFilterA1 .= " VALUES ((SELECT rowid FROM ".MAIN_DB_PREFIX."emailcollector_emailcollector WHERE ref = 'Collect_Responses_Out' and entity = ".$conf->entity."), 'isanswer', '".$this->db->idate(dol_now())."', ".$user->id.", 1)"; + $sqlforexampleFilterA2 = "INSERT INTO ".MAIN_DB_PREFIX."emailcollector_emailcollectorfilter (fk_emailcollector, type, date_creation, fk_user_creat, status)"; + $sqlforexampleFilterA2 .= " VALUES ((SELECT rowid FROM ".MAIN_DB_PREFIX."emailcollector_emailcollector WHERE ref = 'Collect_Responses_Out' and entity = ".$conf->entity."), 'withouttrackingidinmsgid', '".$this->db->idate(dol_now())."', ".$user->id.", 1)"; + $sqlforexampleActionA1 = "INSERT INTO ".MAIN_DB_PREFIX."emailcollector_emailcollectoraction (fk_emailcollector, type, date_creation, fk_user_creat, status)"; + $sqlforexampleActionA1 .= " VALUES ((SELECT rowid FROM ".MAIN_DB_PREFIX."emailcollector_emailcollector WHERE ref = 'Collect_Responses_Out' and entity = ".$conf->entity."), 'recordevent', '".$this->db->idate(dol_now())."', ".$user->id.", 1)"; + $sql[] = $sqlforexampleA1; + $sql[] = $sqlforexampleFilterA1; + $sql[] = $sqlforexampleFilterA2; + $sql[] = $sqlforexampleActionA1; } } @@ -330,7 +333,7 @@ class modEmailCollector extends DolibarrModules $tmpresql = $this->db->query($tmpsql); if ($tmpresql) { if ($this->db->num_rows($tmpresql) == 0) { - $descriptionB1 = 'This collector will scan your mailbox to find all emails that are an answer of an email sent from your application. An event with the email response will be recorded at the good place (Module Agenda must be enabled). For example, if your send a commercial proposal, order or invoice by email and your customer answers your email, the system will automatically find the answer and add it into your ERP.'; + $descriptionB1 = 'This collector will scan your mailbox to find all emails that are an answer of an email sent from your application. An event (Module Agenda must be enabled) with the email response will be recorded at the good place. For example, if your send a commercial proposal, order, invoice or message for a ticket by email from the application, and your customer answers your email, the system will automatically find the answer and add it into your ERP.'; $sqlforexampleB1 = "INSERT INTO ".MAIN_DB_PREFIX."emailcollector_emailcollector (entity, ref, label, description, source_directory, date_creation, fk_user_creat, status)"; $sqlforexampleB1 .= " VALUES (".$conf->entity.", 'Collect_Responses_In', 'Example to collect any input email responses', '".$this->db->escape($descriptionB1)."', 'INBOX', '".$this->db->idate(dol_now())."', ".$user->id.", 0)"; diff --git a/htdocs/core/tpl/commonfields_edit.tpl.php b/htdocs/core/tpl/commonfields_edit.tpl.php index ace640d9b79..ad1a3bd2330 100644 --- a/htdocs/core/tpl/commonfields_edit.tpl.php +++ b/htdocs/core/tpl/commonfields_edit.tpl.php @@ -45,15 +45,23 @@ foreach ($object->fields as $key => $val) print ''; if (!empty($val['help'])) print $form->textwithpicto($langs->trans($val['label']), $langs->trans($val['help'])); else print $langs->trans($val['label']); print ''; print ''; if (in_array($val['type'], array('int', 'integer'))) $value = GETPOSTISSET($key) ?GETPOST($key, 'int') : $object->$key; - elseif ($val['type'] == 'text' || $val['type'] == 'html') $value = GETPOSTISSET($key) ?GETPOST($key, 'restricthtml') : $object->$key; - else $value = GETPOSTISSET($key) ?GETPOST($key, 'alpha') : $object->$key; + elseif (preg_match('/^(text|html)/', $val['type'])) { + $tmparray = explode(':', $val['type']); + if (!empty($tmparray[1])) { + $check = $tmparray[1]; + } else { + $check = 'restricthtml'; + } + $value = GETPOSTISSET($key) ? GETPOST($key, $check) : $object->$key; + } + else $value = GETPOSTISSET($key) ? GETPOST($key, 'alpha') : $object->$key; //var_dump($val.' '.$key.' '.$value); if ($val['noteditable']) print $object->showOutputField($val, $key, $value, '', '', '', 0); else print $object->showInputField($val, $key, $value, '', '', '', 0); diff --git a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php index 19eab2e5974..0800d66eea3 100644 --- a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php +++ b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php @@ -83,6 +83,7 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers || $action === 'CASHCONTROL_VALIDATE' || (in_array($object->element, array('facture', 'supplier_invoice')) && $action === 'DOC_DOWNLOAD' && $object->statut != 0) || (in_array($object->element, array('facture', 'supplier_invoice')) && $action === 'DOC_PREVIEW' && $object->statut != 0) + || (!empty($conf->global->BLOCKEDLOG_ADD_ACTIONS_SUPPORTED) && in_array($action, explode(',', $conf->global->BLOCKEDLOG_ADD_ACTIONS_SUPPORTED))) ) { $qualified++; diff --git a/htdocs/emailcollector/class/emailcollector.class.php b/htdocs/emailcollector/class/emailcollector.class.php index b070b69b4c9..943b7c73fb3 100644 --- a/htdocs/emailcollector/class/emailcollector.class.php +++ b/htdocs/emailcollector/class/emailcollector.class.php @@ -1006,6 +1006,8 @@ class EmailCollector extends CommonObject if ($rule['type'] == 'smaller') $search .= ($search ? ' ' : '').'SMALLER "'.str_replace('"', '', $rule['rulevalue']).'"'; if ($rule['type'] == 'larger') $search .= ($search ? ' ' : '').'LARGER "'.str_replace('"', '', $rule['rulevalue']).'"'; + if ($rule['type'] == 'withtrackingidinmsgid') { $searchfilterdoltrackid++; $searchhead .= '/Message-ID.*@'.preg_quote($host, '/').'/'; } + if ($rule['type'] == 'withouttrackingidinmsgid') { $searchfilterdoltrackid++; $searchhead .= '/Message-ID.*@'.preg_quote($host, '/').'/'; } if ($rule['type'] == 'withtrackingid') { $searchfilterdoltrackid++; $searchhead .= '/References.*@'.preg_quote($host, '/').'/'; } if ($rule['type'] == 'withouttrackingid') { $searchfilternodoltrackid++; $searchhead .= '! /References.*@'.preg_quote($host, '/').'/'; } diff --git a/htdocs/emailcollector/class/emailcollectorfilter.class.php b/htdocs/emailcollector/class/emailcollectorfilter.class.php index 40c8a91d235..cb8db05fa34 100644 --- a/htdocs/emailcollector/class/emailcollectorfilter.class.php +++ b/htdocs/emailcollector/class/emailcollectorfilter.class.php @@ -165,7 +165,7 @@ class EmailCollectorFilter extends CommonObject $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")); return -1; } - if (!in_array($this->type, array('seen', 'unseen', 'unanswered', 'answered', 'withtrackingid', 'withouttrackingid', 'isanswer', 'isnotanswer')) && empty($this->rulevalue)) + if (!in_array($this->type, array('seen', 'unseen', 'unanswered', 'answered', 'withtrackingidinmsgid', 'withouttrackingidinmsgid', 'withtrackingid', 'withouttrackingid', 'isanswer', 'isnotanswer')) && empty($this->rulevalue)) { $langs->load("errors"); $this->errors[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("SearchString")); diff --git a/htdocs/fichinter/class/fichinter.class.php b/htdocs/fichinter/class/fichinter.class.php index f0cfeed3cca..d0bc877d910 100644 --- a/htdocs/fichinter/class/fichinter.class.php +++ b/htdocs/fichinter/class/fichinter.class.php @@ -58,8 +58,8 @@ class Fichinter extends CommonObject 'datet' =>array('type'=>'date', 'label'=>'Datet', 'enabled'=>1, 'visible'=>-1, 'position'=>95), 'duree' =>array('type'=>'double', 'label'=>'Duree', 'enabled'=>1, 'visible'=>-1, 'position'=>100), 'description' =>array('type'=>'text', 'label'=>'Description', 'enabled'=>1, 'visible'=>-1, 'position'=>105, 'showoncombobox'=>1), - 'note_private' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>110), - 'note_public' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>115), + 'note_private' =>array('type'=>'text', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>110), + 'note_public' =>array('type'=>'text', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>115), 'model_pdf' =>array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>1, 'visible'=>0, 'position'=>120), 'last_main_doc' =>array('type'=>'varchar(255)', 'label'=>'Last main doc', 'enabled'=>1, 'visible'=>-1, 'position'=>125), 'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>130), diff --git a/htdocs/fichinter/class/fichinterrec.class.php b/htdocs/fichinter/class/fichinterrec.class.php index bf3b8d43f9d..818c1763786 100644 --- a/htdocs/fichinter/class/fichinterrec.class.php +++ b/htdocs/fichinter/class/fichinterrec.class.php @@ -564,14 +564,14 @@ class FichinterRec extends Fichinter if ($user->rights->fichinter->creer) { $sql = "UPDATE ".MAIN_DB_PREFIX."fichinter_rec "; $sql .= " SET frequency='".$this->db->escape($freq)."'"; - $sql .= ", last_gen='".$this->db->escape($courant)."'"; + $sql .= ", date_last_gen='".$this->db->escape($courant)."'"; $sql .= " WHERE rowid = ".$this->id; $resql = $this->db->query($sql); if ($resql) { $this->frequency = $freq; - $this->last_gen = $courant; + $this->date_last_gen = $courant; return 0; } else { dol_print_error($this->db); diff --git a/htdocs/includes/odtphp/Segment.php b/htdocs/includes/odtphp/Segment.php index cd8bec8c4ff..ca8797ba577 100644 --- a/htdocs/includes/odtphp/Segment.php +++ b/htdocs/includes/odtphp/Segment.php @@ -231,14 +231,10 @@ class Segment implements IteratorAggregate, Countable //throw new SegmentException("var $key not found in {$this->getName()}"); } - $value=$this->odf->htmlToUTFAndPreOdf($value); + $tag = $this->odf->getConfig('DELIMITER_LEFT') . $key . $this->odf->getConfig('DELIMITER_RIGHT'); - $value = $encode ? htmlspecialchars($value) : $value; - $value = ($charset == 'ISO-8859') ? utf8_encode($value) : $value; - - $value=$this->odf->preOdfToOdf($value); - - $this->vars[$this->odf->getConfig('DELIMITER_LEFT') . $key . $this->odf->getConfig('DELIMITER_RIGHT')] = $value; + $this->vars[$tag] = $this->odf->convertVarToOdf($value, $encode, $charset); + return $this; } /** diff --git a/htdocs/includes/odtphp/odf.php b/htdocs/includes/odtphp/odf.php index 3d510fdbaf1..5ec9b8f8870 100644 --- a/htdocs/includes/odtphp/odf.php +++ b/htdocs/includes/odtphp/odf.php @@ -141,7 +141,23 @@ class Odf //} } + $this->vars[$tag] = $this->convertVarToOdf($value, $encode, $charset); + + return $this; + } + + /** + * Replaces html tags in odt tags and returns a compatible string + * @param string $key Name of the variable within the template + * @param string $value Replacement value + * @param bool $encode If true, special XML characters are encoded + * @param string $charset Charset + * @return string + */ + public function convertVarToOdf($value, $encode = true, $charset = 'ISO-8859') + { $value = ($charset == 'ISO-8859') ? utf8_encode($value) : $value; + $convertedValue = $value; // Check if the value includes html tags if ($this->_hasHtmlTag($value) === true) { @@ -155,7 +171,7 @@ class Odf '' ); - $this->vars[$tag] = $this->_replaceHtmlWithOdtTag($this->_getDataFromHtml($value), $customStyles, $fontDeclarations); + $convertedValue = $this->_replaceHtmlWithOdtTag($this->_getDataFromHtml($value), $customStyles, $fontDeclarations); foreach ($customStyles as $key => $val) { array_push($automaticStyles, '' . $val . ''); @@ -179,9 +195,9 @@ class Odf } $this->contentXml = str_replace('', $fonts . '', $this->contentXml); } - else $this->vars[$tag] = preg_replace('/(\r\n|\r|\n)/i', "", $value); - - return $this; + else $convertedValue = preg_replace('/(\r\n|\r|\n)/i', "", $value); + + return $convertedValue; } /** diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index 83a502dbbff..b66d205ef40 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -98,7 +98,8 @@ ALTER TABLE llx_bom_bomline ADD COLUMN position integer NOT NULL DEFAULT 0; ALTER TABLE llx_bom_bomline ADD COLUMN qty_frozen smallint DEFAULT 0; ALTER TABLE llx_bom_bomline ADD COLUMN disable_stock_change smallint DEFAULT 0; -ALTER TABLE llx_bom_bomline DROP COLUMN `rank`; +-- VMYSQL4.1 ALTER TABLE llx_bom_bomline DROP COLUMN `rank`; +-- VPGSQL8.2 ALTER TABLE llx_bom_bomline DROP COLUMN rank; create table llx_categorie_warehouse ( diff --git a/htdocs/install/mysql/migration/3.2.0-3.3.0.sql b/htdocs/install/mysql/migration/3.2.0-3.3.0.sql index 91c155d3d84..c0efe6d68b3 100644 --- a/htdocs/install/mysql/migration/3.2.0-3.3.0.sql +++ b/htdocs/install/mysql/migration/3.2.0-3.3.0.sql @@ -315,6 +315,7 @@ ALTER TABLE llx_c_chargesociales ADD COLUMN accountancy_code varchar(15) DEFAULT -- Tables for accountancy expert DROP TABLE llx_accountingaccount; +DROP TABLE llx_accounting_account; DROP TABLE llx_accountingsystem; DROP TABLE llx_accounting_system; diff --git a/htdocs/install/mysql/migration/3.3.0-3.4.0.sql b/htdocs/install/mysql/migration/3.3.0-3.4.0.sql index 0f84c92ef22..88d9ae1b685 100644 --- a/htdocs/install/mysql/migration/3.3.0-3.4.0.sql +++ b/htdocs/install/mysql/migration/3.3.0-3.4.0.sql @@ -102,6 +102,10 @@ ALTER TABLE llx_expedition DROP FOREIGN KEY fk_expedition_fk_shipping_method; ALTER TABLE llx_expedition DROP INDEX idx_expedition_fk_expedition_methode; ALTER TABLE llx_expedition CHANGE COLUMN fk_expedition_methode fk_shipping_method integer; +-- This table and constraint should not exists as it appears in more recent version, but we may have it if we load an old dump +-- on a newly created database and we want to be sure upgrade of rowid into autoincrement done later will works. +ALTER TABLE llx_reception DROP FOREIGN KEY fk_reception_fk_shipping_method; + ALTER TABLE llx_c_shipment_mode ADD COLUMN tracking VARCHAR(255) NOT NULL DEFAULT '' AFTER description; --ALTER TABLE llx_c_shipment_mode DROP COLUMN CASCADE; diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 1498639d731..241848a594a 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -484,7 +484,7 @@ WarningPHPMailA=- Using the server of the Email Service Provider increase the tr WarningPHPMailB=- Some Email Service Providers (like Yahoo) do not allow you to send an email from another server than their own server. Your current setup uses the server of the application to send email and not the server of your email provider, so some recipients (the one compatible with the restrictive DMARC protocol), will ask your email provider if they can accept your email and some email providers (like Yahoo) may respond "no" because the server is not theirs, so few of your sent Emails may not be accepted for delivery (be careful also of your email provider's sending quota). WarningPHPMailC=- Using the SMTP server of your own Email Service Provider to send emails is also interesting so all emails sent from application will also be saved into your "Sent" directory of your mailbox. WarningPHPMail2=If your email SMTP provider need to restrict email client to some IP addresses (very rare), this is the IP address of the mail user agent (MUA) for your ERP CRM application: %s. -WarningPHPMailSPF=If the domain name in your sender email address is protected by SPF (ask you email provider), you must include the following IPs in the SPF record of the DNS of your domain: %s. +WarningPHPMailSPF=If the domain name in your sender email address is protected by a SPF record (ask you domain name registar), you must add the following IPs in the SPF record of the DNS of your domain: %s. ClickToShowDescription=Click to show description DependsOn=This module needs the module(s) RequiredBy=This module is required by module(s) @@ -1988,6 +1988,8 @@ LoadThirdPartyFromName=Load third party searching on %s (load only) LoadThirdPartyFromNameOrCreate=Load third party searching on %s (create if not found) WithDolTrackingID=Message from a conversation initiated by a first email sent from Dolibarr WithoutDolTrackingID=Message from a conversation initiated by a first email NOT sent from Dolibarr +WithDolTrackingIDInMsgId=Message sent from Dolibarr +WithoutDolTrackingIDInMsgId=Message NOT sent from Dolibarr CreateCandidature=Create candidature FormatZip=Zip MainMenuCode=Menu entry code (mainmenu) @@ -2030,7 +2032,7 @@ ImportSetup=Setup of module Import InstanceUniqueID=Unique ID of the instance SmallerThan=Smaller than LargerThan=Larger than -IfTrackingIDFoundEventWillBeLinked=Note that If a tracking ID of an object is found into incoming email, or if the email is an answer of an email aready collected and linked to an object, the event will be automatically linked to the known related object too. +IfTrackingIDFoundEventWillBeLinked=Note that If a tracking ID of an object is found into email, or if the email is an answer of an email aready collected and linked to an object, the created event will be automatically linked to the known related object. WithGMailYouCanCreateADedicatedPassword=With a GMail account, if you enabled the 2 steps validation, it is recommanded to create a dedicated second password for the application instead of using your own account passsword from https://myaccount.google.com/. EmailCollectorTargetDir=It may be a desired behaviour to move the email into another tag/directory when it was processed successfully. Just set name of directory here to use this feature (Do NOT use special characters in name). Note that you must also use a read/write login account. EmailCollectorLoadThirdPartyHelp=You can use this action to use the email content to find and load an existing thirdparty in your database. The found (or created) thirdparty will be used for following actions that need it. In the parameter field you can use for example 'EXTRACT:BODY:Name:\s([^\s]*)' if you want to extract the name of the thirdparty from a string 'Name: name to find' found into the body. diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 399dd3b10b8..8465f804d5c 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -70,7 +70,7 @@ class MyObject extends CommonObject /** - * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') + * 'type' if the field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" * 'label' the translation key. * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index a90c9dd5b1b..6c75d96fe89 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -72,15 +72,16 @@ class Products extends DolibarrApi * @param int $id ID of product * @param int $includestockdata Load also information about stock (slower) * @param bool $includesubproducts Load information about subproducts + * @param bool $includeparentid Load also ID of parent product (if product is a variant of a parent product) * @return array|mixed Data without useless information * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ - public function get($id, $includestockdata = 0, $includesubproducts = false) + public function get($id, $includestockdata = 0, $includesubproducts = false, $includeparentid = false) { - return $this->_fetch($id, '', '', '', $includestockdata, $includesubproducts); + return $this->_fetch($id, '', '', '', $includestockdata, $includesubproducts, $includeparentid); } /** @@ -91,6 +92,7 @@ class Products extends DolibarrApi * @param string $ref Ref of element * @param int $includestockdata Load also information about stock (slower) * @param bool $includesubproducts Load information about subproducts + * @param bool $includeparentid Load also ID of parent product (if product is a variant of a parent product) * * @return array|mixed Data without useless information * @@ -100,9 +102,9 @@ class Products extends DolibarrApi * @throws RestException 403 * @throws RestException 404 */ - public function getByRef($ref, $includestockdata = 0, $includesubproducts = false) + public function getByRef($ref, $includestockdata = 0, $includesubproducts = false, $includeparentid = false) { - return $this->_fetch('', $ref, '', '', $includestockdata, $includesubproducts); + return $this->_fetch('', $ref, '', '', $includestockdata, $includesubproducts, $includeparentid); } /** @@ -113,6 +115,7 @@ class Products extends DolibarrApi * @param string $ref_ext Ref_ext of element * @param int $includestockdata Load also information about stock (slower) * @param bool $includesubproducts Load information about subproducts + * @param bool $includeparentid Load also ID of parent product (if product is a variant of a parent product) * * @return array|mixed Data without useless information * @@ -122,9 +125,9 @@ class Products extends DolibarrApi * @throws RestException 403 * @throws RestException 404 */ - public function getByRefExt($ref_ext, $includestockdata = 0, $includesubproducts = false) + public function getByRefExt($ref_ext, $includestockdata = 0, $includesubproducts = false, $includeparentid = false) { - return $this->_fetch('', '', $ref_ext, '', $includestockdata, $includesubproducts); + return $this->_fetch('', '', $ref_ext, '', $includestockdata, $includesubproducts, $includeparentid); } /** @@ -135,6 +138,7 @@ class Products extends DolibarrApi * @param string $barcode Barcode of element * @param int $includestockdata Load also information about stock (slower) * @param bool $includesubproducts Load information about subproducts + * @param bool $includeparentid Load also ID of parent product (if product is a variant of a parent product) * * @return array|mixed Data without useless information * @@ -144,9 +148,9 @@ class Products extends DolibarrApi * @throws RestException 403 * @throws RestException 404 */ - public function getByBarcode($barcode, $includestockdata = 0, $includesubproducts = false) + public function getByBarcode($barcode, $includestockdata = 0, $includesubproducts = false, $includeparentid = false) { - return $this->_fetch('', '', '', $barcode, $includestockdata, $includesubproducts); + return $this->_fetch('', '', '', $barcode, $includestockdata, $includesubproducts, $includeparentid); } /** diff --git a/htdocs/takepos/css/pos.css.php b/htdocs/takepos/css/pos.css.php index 4666de59a8e..973bbabba2d 100644 --- a/htdocs/takepos/css/pos.css.php +++ b/htdocs/takepos/css/pos.css.php @@ -669,3 +669,71 @@ div#moreinfo, div#infowarehouse { padding-right: 4px; } } + +/* Modal box */ +.modal { + display: none; /* Hidden by default */ + position: fixed; + z-index: 20; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgb(0,0,0); + background-color: rgba(0,0,0,0.4); +} + +/* The Close Button */ +.close { + color: #aaa; + float: right; + font-size: 28px; + font-weight: bold; +} + +.close:hover, +.close:focus { + color: black; + text-decoration: none; + cursor: pointer; +} + +.modal-header { + padding: 2px 16px; + background-color: #2b4161; + color: white; +} + +.modal-body {padding: 2px 16px;} + +.modal-content { + position: relative; + background-color: #fefefe; + margin: 15% auto; /* 15% from the top and centered */ + padding: 0; + border: 1px solid #888; + width: 40%; + box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19); + animation-name: animatetop; + animation-duration: 0.4s; + min-width: 200px; +} + +@keyframes animatetop { + from {top: -300px; opacity: 0} + to {top: 0; opacity: 1} +} + +.block { + display: block; + width: 100%; + border: none; + color: white; + background-color: #8c907e; + padding: 14px 28px; + font-size: 16px; + cursor: pointer; + text-align: center; + margin: 2px; +} diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index 73b039d97e9..bcc56ff0166 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -728,27 +728,12 @@ function CashReport(rowid) // Popup to select the terminal to use function TerminalsDialog() { - jQuery("#dialog-info").dialog({ - resizable: false, - height: global->TAKEPOS_NUM_TERMINALS / 3 * 20); ?>, - width: dol_optimize_smallscreen ? 316 : 400); ?>, - modal: true, - buttons: { - 'trans("Terminal")) ?> 1': function() { - location.href='index.php?setterminal=1'; - } - global->TAKEPOS_NUM_TERMINALS; $i++) - { - print ", - '".dol_escape_js($langs->trans("Terminal"))." ".$i."': function() { - location.href='index.php?setterminal=".$i."'; - } - "; - } - ?> - } - }); + var modal = document.getElementById("ModalTerminal"); + var span = document.getElementsByClassName("close")[0]; + span.onclick = function() { + modal.style.display = "none"; + } + modal.style.display = "block"; } function DirectPayment(){ @@ -802,7 +787,6 @@ $( document ).ready(function() { '.$langs->trans('TerminalSelect').''; $keyCodeForEnter = $conf->global->{'CASHDESK_READER_KEYCODE_FOR_ENTER'.$_SESSION['takeposterminal']} > 0 ? $conf->global->{'CASHDESK_READER_KEYCODE_FOR_ENTER'.$_SESSION['takeposterminal']} : ''; ?>
@@ -853,6 +837,28 @@ if (empty($conf->global->TAKEPOS_HIDE_HEAD_BAR)) { } ?> + + + + +