From bb700494a18ba764ca70f43acff1ab2003efac9d Mon Sep 17 00:00:00 2001 From: fappels Date: Wed, 13 Dec 2017 20:39:37 +0100 Subject: [PATCH 01/27] Fix Collation update missing for llx_expeditiondet_batch --- htdocs/install/mysql/migration/6.0.0-7.0.0.sql | 2 ++ 1 file changed, 2 insertions(+) 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 bf49e8730fb..dbff8454417 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 @@ -37,6 +37,8 @@ -- VMYSQLUTF8UNICODECI ALTER TABLE llx_stock_mouvement MODIFY batch VARCHAR(30) COLLATE utf8_unicode_ci; -- VMYSQLUTF8UNICODECI ALTER TABLE llx_product_lot MODIFY batch VARCHAR(30) CHARACTER SET utf8; -- VMYSQLUTF8UNICODECI ALTER TABLE llx_product_lot MODIFY batch VARCHAR(30) COLLATE utf8_unicode_ci; +-- VMYSQLUTF8UNICODECI ALTER TABLE llx_expeditiondet_batch MODIFY batch VARCHAR(30) CHARACTER SET utf8; +-- VMYSQLUTF8UNICODECI ALTER TABLE llx_expeditiondet_batch MODIFY batch VARCHAR(30) COLLATE utf8_unicode_ci; -- VMYSQLUTF8UNICODECI ALTER TABLE llx_product_batch MODIFY batch VARCHAR(30) CHARACTER SET utf8; -- VMYSQLUTF8UNICODECI ALTER TABLE llx_product_batch MODIFY batch VARCHAR(30) COLLATE utf8_unicode_ci; -- VMYSQLUTF8UNICODECI ALTER TABLE llx_product MODIFY accountancy_code_sell VARCHAR(32) CHARACTER SET utf8; From 0c8ff80af07120a8d0bded87d1ed64d8e45b4398 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Thu, 14 Dec 2017 06:57:17 +0100 Subject: [PATCH 02/27] FIX : Edit accountancy in loan --- htdocs/loan/card.php | 143 ++++++++++++++++++++----------- htdocs/loan/class/loan.class.php | 3 + 2 files changed, 94 insertions(+), 52 deletions(-) diff --git a/htdocs/loan/card.php b/htdocs/loan/card.php index 32d8aa1c2aa..b920c8d1a6a 100644 --- a/htdocs/loan/card.php +++ b/htdocs/loan/card.php @@ -27,8 +27,8 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/loan/class/loan.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/loan.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; -if (! empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; if (! empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php'; +if (! empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php'; require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; @@ -124,42 +124,42 @@ if (empty($reshook)) setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Rate")), null, 'errors'); } - if (! $error) - { - $object->label = GETPOST('label'); - $object->fk_bank = GETPOST('accountid'); - $object->capital = $capital; - $object->datestart = $datestart; - $object->dateend = $dateend; - $object->nbterm = GETPOST('nbterm'); - $object->rate = $rate; - $object->note_private = GETPOST('note_private','none'); - $object->note_public = GETPOST('note_public','none'); - $object->fk_project = GETPOST('projectid','int'); + if (! $error) + { + $object->label = GETPOST('label'); + $object->fk_bank = GETPOST('accountid'); + $object->capital = $capital; + $object->datestart = $datestart; + $object->dateend = $dateend; + $object->nbterm = GETPOST('nbterm'); + $object->rate = $rate; + $object->note_private = GETPOST('note_private','none'); + $object->note_public = GETPOST('note_public','none'); + $object->fk_project = GETPOST('projectid','int'); - $accountancy_account_capital = GETPOST('accountancy_account_capital'); - $accountancy_account_insurance = GETPOST('accountancy_account_insurance'); - $accountancy_account_interest = GETPOST('accountancy_account_interest'); + $accountancy_account_capital = GETPOST('accountancy_account_capital'); + $accountancy_account_insurance = GETPOST('accountancy_account_insurance'); + $accountancy_account_interest = GETPOST('accountancy_account_interest'); - if ($accountancy_account_capital <= 0) { $object->account_capital = ''; } else { $object->account_capital = $accountancy_account_capital; } - if ($accountancy_account_insurance <= 0) { $object->account_insurance = ''; } else { $object->account_insurance = $accountancy_account_insurance; } - if ($accountancy_account_interest <= 0) { $object->account_interest = ''; } else { $object->account_interest = $accountancy_account_interest; } + if ($accountancy_account_capital <= 0) { $object->account_capital = ''; } else { $object->account_capital = $accountancy_account_capital; } + if ($accountancy_account_insurance <= 0) { $object->account_insurance = ''; } else { $object->account_insurance = $accountancy_account_insurance; } + if ($accountancy_account_interest <= 0) { $object->account_interest = ''; } else { $object->account_interest = $accountancy_account_interest; } - $id=$object->create($user); - if ($id <= 0) - { - $error++; - setEventMessages($object->error, $object->errors, 'errors'); - $action = 'create'; - } - } - } - else - { - header("Location: index.php"); - exit(); - } - } + $id=$object->create($user); + if ($id <= 0) + { + $error++; + setEventMessages($object->error, $object->errors, 'errors'); + $action = 'create'; + } + } + } + else + { + header("Location: index.php"); + exit(); + } + } // Update record else if ($action == 'update' && $user->rights->loan->write) @@ -550,11 +550,13 @@ if ($id > 0) print ''; // Accountancy account capital - print ''; - print $langs->trans("LoanAccountancyCapitalCode"); - print ''; + print ''; if ($action == 'edit') { + print ''; + print $langs->trans("LoanAccountancyCapitalCode"); + print ''; + if (! empty($conf->accounting->enabled)) { print $formaccounting->select_account($object->account_capital, 'accountancy_account_capital', 1, '', 1, 1); @@ -563,23 +565,36 @@ if ($id > 0) { print ''; } + print ''; } else { - if (! empty($conf->accounting->enabled)) { - print length_accountg($object->account_capital); + print ''; + print $langs->trans("LoanAccountancyCapitalCode"); + print ''; + + if (! empty($conf->accounting->enabled)) + { + $accountingaccount = new AccountingAccount($db); + $accountingaccount->fetch('',$object->account_capital, 1); + + print $accountingaccount->getNomUrl(0,1,1,'',1); } else { print $object->account_capital; } + + print ''; } - print ''; + print ''; // Accountancy account insurance - print ''; - print $langs->trans("LoanAccountancyInsuranceCode"); - print ''; + print ''; if ($action == 'edit') { + print ''; + print $langs->trans("LoanAccountancyInsuranceCode"); + print ''; + if (! empty($conf->accounting->enabled)) { print $formaccounting->select_account($object->account_insurance, 'accountancy_account_insurance', 1, '', 1, 1); @@ -588,23 +603,36 @@ if ($id > 0) { print ''; } + print ''; } else { - if (! empty($conf->accounting->enabled)) { - print length_accountg($object->account_insurance); + print ''; + print $langs->trans("LoanAccountancyCapitalCode"); + print ''; + + if (! empty($conf->accounting->enabled)) + { + $accountingaccount = new AccountingAccount($db); + $accountingaccount->fetch('',$object->account_insurance, 1); + + print $accountingaccount->getNomUrl(0,1,1,'',1); } else { print $object->account_insurance; } + + print ''; } - print ''; + print ''; // Accountancy account interest - print ''; - print $langs->trans("LoanAccountancyInterestCode"); - print ''; + print ''; if ($action == 'edit') { + print ''; + print $langs->trans("LoanAccountancyInterestCode"); + print ''; + if (! empty($conf->accounting->enabled)) { print $formaccounting->select_account($object->account_interest, 'accountancy_account_interest', 1, '', 1, 1); @@ -613,16 +641,27 @@ if ($id > 0) { print ''; } + print ''; } else { - if (! empty($conf->accounting->enabled)) { - print length_accountg($object->account_interest); + print ''; + print $langs->trans("LoanAccountancyInterestCode"); + print ''; + + if (! empty($conf->accounting->enabled)) + { + $accountingaccount = new AccountingAccount($db); + $accountingaccount->fetch('',$object->account_interest, 1); + + print $accountingaccount->getNomUrl(0,1,1,'',1); } else { print $object->account_interest; } + + print ''; } - print ''; + print ''; print ''; diff --git a/htdocs/loan/class/loan.class.php b/htdocs/loan/class/loan.class.php index 8464860be2f..19e8f5f84bf 100644 --- a/htdocs/loan/class/loan.class.php +++ b/htdocs/loan/class/loan.class.php @@ -297,6 +297,9 @@ class Loan extends CommonObject $sql.= " capital='".price2num($this->db->escape($this->capital))."',"; $sql.= " datestart='".$this->db->idate($this->datestart)."',"; $sql.= " dateend='".$this->db->idate($this->dateend)."',"; + $sql.= " accountancy_account_capital = '".$this->db->escape($this->account_capital)."',"; + $sql.= " accountancy_account_insurance = '".$this->db->escape($this->account_insurance)."',"; + $sql.= " accountancy_account_interest = '".$this->db->escape($this->account_interest)."',"; $sql.= " fk_projet=".(empty($this->fk_project)?'NULL':$this->fk_project).","; $sql.= " fk_user_modif = ".$user->id; $sql.= " WHERE rowid=".$this->id; From 88b456a542be124559a26af86e8cff1f9eaea270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien?= Date: Thu, 14 Dec 2017 11:53:48 +0100 Subject: [PATCH 03/27] Resolve bug for REST API PUT task An error occured when I was trying to PUT task despite all rigths. Ressource 'task' --> 'tasks' --- htdocs/projet/class/api_tasks.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/projet/class/api_tasks.class.php b/htdocs/projet/class/api_tasks.class.php index d5215ef8106..81e28663cc4 100644 --- a/htdocs/projet/class/api_tasks.class.php +++ b/htdocs/projet/class/api_tasks.class.php @@ -275,7 +275,7 @@ class Tasks extends DolibarrApi throw new RestException(404, 'Task not found'); } - if( ! DolibarrApi::_checkAccessToResource('task',$this->task->id)) { + if( ! DolibarrApi::_checkAccessToResource('tasks',$this->task->id)) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } @@ -432,7 +432,7 @@ class Tasks extends DolibarrApi throw new RestException(404, 'Task not found'); } - if( ! DolibarrApi::_checkAccessToResource('task',$this->project->id)) { + if( ! DolibarrApi::_checkAccessToResource('tasks',$this->project->id)) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } foreach($request_data as $field => $value) { @@ -467,7 +467,7 @@ class Tasks extends DolibarrApi throw new RestException(404, 'Task not found'); } - if( ! DolibarrApi::_checkAccessToResource('task',$this->project->id)) { + if( ! DolibarrApi::_checkAccessToResource('tasks',$this->project->id)) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } From 5af153550d39c3288cddf72e912dad790c640aab Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Dec 2017 15:15:14 +0100 Subject: [PATCH 04/27] Debug blockedlog: - Add a track into log when we disable/enable module - Add a protection to avoid disable of module when recording was started - Better compatibility with multicompany - Can filter on ref and amount - Add a permission to read the blockedlog - Add more information on payments/invoice/thirdparty into log - Reset of module data after a migration from v6 (not compatible) --- htdocs/admin/modules.php | 9 +- htdocs/blockedlog/admin/blockedlog.php | 8 +- htdocs/blockedlog/admin/blockedlog_list.php | 12 +- htdocs/blockedlog/ajax/block-add.php | 2 +- htdocs/blockedlog/ajax/block-info.php | 2 +- htdocs/blockedlog/class/blockedlog.class.php | 194 ++++++++++++++---- htdocs/blockedlog/lib/blockedlog.lib.php | 9 +- htdocs/core/lib/functions.lib.php | 8 +- htdocs/core/lib/usergroups.lib.php | 4 +- htdocs/core/modules/DolibarrModules.class.php | 2 +- htdocs/core/modules/modBlockedLog.class.php | 126 ++++++++++-- ..._modBlockedlog_ActionsBlockedLog.class.php | 35 +++- htdocs/install/upgrade2.php | 124 ++++++++++- htdocs/langs/en_US/blockedlog.lang | 6 +- htdocs/langs/en_US/install.lang | 2 + .../core/modules/modMyModule.class.php | 20 +- .../modulebuilder/template/myobject_list.php | 1 + htdocs/user/class/user.class.php | 24 ++- htdocs/user/class/usergroup.class.php | 5 + htdocs/user/group/card.php | 5 + htdocs/user/group/perms.php | 42 ++-- htdocs/user/perms.php | 41 ++-- 22 files changed, 519 insertions(+), 162 deletions(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 49526696157..18546d67dc1 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -79,9 +79,9 @@ $familyinfo=array( $param=''; if ($search_keyword) $param.='&search_keyword='.urlencode($search_keyword); -if ($search_status) $param.='&search_status='.urlencode($search_status); -if ($search_nature) $param.='&search_nature='.urlencode($search_nature); -if ($search_version) $param.='&search_version='.urlencode($search_version); +if ($search_status > -1) $param.='&search_status='.urlencode($search_status); +if ($search_nature > -1) $param.='&search_nature='.urlencode($search_nature); +if ($search_version > -1) $param.='&search_version='.urlencode($search_version); $dirins=DOL_DOCUMENT_ROOT.'/custom'; $urldolibarrmodules='https://www.dolistore.com/'; @@ -691,7 +691,8 @@ if ($mode == 'common') } else if (! empty($objMod->always_enabled) || ((! empty($conf->multicompany->enabled) && $objMod->core_enabled) && ($user->entity || $conf->entity!=1))) { - print $langs->trans("Required"); + if ($objMod->alreadyUsed()) print $langs->trans("Used"); + else print $langs->trans("Required"); if (! empty($conf->multicompany->enabled) && $user->entity) $disableSetup++; } else diff --git a/htdocs/blockedlog/admin/blockedlog.php b/htdocs/blockedlog/admin/blockedlog.php index 5aa202e2806..091e520c333 100644 --- a/htdocs/blockedlog/admin/blockedlog.php +++ b/htdocs/blockedlog/admin/blockedlog.php @@ -30,7 +30,7 @@ $langs->load("admin"); $langs->load("other"); $langs->load("blockedlog"); -if (! $user->admin) accessforbidden(); +if (! $user->admin || empty($conf->blockedlog->enabled)) accessforbidden(); $action = GETPOST('action','alpha'); $backtopage = GETPOST('backtopage', 'alpha'); @@ -76,9 +76,8 @@ if (preg_match('/del_(.*)/',$action,$reg)) * View */ -$block_static = new BlockedLog($db); - $form=new Form($db); +$block_static = new BlockedLog($db); llxHeader('',$langs->trans("BlockedLogSetup")); @@ -107,8 +106,7 @@ print ''; if (!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY)) { // Example with a yes / no select - $var=!$var; - print ''; + print ''; print ''.$langs->trans("BlockedLogAuthorityUrl").img_info($langs->trans('BlockedLogAuthorityNeededToStoreYouFingerprintsInNonAlterableRemote')).''; print ''; print '
'; diff --git a/htdocs/blockedlog/admin/blockedlog_list.php b/htdocs/blockedlog/admin/blockedlog_list.php index ee54f18348d..5caf9ef501c 100644 --- a/htdocs/blockedlog/admin/blockedlog_list.php +++ b/htdocs/blockedlog/admin/blockedlog_list.php @@ -59,12 +59,12 @@ $pagenext = $page + 1; if (empty($sortfield)) $sortfield='rowid'; if (empty($sortorder)) $sortorder='DESC'; - - - $block_static = new BlockedLog($db); +$result = restrictedArea($user, 'blockedlog', 0, ''); + + /* * Actions */ @@ -335,8 +335,10 @@ jQuery(document).ready(function () { for(x in data) { value = data[x]; - $("#pop-info table tbody").append(""+prefix+x+""+value+""); - if( (typeof value === "object") && (value !== null) ) { + if (typeof value != "object") { + $("#pop-info table tbody").append(""+prefix+x+""+value+""); + } + if ((typeof value === "object") && (value !== null)) { drawData(value, prefix+x+" >> "); } } diff --git a/htdocs/blockedlog/ajax/block-add.php b/htdocs/blockedlog/ajax/block-add.php index c82eac81e7b..24fd71f0514 100644 --- a/htdocs/blockedlog/ajax/block-add.php +++ b/htdocs/blockedlog/ajax/block-add.php @@ -19,7 +19,7 @@ /** * \file htdocs/blockedlog/ajax/block-add.php * \ingroup blockedlog - * \brief Block-add + * \brief block-add */ diff --git a/htdocs/blockedlog/ajax/block-info.php b/htdocs/blockedlog/ajax/block-info.php index 83317f33d57..888f9385630 100644 --- a/htdocs/blockedlog/ajax/block-info.php +++ b/htdocs/blockedlog/ajax/block-info.php @@ -39,7 +39,7 @@ require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; $id = GETPOST('id'); $block = new BlockedLog($db); -if($block->fetch($id)>0) { +if ($block->fetch($id)>0) { echo json_encode($block->object_data); } else { diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index 621ee254a48..bf9f59f14e2 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -29,6 +29,11 @@ class BlockedLog * @var int */ public $id; + /** + * Entity + * @var int + */ + public $entity; public $error = ''; public $errors = array(); @@ -147,6 +152,21 @@ class BlockedLog $this->error++; } } + else if ($this->action == 'MODULE_SET') + { + return 'System to track events into unalterable logs were enabled'; + } + else if ($this->action == 'MODULE_RESET') + { + if ($this->signature == '0000000000') + { + return 'System to track events into unalterable logs were disabled after some recording were done. We saved a special Fingerprint to track the chain as broken.'; + } + else + { + return 'System to track events into unalterable logs were disabled. This is possible because no record were done yet.'; + } + } return ''.$langs->trans('ImpossibleToReloadObject', $this->element, $this->fk_object).''; @@ -178,9 +198,10 @@ class BlockedLog /** * Populate properties of log from object data * - * @param Object $object object to store - * @param string $action action - * @param string $amounts amounts + * @param Object $object object to store + * @param string $action action + * @param string $amounts amounts + * @return int >0 if OK, <0 if KO */ public function setObjectData(&$object, $action, $amounts) { @@ -214,9 +235,7 @@ class BlockedLog $this->object_data=new stdClass(); // Add thirdparty info - if (empty($object->thirdparty) && method_exists($object, 'fetch_thirdparty')) $object->fetch_thirdparty(); - if (! empty($object->thirdparty)) { $this->object_data->thirdparty = new stdClass(); @@ -249,7 +268,6 @@ class BlockedLog } // Add user info - $this->fk_user = $user->id; $this->user_fullname = $user->getFullName($langs); @@ -257,42 +275,97 @@ class BlockedLog if ($this->element == 'facture') { - $this->object_data->total_ht = (double) $object->total_ht; - $this->object_data->total_tva = (double) $object->total_tva; - $this->object_data->total_ttc = (double) $object->total_ttc; - $this->object_data->total_localtax1 = (double) $object->total_localtax1; - $this->object_data->total_localtax2 = (double) $object->total_localtax2; - - $this->object_data->revenue_stamp = (double) $object->revenue_stamp; - $this->object_data->date_pointoftax = (double) $object->date_pointoftax; - $this->object_data->note_public = (double) $object->note_public; - } - if($this->element == 'invoice_supplier') { - if(empty($object->thirdparty))$object->fetch_thirdparty(); - $this->object_data->thirdparty = new stdClass(); - - foreach($object->thirdparty as $key=>$value) { - if(!is_object($value)) $this->object_data->thirdparty->{$key} = $value; + foreach($object as $key=>$value) + { + if (in_array($key, array('fields'))) continue; // Discard some properties + if (! in_array($key, array( + 'ref','facnumber','ref_client','ref_supplier','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public' + ))) continue; // Discard if not into a dedicated list + if (!is_object($value)) $this->object_data->{$key} = $value; + } + } + elseif ($this->element == 'invoice_supplier') + { + foreach($object as $key=>$value) + { + if (in_array($key, array('fields'))) continue; // Discard some properties + if (! in_array($key, array( + 'ref','facnumber','ref_client','ref_supplier','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public' + ))) continue; // Discard if not into a dedicated list + if (!is_object($value)) $this->object_data->{$key} = $value; } - - $this->object_data->total_ht = (double) $object->total_ht; - $this->object_data->total_tva = (double) $object->total_tva; - $this->object_data->total_ttc = (double) $object->total_ttc; - $this->object_data->total_localtax1 = (double) $object->total_localtax1; - $this->object_data->total_localtax2 = (double) $object->total_localtax2; - - $this->object_data->revenue_stamp = (double) $object->revenue_stamp; - $this->object_data->date_pointoftax = (double) $object->date_pointoftax; - $this->object_data->note_public = (double) $object->note_public; } elseif ($this->element == 'payment'|| $object->element == 'payment_supplier') { - $this->object_data->amounts = $object->amounts; + //var_dump($object); + $this->object_data->ref = $object->ref; + $this->object_data->date = $object->datepaye; + $this->object_data->type_code = dol_getIdFromCode($this->db, $object->paiementid, 'c_paiement', 'id', 'code'); + $this->object_data->payment_num = $object->num_paiement; + //$this->object_data->fk_account = $object->fk_account; + $this->object_data->note = $object->note; + //var_dump($this->object_data);exit; + + $paymentpartnumber=0; + foreach($object->amounts as $invoiceid => $amount) + { + if ($this->element == 'payment_supplier') + { + $tmpinvoice = new FactureFournisseur($this->db); + } + else + { + $tmpinvoice = new Facture($this->db); + } + $result = $tmpinvoice->fetch($invoiceid); + if ($result <= 0) + { + $this->error = $tmpinvoice->error; + $this->errors = $tmpinvoice->errors; + return -1; + } + $result = $tmpinvoice->fetch_thirdparty(); + if ($result <= 0) + { + $this->error = $tmpinvoice->error; + $this->errors = $tmpinvoice->errors; + return -1; + } + + $paymentpart = new stdClass(); + $paymentpart->amount = $amount; + + $paymentpart->thirdparty = new stdClass(); + foreach($tmpinvoice->thirdparty as $key=>$value) + { + if (in_array($key, array('fields'))) continue; // Discard some properties + if (! in_array($key, array( + 'name','name_alias','ref_ext','address','zip','town','state_code','country_code','idprof1','idprof2','idprof3','idprof4','idprof5','idprof6','phone','fax','email','barcode', + 'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur' + ))) continue; // Discard if not into a dedicated list + if (!is_object($value)) $paymentpart->thirdparty->{$key} = $value; + } + + $paymentpart->invoice = new stdClass(); + foreach($tmpinvoice as $key=>$value) + { + if (in_array($key, array('fields'))) continue; // Discard some properties + if (! in_array($key, array( + 'ref','facnumber','ref_client','ref_supplier','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public' + ))) continue; // Discard if not into a dedicated list + if (!is_object($value)) $paymentpart->invoice->{$key} = $value; + } + + $paymentpartnumber++; + $this->object_data->payment_part[$paymentpartnumber] = $paymentpart; + } } elseif($this->element == 'payment_salary') { $this->object_data->amounts = array($object->amount); } + + return 1; } /** @@ -315,7 +388,8 @@ class BlockedLog $langs->load("blockedlog"); - $sql = "SELECT b.rowid, b.date_creation, b.signature, b.signature_line, b.amounts, b.action, b.element, b.fk_object, b.certified, b.tms, b.fk_user, b.user_fullname, b.date_object, b.ref_object, b.object_data"; + $sql = "SELECT b.rowid, b.date_creation, b.signature, b.signature_line, b.amounts, b.action, b.element, b.fk_object, b.entity,"; + $sql.= " b.certified, b.tms, b.fk_user, b.user_fullname, b.date_object, b.ref_object, b.object_data"; $sql.= " FROM ".MAIN_DB_PREFIX."blockedlog as b"; if ($id) $sql.= " WHERE b.rowid = ". $id; @@ -327,6 +401,7 @@ class BlockedLog $obj = $this->db->fetch_object($resql); $this->id = $obj->rowid; + $this->entity = $obj->entity; $this->ref = $obj->rowid; $this->date_creation = $this->db->jdate($obj->date_creation); @@ -383,10 +458,11 @@ class BlockedLog /** * Create blocked log in database. * - * @param User $user Object user that create - * @return int <0 if KO, >0 if OK + * @param User $user Object user that create + * @param int $forcesignature Force signature (for example '0000000000' when we disabled the module) + * @return int <0 if KO, >0 if OK */ - public function create($user) { + public function create($user, $forcesignature='') { global $conf,$langs,$hookmanager; @@ -400,14 +476,14 @@ class BlockedLog dol_syslog(get_class($this).'::create action='.$this->action.' fk_user='.$this->fk_user.' user_fullname='.$this->user_fullname, LOG_DEBUG); // Check parameters/properties - if (is_null($this->amounts)) + if (! isset($this->amounts)) // amount can be 0 for some events (like when module is disabled) { $this->error=$langs->trans("BlockLogNeedAmountsValue"); dol_syslog($this->error, LOG_WARNING); return -1; } - if(empty($this->element)) { + if (empty($this->element)) { $this->error=$langs->trans("BlockLogNeedElement"); dol_syslog($this->error, LOG_WARNING); return -2; @@ -429,6 +505,7 @@ class BlockedLog $this->signature_line = dol_hash($keyforsignature, '5'); // Not really usefull $this->signature = dol_hash($previoushash . $keyforsignature, '5'); + if ($forcesignature) $this->signature = $forcesignature; //var_dump($keyforsignature);var_dump($previoushash);var_dump($this->signature_line);var_dump($this->signature); $sql = "INSERT INTO ".MAIN_DB_PREFIX."blockedlog ("; @@ -460,7 +537,7 @@ class BlockedLog $sql.= "0,"; $sql.= $this->fk_user.","; $sql.= "'".$this->db->escape($this->user_fullname)."',"; - $sql.= $conf->entity; + $sql.= ($this->entity ? $this->entity : $conf->entity); $sql.= ")"; $res = $this->db->query($sql); @@ -544,7 +621,8 @@ class BlockedLog $previoussignature=''; - $sql="SELECT rowid, signature FROM ".MAIN_DB_PREFIX."blockedlog WHERE entity=".$conf->entity; + $sql = "SELECT rowid, signature FROM ".MAIN_DB_PREFIX."blockedlog"; + $sql.= " WHERE entity=".$conf->entity; if ($beforeid) $sql.= " AND rowid < ".(int) $beforeid; $sql.=" ORDER BY rowid DESC LIMIT 1"; $sql.=($withlock ? " FOR UPDATE ": ""); @@ -611,7 +689,7 @@ class BlockedLog } else{ $sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog - WHERE element='".$element."' AND fk_object=".(int) $fk_object; + WHERE entity=".$conf->entity." AND element='".$element."' AND fk_object=".(int) $fk_object; } if ($search_start > 0) $sql.=" AND date_creation >= '".$this->db->idate($search_start)."'"; @@ -649,7 +727,7 @@ class BlockedLog } /** - * Return the signature (hash) of the "genesis-block" (Block 0) + * Return the signature (hash) of the "genesis-block" (Block 0). * * @return string Signature of genesis-block for current conf->entity */ @@ -671,5 +749,35 @@ class BlockedLog return $conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT; } + + /** + * Check if module was already used or not for at least one recording. + * + * @param int $ignoresystem Ignore system events for the test + */ + function alreadyUsed($ignoresystem=0) + { + global $conf; + + $result = false; + + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog"; + $sql.= " WHERE entity = ".$conf->entity; + if ($ignoresystem) $sql.=" AND action not in ('MODULE_SET','MODULE_RESET')"; + $sql.= $this->db->plimit(1); + + $res = $this->db->query($sql); + if ($res!==false) + { + $obj = $this->db->fetch_object($res); + if ($obj) $result = true; + } + else dol_print_error($this->db); + + dol_syslog("Module Blockedlog alreadyUsed with ignoresystem=".$ignoresystem." is ".$result); + + return $result; + } + } diff --git a/htdocs/blockedlog/lib/blockedlog.lib.php b/htdocs/blockedlog/lib/blockedlog.lib.php index d377384f1c4..130ce9d19e0 100644 --- a/htdocs/blockedlog/lib/blockedlog.lib.php +++ b/htdocs/blockedlog/lib/blockedlog.lib.php @@ -28,7 +28,7 @@ */ function blockedlogadmin_prepare_head() { - global $langs, $conf; + global $db, $langs, $conf; $h = 0; $head = array(); @@ -40,6 +40,13 @@ function blockedlogadmin_prepare_head() $head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/blockedlog_list.php"; $head[$h][1] = $langs->trans("Fingerprints"); + + require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; + $b=new BlockedLog($db); + if ($b->alreadyUsed()) + { + $head[$h][1].=' ...'; + } $head[$h][2] = 'fingerprints'; $h++; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 61f85b88a12..01f064c3934 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -6127,15 +6127,15 @@ function dol_osencode($str) * Store also Code-Id into a cache to speed up next request on same key. * * @param DoliDB $db Database handler - * @param string $key Code or Id to get Id or Code + * @param string $key Code or Id to get Id or Code * @param string $tablename Table name without prefix - * @param string $fieldkey Field for code - * @param string $fieldid Field for id + * @param string $fieldkey Field to search the key into + * @param string $fieldid Field to get * @param int $entityfilter Filter by entity * @return int <0 if KO, Id of code if OK * @see $langs->getLabelFromKey */ -function dol_getIdFromCode($db,$key,$tablename,$fieldkey='code',$fieldid='id',$entityfilter=0) +function dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0) { global $cache_codes; diff --git a/htdocs/core/lib/usergroups.lib.php b/htdocs/core/lib/usergroups.lib.php index 6fe236d6b41..b8833e42543 100644 --- a/htdocs/core/lib/usergroups.lib.php +++ b/htdocs/core/lib/usergroups.lib.php @@ -224,7 +224,7 @@ function group_prepare_head($object) if ($canreadperms) { $head[$h][0] = DOL_URL_ROOT.'/user/group/perms.php?id='.$object->id; - $head[$h][1] = $langs->trans("GroupRights"); + $head[$h][1] = $langs->trans("GroupRights"). ' '.($object->nb_rights).''; $head[$h][2] = 'rights'; $h++; } @@ -267,7 +267,7 @@ function user_admin_prepare_head() $head[$h][2] = 'attributes'; $h++; - $head[$h][0] = DOL_URL_ROOT.'/user/admin/group_extrafields.php'; + $head[$h][0] = DOL_URL_ROOT.'/user/admin/group_extrafields.php'; $head[$h][1] = $langs->trans("ExtraFields")." ".$langs->trans("Groups"); $head[$h][2] = 'attributes_group'; $h++; diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 0155634ed25..c8fd99339e7 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -1666,7 +1666,7 @@ class DolibarrModules // Can not be abstract, because we need to insta $r_def = $this->rights[$key][3]; $r_perms = $this->rights[$key][4]; $r_subperms = isset($this->rights[$key][5])?$this->rights[$key][5]:''; - $r_modul = $this->rights_class; + $r_modul = empty($this->rights_class)?strtolower($this->name):$this->rights_class; if (empty($r_type)) $r_type='w'; diff --git a/htdocs/core/modules/modBlockedLog.class.php b/htdocs/core/modules/modBlockedLog.class.php index 95d1933cc89..56a9191866f 100644 --- a/htdocs/core/modules/modBlockedLog.class.php +++ b/htdocs/core/modules/modBlockedLog.class.php @@ -36,10 +36,12 @@ class modBlockedLog extends DolibarrModules */ function __construct($db) { - global $langs,$conf,$mysoc; + global $langs, $conf, $mysoc; $this->db = $db; $this->numero = 3200; + // Key text used to identify module (for permissions, menus, etc...) + $this->rights_class = 'blockedlog'; // Family can be 'crm','financial','hr','projects','products','ecm','technic','other' // It is used to group modules in module setup page @@ -77,17 +79,27 @@ class modBlockedLog extends DolibarrModules // Currently, activation is not automatic because only companies (in France) making invoices to non business customers must // enable this module. - // It is automatic only if $conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY is on. - if (! empty($conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY)) + /*if (! empty($conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY)) { - $this->automatic_activation = array('FR'=>'BlockedLogActivatedBecauseRequiredByYourCountryLegislation'); - } + $tmp=explode(',', $conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY); + $this->automatic_activation = array(); + foreach($tmp as $key) + { + $this->automatic_activation[$key]='BlockedLogActivatedBecauseRequiredByYourCountryLegislation'; + } + }*/ + //var_dump($this->automatic_activation); - $this->always_enabled = !empty($conf->blockedlog->enabled) && !empty($conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY) && in_array($mysoc->country_code, explode(',', $conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY)); + $this->always_enabled = (!empty($conf->blockedlog->enabled) + && !empty($conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY) + && in_array($mysoc->country_code, explode(',', $conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY)) + && $this->alreadyUsed(1)); // Constants //----------- - $this->const = array(); + $this->const = array( + 1=>array('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY', 'chaine', 'FR', 'This is list of country code where the module may be mandatory', 0, 'current', 0) + ); // New pages on tabs // ----------------- @@ -97,23 +109,76 @@ class modBlockedLog extends DolibarrModules //------ $this->boxes = array(); + // Permissions + $this->rights = array(); // Permission array used by this module + + $r=0; + $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) + $this->rights[$r][1] = 'Read archived events and fingerprints'; // Permission label + $this->rights[$r][3] = 0; // Permission by default for new user (0/1) + $this->rights[$r][4] = 'read'; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) + $this->rights[$r][5] = ''; + // Main menu entries //------------------ $this->menu = array(); } + /** * Check if module was already used before unactivation linked to warnings_unactivation property + * + * @return boolean True if already used, otherwise False */ function alreadyUsed() { - $res = $this->db->query("SELECT count(*) as nb FROM ".MAIN_DB_PREFIX."blockedlog"); - if($res!==false) { - $obj = $this->db->fetch_object($res); - return ($obj->nb > 0); + require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; + $b=new BlockedLog($this->db); + return $b->alreadyUsed(1); + } + + + /** + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories. + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + function init($options='') + { + global $conf, $user; + + $sql = array(); + + // If already used, we add an entry to show we enable module + require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; + + $object=new stdClass; + $object->id = 1; + $object->element = 'module'; + $object->ref = 'systemevent'; + $object->entity = $conf->entity; + $object->date = dol_now(); + + $b=new BlockedLog($this->db); + $result = $b->setObjectData($object, 'MODULE_SET', 0); + if ($result < 0) + { + $this->error = $b->error; + $this->errors = $b->erros; + return 0; } - return false; + $res = $b->create($user); + if ($res<=0) { + $this->error = $b->error; + $this->errors = $b->errors; + return $res; + } + + return $this->_init($sql, $options); } /** @@ -126,26 +191,43 @@ class modBlockedLog extends DolibarrModules */ function remove($options = '') { - global $user; + global $conf, $user; - require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; + $sql = array(); - $object=new stdClass; + // If already used, we add an entry to show we enable module + require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; + + $object=new stdClass; $object->id = 1; $object->element = 'module'; - $object->ref = 'module'; + $object->ref = 'systemevent'; + $object->entity = $conf->entity; $object->date = dol_now(); $b=new BlockedLog($this->db); - $b->setObjectData($object, 'MODULE_RESET', -1); - - $res = $b->create($user); - if($res<=0) { + $result = $b->setObjectData($object, 'MODULE_RESET', 0); + if ($result < 0) + { $this->error = $b->error; - return $res; + $this->errors = $b->erros; + return 0; } - return $this->_remove(array(), $options); + if ($b->alreadyUsed(1)) + { + $res = $b->create($user, '0000000000'); // If already used for something else than SET or UNSET, we log with error + } + else + { + $res = $b->create($user); + } + if ($res<=0) { + $this->error = $b->error; + $this->errors = $b->errors; + return $res; + } + return $this->_remove($sql, $options); } } diff --git a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php index 48ed23aba32..edb7772eb9c 100644 --- a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php +++ b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php @@ -56,15 +56,24 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); // Event/record is qualified - if ($action==='BILL_VALIDATE' || $action === 'BILL_PAYED' || $action==='BILL_UNPAYED' || $action==='BILL_DELETE' - || $action === 'BILL_SENTBYMAIL' || $action === 'DOC_DOWNLOAD' || $action === 'DOC_PREVIEW' - || $action === 'BILL_SUPPLIER_PAYED') + $qualified = 0; + if ($action==='BILL_VALIDATE' || $action==='BILL_DELETE' || $action === 'BILL_SENTBYMAIL' + || (in_array($object->element, array('facture','suplier_invoice')) && $action === 'DOC_DOWNLOAD') || (in_array($object->element, array('facture','suplier_invoice')) && $action === 'DOC_PREVIEW') + ) { + $qualified++; $amounts= (double) $object->total_ttc; } - else if ($action === 'PAYMENT_CUSTOMER_CREATE' || $action === 'PAYMENT_SUPPLIER_CREATE' + /*if ($action === 'BILL_PAYED' || $action==='BILL_UNPAYED' + || $action === 'BILL_SUPPLIER_PAYED' || $action === 'BILL_SUPPLIER_UNPAYED') + { + $qualified++; + $amounts= (double) $object->total_ttc; + }*/ + if ($action === 'PAYMENT_CUSTOMER_CREATE' || $action === 'PAYMENT_SUPPLIER_CREATE' || $action === 'PAYMENT_CUSTOMER_DELETE' || $action === 'PAYMENT_SUPPLIER_DELETE') // 'PAYMENT_ADD_TO_BANK' { + $qualified++; $amounts = 0; if(!empty($object->amounts)) { foreach($object->amounts as $amount) { @@ -72,22 +81,32 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers } } } - else if (strpos($action,'PAYMENT')!==false && ! in_array($action, array('PAYMENT_ADD_TO_BANK'))) { + if (strpos($action,'PAYMENT')!==false && ! in_array($action, array('PAYMENT_ADD_TO_BANK'))) + { + $qualified++; $amounts= (double) $object->amount; } - else { + + if (! $qualified) + { return 0; // not implemented action log } $b=new BlockedLog($this->db); - $b->setObjectData($object, $action, $amounts); // Set field date_object, ref_object, fk_object, element, object_data + $result = $b->setObjectData($object, $action, $amounts); // Set field date_object, ref_object, fk_object, element, object_data + if ($result < 0) + { + $this->error = $b->error; + $this->errors = $b->erros; + return -1; + } $res = $b->create($user); if ($res<0) { - setEventMessage($b->error,'errors'); + setEventMessages($b->error, $b->errors, 'errors'); return -1; } else diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 1a486cb34af..4e4269e3699 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -380,7 +380,9 @@ if (! GETPOST('action','aZ09') || preg_match('/upgrade/i',GETPOST('action','aZ09 if (versioncompare($versiontoarray,$afterversionarray) >= 0 && versioncompare($versiontoarray,$beforeversionarray) <= 0) { // Migrate contact association - migrate_event_assignement_contact($db,$langs,$conf); + migrate_event_assignement_contact($db,$langs,$conf); + + migrate_reset_blocked_log($db,$langs,$conf); } } @@ -3872,6 +3874,125 @@ function migrate_event_assignement_contact($db,$langs,$conf) print ''; } + +/** + * Migrate to reset the blocked log for V7+ algorithm + * + * @param DoliDB $db Database handler + * @param Translate $langs Object langs + * @param Conf $conf Object conf + * @return void + */ +function migrate_reset_blocked_log($db,$langs,$conf) +{ + require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; + + print ''; + + print '
'; + print ''.$langs->trans('MigrationResetBlockedLog')."
\n"; + + $error = 0; + + dolibarr_install_syslog("upgrade2::migrate_reset_blocked_log"); + + $db->begin(); + + $sqlSelect = "SELECT DISTINCT entity"; + $sqlSelect.= " FROM ".MAIN_DB_PREFIX."blockedlog"; + + //print $sqlSelect; + + $resql = $db->query($sqlSelect); + if ($resql) + { + $i = 0; + $num = $db->num_rows($resql); + + if ($num) + { + while ($i < $num) + { + $obj = $db->fetch_object($resql); + + print 'Process entity '.$obj->entity; + + $sqlSearch = "SELECT count(rowid) as nb FROM ".MAIN_DB_PREFIX."blockedlog WHERE action = 'MODULE_SET' and entity = ".$obj->entity; + $resqlSearch = $db->query($sqlSearch); + if ($resqlSearch) + { + $objSearch = $db->fetch_object($resqlSearch); + //var_dump($objSearch); + if ($objSearch && $objSearch->nb == 0) + { + print ' - Record for entity must be reset...'; + + $sqlUpdate = "DELETE FROM ".MAIN_DB_PREFIX."blockedlog"; + $sqlUpdate.= " WHERE entity = " . $obj->entity; + $resqlUpdate=$db->query($sqlUpdate); + if (! $resqlUpdate) + { + $error++; + dol_print_error($db); + } + else + { + // Add set line + $object=new stdClass; + $object->id = 1; + $object->element = 'module'; + $object->ref = 'systemevent'; + $object->entity = $obj->entity; + $object->date = dol_now(); + + $b=new BlockedLog($this->db); + $b->setObjectData($object, 'MODULE_SET', 0); + + $res = $b->create($user); + if ($res<=0) { + $this->error = $b->error; + $this->errors = $b->errors; + $error++; + } + } + } + else + { + print ' - '.$langs->trans('AlreadyInV7'); + } + } + else + { + dol_print_error($db); + } + + $i++; + } + } + else + { + print $langs->trans('NothingToDo')."
\n"; + } + + if (! $error) + { + $db->commit(); + } + else + { + $db->rollback(); + } + } + else + { + dol_print_error($db); + $db->rollback(); + } + + print ''; +} + + /** * Migrate to add entity value into llx_societe_remise * @@ -3946,7 +4067,6 @@ function migrate_remise_entity($db,$langs,$conf) $db->rollback(); } - print ''; } diff --git a/htdocs/langs/en_US/blockedlog.lang b/htdocs/langs/en_US/blockedlog.lang index 5b455fdd7b4..ca99d42a6bf 100644 --- a/htdocs/langs/en_US/blockedlog.lang +++ b/htdocs/langs/en_US/blockedlog.lang @@ -2,7 +2,7 @@ BlockedLog=Unalterable Logs Field=Field BlockedLogDesc=This module tracks some events into an unalterable log (that you can't modify once recorded) into a block chain, in real time. This module provides compatibility with requirements of laws of some countries (like France with the law Fincance 2016 - Norme NF535). Fingerprints=Archived events and fingerprints -FingerprintsDesc=Archived business events and fingerprints +FingerprintsDesc=This is the tool to browser the unalterable logs CompanyInitialKey=Company initial key (hash of genesis block) ShowAllFingerPrintsMightBeTooLong=Show all archived logs (might be long) ShowAllFingerPrintsErrorsMightBeTooLong=Show all archive logs with error (might be long) @@ -21,6 +21,8 @@ logBILL_UNPAYED=Customer bill set unpayed logBILL_VALIDATE=Customer bill validated logBILL_SENTBYMAIL=Customer bill send by mail logBILL_DELETE=Customer bill deleted +logMODULE_RESET=Module BlockedLog was disabled +logMODULE_SET=Module BlockedLog was enabled BlockedlogInfoDialog=Log Details Fingerprint=Fingerprint DownloadLogCSV=Download archive logs (CSV) @@ -30,4 +32,4 @@ DataOfArchivedEvent=Full datas of archived event ImpossibleToReloadObject=Object (type %s, id %s) removed (see 'Full data' link for unerasable saved data) BlockedLogAreRequiredByYourCountryLegislation=Unalterable Logs module may be required by the legislation of your country. Disabling this module may render any future transactions invalid with respect to the law and the use of legal software as they can not be validated by a tax audit. BlockedLogActivatedBecauseRequiredByYourCountryLegislation=Unalterable Logs module was activated because of the legislation of your country. Disabling this module may render any future transactions invalid with respect to the law and the use of legal software as they can not be validated by a tax audit. -BlockedLogDisableNotAllowedForCountry=Disable not allowed for this countries (just to prevent to disable the module by error, if your country is...) \ No newline at end of file +BlockedLogDisableNotAllowedForCountry=List of countries where usage of this module is mandatory (just to prevent to disable the module by error, if your country is in this list, disable of module is not possible without editing this list first) \ No newline at end of file diff --git a/htdocs/langs/en_US/install.lang b/htdocs/langs/en_US/install.lang index 7204938098b..87ef7d79b13 100644 --- a/htdocs/langs/en_US/install.lang +++ b/htdocs/langs/en_US/install.lang @@ -141,6 +141,7 @@ KeepDefaultValuesProxmox=You use the Dolibarr setup wizard from a Proxmox virtua UpgradeExternalModule=Run dedicated upgrade process of external modules SetAtLeastOneOptionAsUrlParameter=Set at least one option as a parameter in URL. For example: '...repair.php?standard=confirmed' NothingToDelete=Nothing to clean/delete +NothingToDo=Nothing to do ######### # upgrade MigrationFixData=Fix for denormalized data @@ -196,6 +197,7 @@ MigrationEventsContact=Migration of events to add event contact into assignement MigrationRemiseEntity=Update entity field value of llx_societe_remise MigrationRemiseExceptEntity=Update entity field value of llx_societe_remise_except MigrationReloadModule=Reload module %s +MigrationResetBlockedLog=Reset module BlockedLog for v7 algorithm ShowNotAvailableOptions=Show not available options HideNotAvailableOptions=Hide not available options ErrorFoundDuringMigration=Error were reported during migration process so next step is not available. To ignore errors, you can click here, but application or some features may not work correctly until fixed. diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index dd489b5b491..0dba5024136 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -299,12 +299,12 @@ class modMyModule extends DolibarrModules } /** - * Function called when module is enabled. - * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. - * It also creates data directories + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories * - * @param string $options Options when enabling module ('', 'noboxes') - * @return int 1 if OK, 0 if KO + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO */ public function init($options='') { @@ -326,12 +326,12 @@ class modMyModule extends DolibarrModules } /** - * Function called when module is disabled. - * Remove from database constants, boxes and permissions from Dolibarr database. - * Data directories are not deleted + * Function called when module is disabled. + * Remove from database constants, boxes and permissions from Dolibarr database. + * Data directories are not deleted * - * @param string $options Options when enabling module ('', 'noboxes') - * @return int 1 if OK, 0 if KO + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO */ public function remove($options = '') { diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index b33ab447592..7d0c5a7d26c 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -102,6 +102,7 @@ if ($user->societe_id > 0) //$socid = $user->societe_id; accessforbidden(); } +//$result = restrictedArea($user, 'mymodule', $id,''); // Initialize array of search criterias $search_all=trim(GETPOST("search_all",'alpha')); diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index c8a9a141aeb..5a103871058 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -727,19 +727,21 @@ class User extends CommonObject if ($perms) { if (! isset($this->rights) || ! is_object($this->rights)) $this->rights = new stdClass(); // For avoid error - if (! isset($this->rights->$module) || ! is_object($this->rights->$module)) $this->rights->$module = new stdClass(); - if ($subperms) + if ($module) { - if (! isset($this->rights->$module->$perms) || ! is_object($this->rights->$module->$perms)) $this->rights->$module->$perms = new stdClass(); - if(empty($this->rights->$module->$perms->$subperms)) $this->nb_rights++; - $this->rights->$module->$perms->$subperms = 1; + if (! isset($this->rights->$module) || ! is_object($this->rights->$module)) $this->rights->$module = new stdClass(); + if ($subperms) + { + if (! isset($this->rights->$module->$perms) || ! is_object($this->rights->$module->$perms)) $this->rights->$module->$perms = new stdClass(); + if(empty($this->rights->$module->$perms->$subperms)) $this->nb_rights++; + $this->rights->$module->$perms->$subperms = 1; + } + else + { + if(empty($this->rights->$module->$perms)) $this->nb_rights++; + $this->rights->$module->$perms = 1; + } } - else - { - if(empty($this->rights->$module->$perms)) $this->nb_rights++; - $this->rights->$module->$perms = 1; - } - } $i++; } diff --git a/htdocs/user/class/usergroup.class.php b/htdocs/user/class/usergroup.class.php index f16af4a4c48..f2ca661681f 100644 --- a/htdocs/user/class/usergroup.class.php +++ b/htdocs/user/class/usergroup.class.php @@ -50,6 +50,8 @@ class UserGroup extends CommonObject public $datem; // Modification date of group public $members=array(); // Array of users + public $nb_rights; // Number of rights granted to the user + private $_tab_loaded=array(); // Array of cache of already loaded permissions public $oldcopy; // To contains a clone of this when we need to save old properties of object @@ -63,6 +65,7 @@ class UserGroup extends CommonObject function __construct($db) { $this->db = $db; + $this->nb_rights = 0; return 0; } @@ -536,10 +539,12 @@ class UserGroup extends CommonObject if ($subperms) { if (! isset($this->rights->$module->$perms) || ! is_object($this->rights->$module->$perms)) $this->rights->$module->$perms = new stdClass(); + if(empty($this->rights->$module->$perms->$subperms)) $this->nb_rights++; $this->rights->$module->$perms->$subperms = 1; } else { + if(empty($this->rights->$module->$perms)) $this->nb_rights++; $this->rights->$module->$perms = 1; } } diff --git a/htdocs/user/group/card.php b/htdocs/user/group/card.php index 1b7be0b0a17..5a68dd1391b 100644 --- a/htdocs/user/group/card.php +++ b/htdocs/user/group/card.php @@ -60,6 +60,11 @@ if (! empty($conf->multicompany->enabled) && $conf->entity > 1 && $conf->global- } $object = new Usergroup($db); +if ($id > 0) +{ + $object->fetch($id); + $object->getrights(); +} $extrafields = new ExtraFields($db); // fetch optionals attributes and labels diff --git a/htdocs/user/group/perms.php b/htdocs/user/group/perms.php index 6c9e7d3966b..3b6d7037229 100644 --- a/htdocs/user/group/perms.php +++ b/htdocs/user/group/perms.php @@ -56,7 +56,6 @@ if (! $canreadperms) accessforbidden(); $object = new Usergroup($db); $object->fetch($id); -$object->getrights(); $entity=$conf->entity; @@ -73,19 +72,26 @@ $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 (empty($reshook)) +{ if ($action == 'addrights' && $caneditperms) { $editgroup = new Usergroup($db); $result=$editgroup->fetch($id); - if ($result > 0) $editgroup->addrights($rights, $module, '', $entity); + if ($result > 0) + { + $editgroup->addrights($rights, $module, '', $entity); + } } if ($action == 'delrights' && $caneditperms) { $editgroup = new Usergroup($db); $result=$editgroup->fetch($id); - if ($result > 0) $editgroup->delrights($rights, $module, '', $entity); + if ($result > 0) + { + $editgroup->delrights($rights, $module, '', $entity); + } } } @@ -98,11 +104,13 @@ $form = new Form($db); llxHeader('',$langs->trans("Permissions")); -if ($object->id) +if ($object->id > 0) { - /* + /* * Affichage onglets */ + $object->getrights(); // Reload permission + $head = group_prepare_head($object); $title = $langs->trans("Group"); dol_fiche_head($head, 'rights', $title, -1, 'group'); @@ -239,7 +247,6 @@ if ($object->id) if ($result) { $i = 0; - $var = true; $oldmod = ''; $num = $db->num_rows($result); @@ -258,31 +265,30 @@ if ($object->id) if ($oldmod <> $obj->module) { $oldmod = $obj->module; - $var = !$var; // Rupture detectee, on recupere objMod $objMod = $modules[$obj->module]; $picto=($objMod->picto?$objMod->picto:'generic'); + print ''; + print ''.img_object('', $picto, 'class="inline-block pictoobjectwidth"').' '.$objMod->getName(); + print ' '; + print ''; if ($caneditperms) { - print ''; - print ''.img_object('',$picto).' '.$objMod->getName(); - print ' '; - print ''; - print 'module.'#'.$objMod->getName().'">'.$langs->trans("All").""; + print 'module.'#'.$objMod->getName().'">'.$langs->trans("All").""; print '/'; print 'module.'#'.$objMod->getName().'">'.$langs->trans("None").""; - print ''; - print ' '; - print ''; } + print ''; + print ' '; + print ''; } - print ''; + print ''; // Module - print ''.img_object('',$picto).' '.$objMod->getName().''; + print ''.img_object('', $picto, 'class="inline-block pictoobjectwidth"').' '.$objMod->getName().''; if (is_array($permsgroupbyentity[$entity])) { diff --git a/htdocs/user/perms.php b/htdocs/user/perms.php index e523d01009f..b83a6831053 100644 --- a/htdocs/user/perms.php +++ b/htdocs/user/perms.php @@ -282,7 +282,6 @@ if ($result) { $num = $db->num_rows($result); $i = 0; - $var = True; $oldmod=''; while ($i < $num) @@ -295,39 +294,37 @@ if ($result) $i++; continue; } - if (isset($obj->module) && ($oldmod <> $obj->module)) { $oldmod = $obj->module; - $var = !$var; - // Rupture detectee, on recupere objMod + // Break detected, we get objMod $objMod=$modules[$obj->module]; $picto=($objMod->picto?$objMod->picto:'generic'); - if ($caneditperms && (empty($objMod->rights_admin_allowed) || empty($object->admin))) - { - // On affiche ligne pour modifier droits - print ''; - print ''.img_object('',$picto,'class="pictoobjectwidth"').' '.$objMod->getName(); - print ''; - print ''; - print 'module.'">'.$langs->trans("All").""; - print '/'; - print 'module.'">'.$langs->trans("None").""; - print ''; - print ' '; - print ''."\n"; - } + // Show break line + print ''; + print ''.img_object('',$picto,'class="pictoobjectwidth"').' '.$objMod->getName(); + print ''; + print ''; + if ($caneditperms && empty($objMod->rights_admin_allowed) || empty($object->admin)) + { + print 'module.'">'.$langs->trans("All").""; + print '/'; + print 'module.'">'.$langs->trans("None").""; + } + print ''; + print ' '; + print ''."\n"; } - print ''; + print ''; // Picto and label of permission print ''.img_object('',$picto,'class="pictoobjectwidth"').' '.$objMod->getName().''; // Permission and tick - if (! empty($object->admin) && ! empty($objMod->rights_admin_allowed)) // Permission own because admin + if (! empty($object->admin) && ! empty($objMod->rights_admin_allowed)) // Permission granted because admin { if ($caneditperms) { @@ -337,7 +334,7 @@ if ($result) print img_picto($langs->trans("Active"),'tick'); print ''; } - else if (in_array($obj->id, $permsuser)) // Permission own by user + else if (in_array($obj->id, $permsuser)) // Permission granted by user { if ($caneditperms) { @@ -350,7 +347,7 @@ if ($result) else if (is_array($permsgroupbyentity[$entity])) { - if (in_array($obj->id, $permsgroupbyentity[$entity])) // Permission own by group + if (in_array($obj->id, $permsgroupbyentity[$entity])) // Permission granted by group { if ($caneditperms) { From 5ae13ea9d6d0f933e01abf7dd4614b721daaef66 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Dec 2017 17:05:01 +0100 Subject: [PATCH 05/27] Fix navigation in bank direct debit orders --- htdocs/compta/prelevement/card.php | 19 ++++--------------- .../class/bonprelevement.class.php | 5 +++-- htdocs/compta/prelevement/factures.php | 2 +- htdocs/compta/prelevement/fiche-rejet.php | 4 ++-- htdocs/compta/prelevement/fiche-stat.php | 6 +++--- 5 files changed, 13 insertions(+), 23 deletions(-) diff --git a/htdocs/compta/prelevement/card.php b/htdocs/compta/prelevement/card.php index 97f5d96903f..92799c2cd10 100644 --- a/htdocs/compta/prelevement/card.php +++ b/htdocs/compta/prelevement/card.php @@ -63,6 +63,9 @@ if (! $sortorder) $sortorder='DESC'; $object = new BonPrelevement($db,""); +// 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 + /* * Actions @@ -70,9 +73,7 @@ $object = new BonPrelevement($db,""); if ( $action == 'confirm_delete' ) { - $object->fetch($id, $ref); - - $res=$object->delete(); + $res=$object->delete($user); if ($res > 0) { header("Location: index.php"); @@ -83,8 +84,6 @@ if ( $action == 'confirm_delete' ) // Seems to no be used and replaced with $action == 'infocredit if ( $action == 'confirm_credite' && GETPOST('confirm','alpha') == 'yes') { - $object->fetch($id, $ref); - $res=$object->set_credite(); if ($res >= 0) { @@ -97,8 +96,6 @@ if ($action == 'infotrans' && $user->rights->prelevement->bons->send) { require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; - $object->fetch($id, $ref); - $dt = dol_mktime(12,0,0,GETPOST('remonth','int'),GETPOST('reday','int'),GETPOST('reyear','int')); /* @@ -132,7 +129,6 @@ if ($action == 'infotrans' && $user->rights->prelevement->bons->send) // Set direct debit order to credited, create payment and close invoices if ($action == 'infocredit' && $user->rights->prelevement->bons->credit) { - $object->fetch($id, $ref); $dt = dol_mktime(12,0,0,GETPOST('remonth','int'),GETPOST('reday','int'),GETPOST('reyear','int')); $error = $object->set_infocredit($user, $dt); @@ -156,8 +152,6 @@ llxHeader('',$langs->trans("WithdrawalsReceipts")); if ($id > 0 || $ref) { - $object->fetch($id, $ref); - $head = prelevement_prepare_head($object); dol_fiche_head($head, 'prelevement', $langs->trans("WithdrawalsReceipts"), -1, 'payment'); @@ -414,13 +408,8 @@ if ($id > 0 || $ref) { dol_print_error($db); } - - - - } - llxFooter(); $db->close(); diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php index 188b0236e5f..d829a7c5ada 100644 --- a/htdocs/compta/prelevement/class/bonprelevement.class.php +++ b/htdocs/compta/prelevement/class/bonprelevement.class.php @@ -313,7 +313,7 @@ class BonPrelevement extends CommonObject $this->_fetched = 1; - return 0; + return 1; } else { @@ -1110,9 +1110,10 @@ class BonPrelevement extends CommonObject /** * Get object and lines from database * + * @param User $user Object user that delete * @return int >0 if OK, <0 if KO */ - function delete() + function delete($user=null) { $this->db->begin(); diff --git a/htdocs/compta/prelevement/factures.php b/htdocs/compta/prelevement/factures.php index 60215005446..6cc82869966 100644 --- a/htdocs/compta/prelevement/factures.php +++ b/htdocs/compta/prelevement/factures.php @@ -71,7 +71,7 @@ llxHeader('',$langs->trans("WithdrawalsReceipts")); if ($prev_id > 0 || $ref) { - if ($object->fetch($prev_id, $ref) == 0) + if ($object->fetch($prev_id, $ref) >= 0) { $head = prelevement_prepare_head($object); dol_fiche_head($head, 'invoices', $langs->trans("WithdrawalsReceipts"), -1, 'payment'); diff --git a/htdocs/compta/prelevement/fiche-rejet.php b/htdocs/compta/prelevement/fiche-rejet.php index f4cb8040a6f..9489eeec4e9 100644 --- a/htdocs/compta/prelevement/fiche-rejet.php +++ b/htdocs/compta/prelevement/fiche-rejet.php @@ -63,7 +63,7 @@ llxHeader('',$langs->trans("WithdrawalsReceipts")); if ($prev_id > 0 || $ref) { - if ($object->fetch($prev_id, $ref) == 0) + if ($object->fetch($prev_id, $ref) >= 0) { $head = prelevement_prepare_head($object); dol_fiche_head($head, 'rejects', $langs->trans("WithdrawalsReceipts"), -1, 'payment'); @@ -152,7 +152,7 @@ $sql.= " FROM ".MAIN_DB_PREFIX."prelevement_bons as p"; $sql.= " , ".MAIN_DB_PREFIX."prelevement_lignes as pl"; $sql.= " , ".MAIN_DB_PREFIX."societe as s"; $sql.= " , ".MAIN_DB_PREFIX."prelevement_rejet as pr"; -$sql.= " WHERE p.rowid=".$prev_id; +$sql.= " WHERE p.rowid=".$object->id; $sql.= " AND pl.fk_prelevement_bons = p.rowid"; $sql.= " AND p.entity = ".$conf->entity; $sql.= " AND pl.fk_soc = s.rowid"; diff --git a/htdocs/compta/prelevement/fiche-stat.php b/htdocs/compta/prelevement/fiche-stat.php index a5583dffa6d..539331d1f71 100644 --- a/htdocs/compta/prelevement/fiche-stat.php +++ b/htdocs/compta/prelevement/fiche-stat.php @@ -58,9 +58,9 @@ $object = new BonPrelevement($db,""); llxHeader('',$langs->trans("WithdrawalsReceipts")); -if ($prev_id) +if ($prev_id > 0 || $ref) { - if ($object->fetch($prev_id) == 0) + if ($object->fetch($prev_id, $ref) >= 0) { $head = prelevement_prepare_head($object); dol_fiche_head($head, 'statistics', $langs->trans("WithdrawalsReceipts"), -1, 'payment'); @@ -144,7 +144,7 @@ if ($prev_id) $sql = "SELECT sum(pl.amount), pl.statut"; $sql.= " FROM ".MAIN_DB_PREFIX."prelevement_lignes as pl"; - $sql.= " WHERE pl.fk_prelevement_bons = ".$prev_id; + $sql.= " WHERE pl.fk_prelevement_bons = ".$object->id; $sql.= " GROUP BY pl.statut"; $resql=$db->query($sql); From 1a3fbc092d651ac68ccd2a6b3f4e443c5527978d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Dec 2017 17:07:32 +0100 Subject: [PATCH 06/27] Fix method not found --- htdocs/admin/modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 18546d67dc1..747a3cd41c3 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -691,7 +691,7 @@ if ($mode == 'common') } else if (! empty($objMod->always_enabled) || ((! empty($conf->multicompany->enabled) && $objMod->core_enabled) && ($user->entity || $conf->entity!=1))) { - if ($objMod->alreadyUsed()) print $langs->trans("Used"); + if (method_exists($objMod, 'alreadyUsed') && $objMod->alreadyUsed()) print $langs->trans("Used"); else print $langs->trans("Required"); if (! empty($conf->multicompany->enabled) && $user->entity) $disableSetup++; } From e774beffc3374e5c67169ffa8adac889a8a1e177 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Dec 2017 17:17:35 +0100 Subject: [PATCH 07/27] Fix the symbol of Yuan must be before amount --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 01f064c3934..6b563dab8b3 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -4026,7 +4026,7 @@ function price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerou { if ($currency_code == 'auto') $currency_code=$conf->currency; - $listofcurrenciesbefore=array('USD','GBP','AUD','MXN','PEN'); + $listofcurrenciesbefore=array('USD','GBP','AUD','MXN','PEN','CNY'); if (in_array($currency_code,$listofcurrenciesbefore)) $cursymbolbefore.=$outlangs->getCurrencySymbol($currency_code); else { From 8bb89f6bf494dd3736f9cfec60d71bee4ba4a43a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Dec 2017 17:24:36 +0100 Subject: [PATCH 08/27] Fix look and feel v6 --- htdocs/compta/prelevement/card.php | 4 +++- htdocs/compta/prelevement/factures.php | 4 +++- htdocs/compta/prelevement/fiche-rejet.php | 4 +++- htdocs/compta/prelevement/fiche-stat.php | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/htdocs/compta/prelevement/card.php b/htdocs/compta/prelevement/card.php index 92799c2cd10..a61f1fef8dc 100644 --- a/htdocs/compta/prelevement/card.php +++ b/htdocs/compta/prelevement/card.php @@ -166,7 +166,9 @@ if ($id > 0 || $ref) }*/ - dol_banner_tab($object, 'ref', '', 1, 'ref', 'ref'); + $linkback = ''.$langs->trans("BackToList").''; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref'); print '
'; print '
'; diff --git a/htdocs/compta/prelevement/factures.php b/htdocs/compta/prelevement/factures.php index 6cc82869966..c829b139436 100644 --- a/htdocs/compta/prelevement/factures.php +++ b/htdocs/compta/prelevement/factures.php @@ -76,7 +76,9 @@ if ($prev_id > 0 || $ref) $head = prelevement_prepare_head($object); dol_fiche_head($head, 'invoices', $langs->trans("WithdrawalsReceipts"), -1, 'payment'); - dol_banner_tab($object, 'ref', '', 1, 'ref', 'ref'); + $linkback = ''.$langs->trans("BackToList").''; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref'); print '
'; print '
'; diff --git a/htdocs/compta/prelevement/fiche-rejet.php b/htdocs/compta/prelevement/fiche-rejet.php index 9489eeec4e9..82431e3bdd2 100644 --- a/htdocs/compta/prelevement/fiche-rejet.php +++ b/htdocs/compta/prelevement/fiche-rejet.php @@ -68,7 +68,9 @@ if ($prev_id > 0 || $ref) $head = prelevement_prepare_head($object); dol_fiche_head($head, 'rejects', $langs->trans("WithdrawalsReceipts"), -1, 'payment'); - dol_banner_tab($object, 'ref', '', 1, 'ref', 'ref'); + $linkback = ''.$langs->trans("BackToList").''; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref'); print '
'; print '
'; diff --git a/htdocs/compta/prelevement/fiche-stat.php b/htdocs/compta/prelevement/fiche-stat.php index 539331d1f71..f0e335da5cf 100644 --- a/htdocs/compta/prelevement/fiche-stat.php +++ b/htdocs/compta/prelevement/fiche-stat.php @@ -65,7 +65,9 @@ if ($prev_id > 0 || $ref) $head = prelevement_prepare_head($object); dol_fiche_head($head, 'statistics', $langs->trans("WithdrawalsReceipts"), -1, 'payment'); - dol_banner_tab($object, 'ref', '', 1, 'ref', 'ref'); + $linkback = ''.$langs->trans("BackToList").''; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref'); print '
'; print '
'; From ebdbddb7fd0d953889de8796bb48ca60a2b72eb1 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Dec 2017 19:50:39 +0100 Subject: [PATCH 09/27] Fix error message and migration --- htdocs/install/mysql/migration/6.0.0-7.0.0.sql | 12 ++++++++++++ htdocs/langs/en_US/projects.lang | 1 + htdocs/projet/activity/perday.php | 2 +- htdocs/projet/activity/perweek.php | 6 +++--- 4 files changed, 17 insertions(+), 4 deletions(-) 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 bf49e8730fb..07bbee53987 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 @@ -615,3 +615,15 @@ ALTER TABLE llx_resource ADD fk_country integer DEFAULT NULL; ALTER TABLE llx_resource ADD INDEX idx_resource_fk_country (fk_country); ALTER TABLE llx_resource ADD CONSTRAINT fk_resource_fk_country FOREIGN KEY (fk_country) REFERENCES llx_c_country (rowid); + + +CREATE TABLE llx_projet_task_comment ( + rowid integer AUTO_INCREMENT PRIMARY KEY, + datec datetime DEFAULT NULL, + tms timestamp, + description text NOT NULL, + fk_user integer DEFAULT NULL, + fk_task integer DEFAULT NULL, + entity integer DEFAULT 1, + import_key varchar(125) DEFAULT NULL +) ENGINE=innodb; diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 7075f45ecd2..48bd55a41ee 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -215,6 +215,7 @@ AllowToLinkFromOtherCompany=Allow to link project from other company

S LatestProjects=Latest %s projects LatestModifiedProjects=Latest %s modified projects OtherFilteredTasks=Other filtered tasks +NoAssignedTasks=No assigned tasks (assign yourself project/tasks from the top select box to enter time on it) # Comments trans AllowCommentOnTask=Allow user comments on tasks AllowCommentOnProject=Allow user comments on projects diff --git a/htdocs/projet/activity/perday.php b/htdocs/projet/activity/perday.php index eb710ce62a2..e3e5a2a4efb 100644 --- a/htdocs/projet/activity/perday.php +++ b/htdocs/projet/activity/perday.php @@ -568,7 +568,7 @@ if (count($tasksarray) > 0) } else { - print ''.$langs->trans("NoTasks").''; + print ''.$langs->trans("NoAssignedTasks").''; } print ""; print '
'; diff --git a/htdocs/projet/activity/perweek.php b/htdocs/projet/activity/perweek.php index 97574ef53b9..023ccd611dd 100644 --- a/htdocs/projet/activity/perweek.php +++ b/htdocs/projet/activity/perweek.php @@ -332,10 +332,10 @@ if ($search_task_ref) $morewherefilter.=natural_search("t.ref", $search_task_r if ($search_task_label) $morewherefilter.=natural_search(array("t.ref", "t.label"), $search_task_label); if ($search_thirdparty) $morewherefilter.=natural_search("s.nom", $search_thirdparty); -$tasksarray=$taskstatic->getTasksArray(0, 0, ($project->id?$project->id:0), $socid, 0, $search_project_ref, $onlyopenedproject, $morewherefilter, ($search_usertoprocessid?$search_usertoprocessid:0)); // We want to see all task of opened project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later. +$tasksarray=$taskstatic->getTasksArray(0, 0, ($project->id?$project->id:0), $socid, 0, $search_project_ref, $onlyopenedproject, $morewherefilter, ($search_usertoprocessid?$search_usertoprocessid:0)); // We want to see all tasks of open project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later. if ($morewherefilter) // Get all task with no filter so we can show total of time spent for not visible tasks { - $tasksarraywithoutfilter=$taskstatic->getTasksArray(0, 0, ($project->id?$project->id:0), $socid, 0, '', $onlyopenedproject, '', ($search_usertoprocessid?$search_usertoprocessid:0)); // We want to see all task of opened project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later. + $tasksarraywithoutfilter=$taskstatic->getTasksArray(0, 0, ($project->id?$project->id:0), $socid, 0, '', $onlyopenedproject, '', ($search_usertoprocessid?$search_usertoprocessid:0)); // We want to see all tasks of open project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later. } $projectsrole=$taskstatic->getUserRolesForProjectsOrTasks($usertoprocess, 0, ($project->id?$project->id:0), 0, $onlyopenedproject); $tasksrole=$taskstatic->getUserRolesForProjectsOrTasks(0, $usertoprocess, ($project->id?$project->id:0), 0, $onlyopenedproject); @@ -595,7 +595,7 @@ if (count($tasksarray) > 0) } else { - print ''.$langs->trans("NoTasks").''; + print ''.$langs->trans("NoAssignedTasks").''; } print ""; print '
'; From db91a88c59110af20ec7056bc18627b7427c569f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Dec 2017 19:53:41 +0100 Subject: [PATCH 10/27] Fix error message and migration --- .../install/mysql/migration/6.0.0-7.0.0.sql | 24 ++++--------------- 1 file changed, 5 insertions(+), 19 deletions(-) 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 07bbee53987..7c9b0f3326e 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 @@ -452,19 +452,17 @@ insert into llx_c_action_trigger (code,label,description,elementtype,rang) value insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROPOSAL_SUPPLIER_CLOSE_SIGNED','Price request closed signed','Executed when a customer proposal is closed signed','proposal_supplier',10); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROPOSAL_SUPPLIER_CLOSE_REFUSED','Price request closed refused','Executed when a customer proposal is closed refused','proposal_supplier',10); -DROP TABLE llx_projet_task_comment; - -CREATE TABLE llx_comment ( +CREATE TABLE llx_projet_task_comment ( rowid integer AUTO_INCREMENT PRIMARY KEY, datec datetime DEFAULT NULL, tms timestamp, description text NOT NULL, - fk_user_author integer DEFAULT NULL, - fk_element integer DEFAULT NULL, - element_type varchar(50) DEFAULT NULL, + fk_user integer DEFAULT NULL, + fk_task integer DEFAULT NULL, entity integer DEFAULT 1, import_key varchar(125) DEFAULT NULL -)ENGINE=innodb; +) ENGINE=innodb; + DELETE FROM llx_const where name = __ENCRYPT('MAIN_SHOW_WORKBOARD')__; @@ -615,15 +613,3 @@ ALTER TABLE llx_resource ADD fk_country integer DEFAULT NULL; ALTER TABLE llx_resource ADD INDEX idx_resource_fk_country (fk_country); ALTER TABLE llx_resource ADD CONSTRAINT fk_resource_fk_country FOREIGN KEY (fk_country) REFERENCES llx_c_country (rowid); - - -CREATE TABLE llx_projet_task_comment ( - rowid integer AUTO_INCREMENT PRIMARY KEY, - datec datetime DEFAULT NULL, - tms timestamp, - description text NOT NULL, - fk_user integer DEFAULT NULL, - fk_task integer DEFAULT NULL, - entity integer DEFAULT 1, - import_key varchar(125) DEFAULT NULL -) ENGINE=innodb; From 929893bd49daf1ae587d46b7995cd217419ce766 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Dec 2017 20:07:35 +0100 Subject: [PATCH 11/27] Fix regression introduced with task comments --- htdocs/install/mysql/migration/6.0.0-7.0.0.sql | 12 +++++++----- .../{llx_projet_task_comment.sql => llx_comment.sql} | 10 ++++++---- htdocs/projet/class/project.class.php | 8 +++++++- htdocs/projet/class/task.class.php | 2 +- htdocs/projet/comment.php | 1 - 5 files changed, 21 insertions(+), 12 deletions(-) rename htdocs/install/mysql/tables/{llx_projet_task_comment.sql => llx_comment.sql} (86%) 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 7c9b0f3326e..bf49e8730fb 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 @@ -452,17 +452,19 @@ insert into llx_c_action_trigger (code,label,description,elementtype,rang) value insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROPOSAL_SUPPLIER_CLOSE_SIGNED','Price request closed signed','Executed when a customer proposal is closed signed','proposal_supplier',10); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROPOSAL_SUPPLIER_CLOSE_REFUSED','Price request closed refused','Executed when a customer proposal is closed refused','proposal_supplier',10); -CREATE TABLE llx_projet_task_comment ( +DROP TABLE llx_projet_task_comment; + +CREATE TABLE llx_comment ( rowid integer AUTO_INCREMENT PRIMARY KEY, datec datetime DEFAULT NULL, tms timestamp, description text NOT NULL, - fk_user integer DEFAULT NULL, - fk_task integer DEFAULT NULL, + fk_user_author integer DEFAULT NULL, + fk_element integer DEFAULT NULL, + element_type varchar(50) DEFAULT NULL, entity integer DEFAULT 1, import_key varchar(125) DEFAULT NULL -) ENGINE=innodb; - +)ENGINE=innodb; DELETE FROM llx_const where name = __ENCRYPT('MAIN_SHOW_WORKBOARD')__; diff --git a/htdocs/install/mysql/tables/llx_projet_task_comment.sql b/htdocs/install/mysql/tables/llx_comment.sql similarity index 86% rename from htdocs/install/mysql/tables/llx_projet_task_comment.sql rename to htdocs/install/mysql/tables/llx_comment.sql index 561f8276455..df5f41ba91b 100644 --- a/htdocs/install/mysql/tables/llx_projet_task_comment.sql +++ b/htdocs/install/mysql/tables/llx_comment.sql @@ -16,13 +16,15 @@ -- -- =========================================================================== -CREATE TABLE llx_projet_task_comment ( +CREATE TABLE llx_comment ( rowid integer AUTO_INCREMENT PRIMARY KEY, datec datetime DEFAULT NULL, tms timestamp, description text NOT NULL, - fk_user integer DEFAULT NULL, - fk_task integer DEFAULT NULL, + fk_user_author integer DEFAULT NULL, + fk_element integer DEFAULT NULL, + element_type varchar(50) DEFAULT NULL, entity integer DEFAULT 1, import_key varchar(125) DEFAULT NULL -) ENGINE=innodb; +)ENGINE=innodb; + diff --git a/htdocs/projet/class/project.class.php b/htdocs/projet/class/project.class.php index da754176386..7a42e77c644 100644 --- a/htdocs/projet/class/project.class.php +++ b/htdocs/projet/class/project.class.php @@ -388,6 +388,8 @@ class Project extends CommonObject */ function fetch($id, $ref='') { + global $conf; + if (empty($id) && empty($ref)) return -1; $sql = "SELECT rowid, ref, title, description, public, datec, opp_amount, budget_amount,"; @@ -443,7 +445,11 @@ class Project extends CommonObject // Retreive all extrafield for thirdparty $this->fetch_optionals(); - $this->fetchComments(); + + if (!empty($conf->global->PROJECT_ALLOW_COMMENT_ON_PROJECT)) + { + $this->fetchComments(); + } return 1; } diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index 25da5bb2e3e..14f3c7e37d4 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -35,7 +35,7 @@ class Task extends CommonObject public $table_element='projet_task'; //!< Name of table without prefix where object is stored public $fk_element='fk_task'; public $picto = 'task'; - protected $childtables=array('projet_task_time','projet_task_comment'); // To test if we can delete object + protected $childtables=array('projet_task_time'); // To test if we can delete object var $fk_task_parent; var $label; diff --git a/htdocs/projet/comment.php b/htdocs/projet/comment.php index 4e3d52a2f37..a51d4872c80 100644 --- a/htdocs/projet/comment.php +++ b/htdocs/projet/comment.php @@ -55,7 +55,6 @@ if (! $user->rights->projet->lire) accessforbidden(); // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('projectcard','globalcard')); -$object = new Project($db); $extrafields = new ExtraFields($db); $object = new Project($db); From 9cdf322bfb1935e74a99530c004a6870def9685f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 15 Dec 2017 22:14:28 +0100 Subject: [PATCH 12/27] Fix scrutinizer bugs --- htdocs/compta/bank/bilan.php | 3 +++ htdocs/compta/deplacement/class/deplacement.class.php | 2 -- htdocs/compta/deplacement/class/deplacementstats.class.php | 3 +-- htdocs/core/class/html.form.class.php | 3 ++- htdocs/core/lib/company.lib.php | 2 ++ .../interface_50_modBlockedlog_ActionsBlockedLog.class.php | 1 + htdocs/install/upgrade2.php | 4 +++- htdocs/user/class/usergroup.class.php | 4 +--- 8 files changed, 13 insertions(+), 9 deletions(-) diff --git a/htdocs/compta/bank/bilan.php b/htdocs/compta/bank/bilan.php index 69370faa34e..22f7c8c9e79 100644 --- a/htdocs/compta/bank/bilan.php +++ b/htdocs/compta/bank/bilan.php @@ -41,6 +41,9 @@ if (!$user->rights->banque->lire) function valeur($sql) { global $db; + + $valeur = 0; + $resql=$db->query($sql); if ($resql) { diff --git a/htdocs/compta/deplacement/class/deplacement.class.php b/htdocs/compta/deplacement/class/deplacement.class.php index 5570a0a8afa..05664080ed3 100644 --- a/htdocs/compta/deplacement/class/deplacement.class.php +++ b/htdocs/compta/deplacement/class/deplacement.class.php @@ -60,8 +60,6 @@ class Deplacement extends CommonObject $this->statuts_short = array(0 => 'Draft', 1 => 'Validated', 2 => 'Refunded'); $this->statuts = array(0 => 'Draft', 1 => 'Validated', 2 => 'Refunded'); - - return 1; } /** diff --git a/htdocs/compta/deplacement/class/deplacementstats.class.php b/htdocs/compta/deplacement/class/deplacementstats.class.php index 942c6c4cafa..75ac39a7cca 100644 --- a/htdocs/compta/deplacement/class/deplacementstats.class.php +++ b/htdocs/compta/deplacement/class/deplacementstats.class.php @@ -26,8 +26,7 @@ include_once DOL_DOCUMENT_ROOT . '/core/class/stats.class.php'; include_once DOL_DOCUMENT_ROOT . '/compta/deplacement/class/deplacement.class.php'; /** - * \class DeplacementStats - * \brief Classe permettant la gestion des stats des deplacements et notes de frais + * Classe permettant la gestion des stats des deplacements et notes de frais */ class DeplacementStats extends Stats { diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 839a4c56fe0..b7ac69d0fc8 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -4594,7 +4594,8 @@ class Form } if (! empty($conf->global->SERVICE_ARE_ECOMMERCE_200238EC)) // If option to have vat for end customer for services is on { - if (! $societe_vendeuse->isInEEC() && (! is_object($societe_acheteuse) || ($societe_acheteuse->isInEEC() && ! $societe_acheteuse->isACompany()))) + require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; + if (! isInEEC($societe_vendeuse) && (! is_object($societe_acheteuse) || (isInEEC($societe_acheteuse) && ! $societe_acheteuse->isACompany()))) { // We also add the buyer if (is_numeric($type)) diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index bf8433cb5d6..4b78bb53bb7 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -581,6 +581,8 @@ function getFormeJuridiqueLabel($code) */ function isInEEC($object) { + if (empty($object->country_code)) return false; + // List of all country codes that are in europe for european vat rules // List found on http://ec.europa.eu/taxation_customs/common/faq/faq_1179_en.htm#9 $country_code_in_EEC=array( diff --git a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php index edb7772eb9c..d7e146938ac 100644 --- a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php +++ b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php @@ -57,6 +57,7 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers // Event/record is qualified $qualified = 0; + $amounts = 0; if ($action==='BILL_VALIDATE' || $action==='BILL_DELETE' || $action === 'BILL_SENTBYMAIL' || (in_array($object->element, array('facture','suplier_invoice')) && $action === 'DOC_DOWNLOAD') || (in_array($object->element, array('facture','suplier_invoice')) && $action === 'DOC_PREVIEW') ) diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 4e4269e3699..eda1a4d26d5 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -3885,6 +3885,8 @@ function migrate_event_assignement_contact($db,$langs,$conf) */ function migrate_reset_blocked_log($db,$langs,$conf) { + global $user; + require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; print ''; @@ -3945,7 +3947,7 @@ function migrate_reset_blocked_log($db,$langs,$conf) $object->entity = $obj->entity; $object->date = dol_now(); - $b=new BlockedLog($this->db); + $b=new BlockedLog($db); $b->setObjectData($object, 'MODULE_SET', 0); $res = $b->create($user); diff --git a/htdocs/user/class/usergroup.class.php b/htdocs/user/class/usergroup.class.php index f2ca661681f..6032489b9c7 100644 --- a/htdocs/user/class/usergroup.class.php +++ b/htdocs/user/class/usergroup.class.php @@ -50,7 +50,7 @@ class UserGroup extends CommonObject public $datem; // Modification date of group public $members=array(); // Array of users - public $nb_rights; // Number of rights granted to the user + public $nb_rights; // Number of rights granted to the user private $_tab_loaded=array(); // Array of cache of already loaded permissions @@ -66,8 +66,6 @@ class UserGroup extends CommonObject { $this->db = $db; $this->nb_rights = 0; - - return 0; } From 394eeb3cd9ca8aa6915b6a2570399172c27b8740 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 16 Dec 2017 12:11:46 +0100 Subject: [PATCH 13/27] Fix rendering MD files of images by adding a css --- dev/dolibarr_changes.txt | 21 ++++++++++++ htdocs/core/modules/DolibarrModules.class.php | 1 + htdocs/includes/parsedown/Parsedown.php | 15 +++++++-- htdocs/modulebuilder/template/README.md | 33 +++++++++---------- htdocs/theme/eldy/style.css.php | 9 +++++ htdocs/theme/md/style.css.php | 10 ++++++ 6 files changed, 70 insertions(+), 19 deletions(-) diff --git a/dev/dolibarr_changes.txt b/dev/dolibarr_changes.txt index f28df995c45..16834e7837b 100644 --- a/dev/dolibarr_changes.txt +++ b/dev/dolibarr_changes.txt @@ -134,6 +134,27 @@ Change also file Luracast/Restler/explorer/index.html PARSEDOWN --------- +* Add support of css by adding in Parsedown.php: + + // @CHANGE LDR + 'class' => $Link['element']['attributes']['class'] + + ... + + // @CHANGE LDR + if (preg_match('/{([^}]+)}/', $remainder, $matches2)) + { + $Element['attributes']['class'] = $matches2[1]; + $remainder = preg_replace('/{'.preg_quote($matches2[1],'/').'}/', '', $remainder); + } + + + // @CHANGE LDR + //$markup .= $this->{$Element['handler']}($Element['text']); + $markup .= preg_replace('/>{[^}]+}/', '>', $this->{$Element['handler']}($Element['text'])); + + + * Fix to avoid fatal error when mb_strlen not available: // @CHANGE LDR Fix when mb_strlen is not available diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index c8fd99339e7..eaf674d5eea 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -641,6 +641,7 @@ class DolibarrModules // Can not be abstract, because we need to insta if ((float) DOL_VERSION >= 6.0) { @include_once DOL_DOCUMENT_ROOT.'/core/lib/parsemd.lib.php'; + $content = dolMd2Html($content, 'parsedown', array( 'doc/'=>dol_buildpath(strtolower($this->name).'/doc/', 1), diff --git a/htdocs/includes/parsedown/Parsedown.php b/htdocs/includes/parsedown/Parsedown.php index a1ec563683f..df718bce111 100644 --- a/htdocs/includes/parsedown/Parsedown.php +++ b/htdocs/includes/parsedown/Parsedown.php @@ -1180,7 +1180,9 @@ class Parsedown 'name' => 'img', 'attributes' => array( 'src' => $Link['element']['attributes']['href'], - 'alt' => $Link['element']['text'], + 'alt' => $Link['element']['text'], + // @CHANGE LDR + 'class' => $Link['element']['attributes']['class'] ), ), ); @@ -1231,6 +1233,13 @@ class Parsedown } $extent += strlen($matches[0]); + + // @CHANGE LDR + if (preg_match('/{([^}]+)}/', $remainder, $matches2)) + { + $Element['attributes']['class'] = $matches2[1]; + $remainder = preg_replace('/{'.preg_quote($matches2[1],'/').'}/', '', $remainder); + } } else { @@ -1426,7 +1435,9 @@ class Parsedown if (isset($Element['handler'])) { - $markup .= $this->{$Element['handler']}($Element['text']); + // @CHANGE LDR + //$markup .= $this->{$Element['handler']}($Element['text']); + $markup .= preg_replace('/>{[^}]+}/', '>', $this->{$Element['handler']}($Element['text'])); } else { diff --git a/htdocs/modulebuilder/template/README.md b/htdocs/modulebuilder/template/README.md index 1eb5ffe771a..d745c808bf4 100644 --- a/htdocs/modulebuilder/template/README.md +++ b/htdocs/modulebuilder/template/README.md @@ -3,6 +3,10 @@ ## Features Description... + + Other modules are available on Dolistore.com. @@ -25,44 +29,44 @@ There is a [Transifex project](https://transifex.com/projects/p/dolibarr-module- Install ------- -### Manually +### From the ZIP file and GUI interface -- Make sure Dolibarr is already installed and configured on your workstation or development server. +- If you get the module in a zip file (like when downloading it from the market place [Dolistore](https://www.dolistore.com)), go into +menu ```Home - Setup - Modules - Deploy external module``` and upload the zip file. -- In your Dolibarr installation directory, edit the ```htdocs/conf/conf.php``` file -- Find the following lines: +Note: If this screen tell you there is no custom directory, check your setup is correct: + +- In your Dolibarr installation directory, edit the ```htdocs/conf/conf.php``` file and check that following lines are not commented: + ```php //$dolibarr_main_url_root_alt ... //$dolibarr_main_document_root_alt ... ``` -- And uncomment these lines (delete the leading ```//```) and assign a sensible value according to your Dolibarr installation +- Uncomment them if necessary (delete the leading ```//```) and assign a sensible value according to your Dolibarr installation For example : - UNIX: ```php - $dolibarr_main_url_root = 'http://localhost/Dolibarr/htdocs'; - $dolibarr_main_document_root = '/var/www/Dolibarr/htdocs'; $dolibarr_main_url_root_alt = '/custom'; $dolibarr_main_document_root_alt = '/var/www/Dolibarr/htdocs/custom'; ``` - Windows: ```php - $dolibarr_main_url_root = 'http://localhost/Dolibarr/htdocs'; - $dolibarr_main_document_root = 'C:/My Web Sites/Dolibarr/htdocs'; $dolibarr_main_url_root_alt = '/custom'; $dolibarr_main_document_root_alt = 'C:/My Web Sites/Dolibarr/htdocs/custom'; ``` - - For more information about the ```conf.php``` file take a look at the conf.php.example file. + +### From a GIT repository - Clone the repository in ```$dolibarr_main_document_root_alt/mymodule``` ```sh -git clone git@github.com:Dolibarr/dolibarr-module-template.git mymodule +cd ....../custom +git clone git@github.com:gitlogin/mymodule.git mymodule ``` ### Final steps @@ -75,11 +79,6 @@ From your browser: -## Publishing the module -The de-facto standard for publishing and marketing modules for Dolibarr is the [Dolistore](https://www.dolistore.com). -Templates for required images and texts are [provided](dev/dolistore). -Check the dedicated [README](dev/dolistore/README.md) for more informations. - --> diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 41cf3da2090..037c6a0f069 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -4575,6 +4575,15 @@ dl.dropdown { } +/* ============================================================================== */ +/* Mardown rendering */ +/* ============================================================================== */ + +.imgmd { + width: 90%; +} + + /* ============================================================================== */ /* JMobile */ /* ============================================================================== */ diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index d6833d7e444..8ab38157947 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -4558,6 +4558,16 @@ dl.dropdown { } + +/* ============================================================================== */ +/* Mardown rendering */ +/* ============================================================================== */ + +.imgmd { + width: 90%; +} + + /* ============================================================================== */ /* JMobile */ /* ============================================================================== */ From fcf50c01b9561546ffb03de58ce2d4848046e437 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 16 Dec 2017 15:33:29 +0100 Subject: [PATCH 14/27] Fix translation --- htdocs/langs/en_US/admin.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index fc3caa74657..372d1a40aca 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -539,7 +539,7 @@ Module320Desc=Add RSS feed inside Dolibarr screen pages Module330Name=Bookmarks Module330Desc=Bookmarks management Module400Name=Projects/Opportunities/Leads -Module400Desc=Management of projects, opportunities or leads. You can then assign any element (invoice, order, proposal, intervention, ...) to a project and get a transversal view from the project view. +Module400Desc=Management of projects, opportunities/leads and/or tasks. You can also assign any element (invoice, order, proposal, intervention, ...) to a project and get a transversal view from the project view. Module410Name=Webcalendar Module410Desc=Webcalendar integration Module500Name=Special expenses From 2163db446bdd432cd13989c82c7c7aacc90a5f26 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 16 Dec 2017 17:24:23 +0100 Subject: [PATCH 15/27] NEW Can test signature of a version from API --- htdocs/admin/system/filecheck.php | 69 ++---- htdocs/api/class/api_setup.class.php | 343 ++++++++++++++++++++++++++- htdocs/core/lib/files.lib.php | 41 ++++ 3 files changed, 405 insertions(+), 48 deletions(-) diff --git a/htdocs/admin/system/filecheck.php b/htdocs/admin/system/filecheck.php index 8aed7d193f9..60c20dfafe7 100644 --- a/htdocs/admin/system/filecheck.php +++ b/htdocs/admin/system/filecheck.php @@ -152,7 +152,7 @@ if (GETPOST('target') == 'remote') } -if ($xml) +if (! $error && $xml) { $checksumconcat = array(); $file_list = array(); @@ -395,19 +395,34 @@ if ($xml) var_dump($checksumget); var_dump($checksumtoget); var_dump($checksumget == $checksumtoget);*/ - print_fiche_titre($langs->trans("GlobalChecksum")).'
'; - print $langs->trans("ExpectedChecksum").' = '. ($checksumtoget ? $checksumtoget : $langs->trans("Unknown")) .'
'; - print $langs->trans("CurrentChecksum").' = '; + + $outexpectedchecksum = ($checksumtoget ? $checksumtoget : $langs->trans("Unknown")); if ($checksumget == $checksumtoget) { - if (count($file_list['added'])) print $checksumget.' - '.$langs->trans("FileIntegrityIsOkButFilesWereAdded").''; - else print ''.$checksumget.''; + if (count($file_list['added'])) + { + $resultcode = 'warning'; + $resultcomment='FileIntegrityIsOkButFilesWereAdded'; + $outcurrentchecksum = $checksumget.' - '.$langs->trans("FileIntegrityIsOkButFilesWereAdded").''; + } + else + { + $resultcode = 'ok'; + $resultcomment='Success'; + $outcurrentchecksum = ''.$checksumget.''; + } } else { - print ''.$checksumget.''; + $resultcode = 'error'; + $resultcomment='Error'; + $outcurrentchecksum = ''.$checksumget.''; } + print_fiche_titre($langs->trans("GlobalChecksum")).'
'; + print $langs->trans("ExpectedChecksum").' = '. $outexpectedchecksum .'
'; + print $langs->trans("CurrentChecksum").' = '. $outcurrentchecksum; + print '
'; print '
'; @@ -424,43 +439,3 @@ $db->close(); exit($error); - -/** - * Function to get list of updated or modified files. - * $file_list is used as global variable - * - * @param array $file_list Array for response - * @param SimpleXMLElement $dir SimpleXMLElement of files to test - * @param string $path Path of files relative to $pathref. We start with ''. Used by recursive calls. - * @param string $pathref Path ref (DOL_DOCUMENT_ROOT) - * @param array $checksumconcat Array of checksum - * @return array Array of filenames - */ -function getFilesUpdated(&$file_list, SimpleXMLElement $dir, $path = '', $pathref = '', &$checksumconcat = array()) -{ - $exclude = 'install'; - - foreach ($dir->md5file as $file) // $file is a simpleXMLElement - { - $filename = $path.$file['name']; - $file_list['insignature'][] = $filename; - - //if (preg_match('#'.$exclude.'#', $filename)) continue; - - if (!file_exists($pathref.'/'.$filename)) - { - $file_list['missing'][] = array('filename'=>$filename, 'expectedmd5'=>(string) $file); - } - else - { - $md5_local = md5_file($pathref.'/'.$filename); - if ($md5_local != (string) $file) $file_list['updated'][] = array('filename'=>$filename, 'expectedmd5'=>(string) $file, 'md5'=>(string) $md5_local); - $checksumconcat[] = $md5_local; - } - } - - foreach ($dir->dir as $subdir) getFilesUpdated($file_list, $subdir, $path.$subdir['name'].'/', $pathref, $checksumconcat); - - return $file_list; -} - diff --git a/htdocs/api/class/api_setup.class.php b/htdocs/api/class/api_setup.class.php index 9a5b18ca95d..caba92f2947 100644 --- a/htdocs/api/class/api_setup.class.php +++ b/htdocs/api/class/api_setup.class.php @@ -329,7 +329,7 @@ class Setup extends DolibarrApi * * @throws RestException */ - function getListOfEvents($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $type = '', $module = '', $sqlfilters = '') + function getListOfEventTypes($sortfield = "code", $sortorder = 'ASC', $limit = 100, $page = 0, $type = '', $module = '', $sqlfilters = '') { $list = array(); @@ -577,4 +577,345 @@ class Setup extends DolibarrApi return $list; } + + /** + * Do a test of integrity for files and setup. + * + * @param string $target Can be 'local' or 'default' or Url of the signatures file to use for the test. Must be reachable by the tested Dolibarr. + * @return Result of file and setup integrity check + * + * @url GET checkintegrity + * + * @throws RestException + */ + function getCheckIntegrity($target) + { + global $langs, $conf; + + if (! DolibarrApiAccess::$user->admin + && (empty($conf->global->API_LOGIN_ALLOWED_FOR_INTEGRITY_CHECK) || DolibarrApiAccess::$user->login != $conf->global->API_LOGIN_ALLOWED_FOR_INTEGRITY_CHECK)) + { + throw new RestException(503, 'Error API open to admin users only or to login user defined with constant API_LOGIN_ALLOWED_FOR_INTEGRITY_CHECK'); + } + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; + + $langs->load("admin"); + + $outexpectedchecksum = ''; + $outcurrentchecksum = ''; + + // Modified or missing files + $file_list = array('missing' => array(), 'updated' => array()); + + // Local file to compare to + $xmlshortfile = GETPOST('xmlshortfile')?GETPOST('xmlshortfile'):'/install/filelist-'.DOL_VERSION.'.xml'; + $xmlfile = DOL_DOCUMENT_ROOT.$xmlshortfile; + // Remote file to compare to + $xmlremote = ($target == 'default' ? '' : $target); + if (empty($xmlremote) && ! empty($conf->global->MAIN_FILECHECK_URL)) $xmlremote = $conf->global->MAIN_FILECHECK_URL; + $param='MAIN_FILECHECK_URL_'.DOL_VERSION; + if (empty($xmlremote) && ! empty($conf->global->$param)) $xmlremote = $conf->global->$param; + if (empty($xmlremote)) $xmlremote = 'https://www.dolibarr.org/files/stable/signatures/filelist-'.DOL_VERSION.'.xml'; + + if ($target == 'local') + { + if (dol_is_file($xmlfile)) + { + $xml = simplexml_load_file($xmlfile); + } + else + { + throw new RestException(500, $langs->trans('XmlNotFound') . ': ' . $xmlfile); + $error++; + } + } + else + { + $xmlarray = getURLContent($xmlremote); + + // Return array('content'=>response,'curl_error_no'=>errno,'curl_error_msg'=>errmsg...) + if (! $xmlarray['curl_error_no'] && $xmlarray['http_code'] != '404') + { + $xmlfile = $xmlarray['content']; + //print "eee".$xmlfile."eee"; + $xml = simplexml_load_string($xmlfile); + } + else + { + $errormsg=$langs->trans('XmlNotFound') . ': ' . $xmlremote.' - '.$xmlarray['http_code'].' '.$xmlarray['curl_error_no'].' '.$xmlarray['curl_error_msg']; + throw new RestException(500, $errormsg); + $error++; + } + } + + + + if (! $error && $xml) + { + $checksumconcat = array(); + $file_list = array(); + $out = ''; + + // Forced constants + if (is_object($xml->dolibarr_constants[0])) + { + $out.=load_fiche_titre($langs->trans("ForcedConstants")); + + $out.='
'; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''."\n"; + + $i = 0; + foreach ($xml->dolibarr_constants[0]->constant as $constant) // $constant is a simpleXMLElement + { + $constname=$constant['name']; + $constvalue=(string) $constant; + $constvalue = (empty($constvalue)?'0':$constvalue); + // Value found + $value=''; + if ($constname && $conf->global->$constname != '') $value=$conf->global->$constname; + $valueforchecksum=(empty($value)?'0':$value); + + $checksumconcat[]=$valueforchecksum; + + $i++; + $out.=''; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.="\n"; + } + + if ($i==0) + { + $out.=''; + } + $out.='
#' . $langs->trans("Constant") . '' . $langs->trans("ExpectedValue") . '' . $langs->trans("Value") . '
'.$i.''.$constname.''.$constvalue.''.$valueforchecksum.'
'.$langs->trans("None").'
'; + $out.='
'; + + $out.='
'; + } + + // Scan htdocs + if (is_object($xml->dolibarr_htdocs_dir[0])) + { + //var_dump($xml->dolibarr_htdocs_dir[0]['includecustom']);exit; + $includecustom=(empty($xml->dolibarr_htdocs_dir[0]['includecustom'])?0:$xml->dolibarr_htdocs_dir[0]['includecustom']); + + // Defined qualified files (must be same than into generate_filelist_xml.php) + $regextoinclude='\.(php|css|html|js|json|tpl|jpg|png|gif|sql|lang)$'; + $regextoexclude='('.($includecustom?'':'custom|').'documents|conf|install|public\/test|Shared\/PCLZip|nusoap\/lib\/Mail|php\/example|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$'; // Exclude dirs + $scanfiles = dol_dir_list(DOL_DOCUMENT_ROOT, 'files', 1, $regextoinclude, $regextoexclude); + + // Fill file_list with files in signature, new files, modified files + $ret = getFilesUpdated($file_list, $xml->dolibarr_htdocs_dir[0], '', DOL_DOCUMENT_ROOT, $checksumconcat, $scanfiles); // Fill array $file_list + // Complete with list of new files + foreach ($scanfiles as $keyfile => $valfile) + { + $tmprelativefilename=preg_replace('/^'.preg_quote(DOL_DOCUMENT_ROOT,'/').'/','', $valfile['fullname']); + if (! in_array($tmprelativefilename, $file_list['insignature'])) + { + $md5newfile=@md5_file($valfile['fullname']); // Can fails if we don't have permission to open/read file + $file_list['added'][]=array('filename'=>$tmprelativefilename, 'md5'=>$md5newfile); + } + } + + // Files missings + $out.=load_fiche_titre($langs->trans("FilesMissing")); + + $out.='
'; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''."\n"; + $tmpfilelist = dol_sort_array($file_list['missing'], 'filename'); + if (is_array($tmpfilelist) && count($tmpfilelist)) + { + $i = 0; + foreach ($tmpfilelist as $file) + { + $i++; + $out.=''; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.="\n"; + } + } + else + { + $out.=''; + } + $out.='
#' . $langs->trans("Filename") . '' . $langs->trans("ExpectedChecksum") . '
'.$i.''.$file['filename'].''.$file['expectedmd5'].'
'.$langs->trans("None").'
'; + $out.='
'; + + $out.='
'; + + // Files modified + $out.=load_fiche_titre($langs->trans("FilesModified")); + + $totalsize=0; + $out.='
'; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''."\n"; + $tmpfilelist2 = dol_sort_array($file_list['updated'], 'filename'); + if (is_array($tmpfilelist2) && count($tmpfilelist2)) + { + $i = 0; + foreach ($tmpfilelist2 as $file) + { + $i++; + $out.=''; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $size = dol_filesize(DOL_DOCUMENT_ROOT.'/'.$file['filename']); + $totalsize += $size; + $out.='' . "\n"; + $out.='' . "\n"; + $out.="\n"; + } + $out.=''; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.="\n"; + } + else + { + $out.=''; + } + $out.='
#' . $langs->trans("Filename") . '' . $langs->trans("ExpectedChecksum") . '' . $langs->trans("CurrentChecksum") . '' . $langs->trans("Size") . '' . $langs->trans("DateModification") . '
'.$i.''.$file['filename'].''.$file['expectedmd5'].''.$file['md5'].''.dol_print_size($size).''.dol_print_date(dol_filemtime(DOL_DOCUMENT_ROOT.'/'.$file['filename']),'dayhour').'
'.$langs->trans("Total").''.dol_print_size($totalsize).'
'.$langs->trans("None").'
'; + $out.='
'; + + $out.='
'; + + // Files added + $out.=load_fiche_titre($langs->trans("FilesAdded")); + + $totalsize = 0; + $out.='
'; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''; + $out.=''."\n"; + $tmpfilelist3 = dol_sort_array($file_list['added'], 'filename'); + if (is_array($tmpfilelist3) && count($tmpfilelist3)) + { + $i = 0; + foreach ($tmpfilelist3 as $file) + { + $i++; + $out.=''; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $size = dol_filesize(DOL_DOCUMENT_ROOT.'/'.$file['filename']); + $totalsize += $size; + $out.='' . "\n"; + $out.='' . "\n"; + $out.="\n"; + } + $out.=''; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.='' . "\n"; + $out.="\n"; + } + else + { + $out.=''; + } + $out.='
#' . $langs->trans("Filename") . '' . $langs->trans("ExpectedChecksum") . '' . $langs->trans("CurrentChecksum") . '' . $langs->trans("Size") . '' . $langs->trans("DateModification") . '
'.$i.''.$file['filename'].''.$file['expectedmd5'].''.$file['md5'].''.dol_print_size($size).''.dol_print_date(dol_filemtime(DOL_DOCUMENT_ROOT.'/'.$file['filename']),'dayhour').'
'.$langs->trans("Total").''.dol_print_size($totalsize).'
'.$langs->trans("None").'
'; + $out.='
'; + + + // Show warning + if (empty($tmpfilelist) && empty($tmpfilelist2) && empty($tmpfilelist3)) + { + //setEventMessage($langs->trans("FileIntegrityIsStrictlyConformedWithReference")); + } + else + { + //setEventMessage($langs->trans("FileIntegritySomeFilesWereRemovedOrModified"), 'warnings'); + } + } + else + { + throw new RestException(500, 'Error: Failed to found dolibarr_htdocs_dir into XML file '.$xmlfile); + $error++; + } + + + // Scan scripts + + + asort($checksumconcat); // Sort list of checksum + //var_dump($checksumconcat); + $checksumget = md5(join(',',$checksumconcat)); + $checksumtoget = trim((string) $xml->dolibarr_htdocs_dir_checksum); + + $outexpectedchecksum = ($checksumtoget ? $checksumtoget : $langs->trans("Unknown")); + if ($checksumget == $checksumtoget) + { + if (count($file_list['added'])) + { + $resultcode = 'warning'; + $resultcomment='FileIntegrityIsOkButFilesWereAdded'; + //$outcurrentchecksum = $checksumget.' - '.$langs->trans("FileIntegrityIsOkButFilesWereAdded").''; + $outcurrentchecksum = $checksumget; + } + else + { + $resultcode = 'ok'; + $resultcomment='Success'; + //$outcurrentchecksum = ''.$checksumget.''; + $outcurrentchecksum = $checksumget; + } + } + else + { + $resultcode = 'error'; + $resultcomment='Error'; + //$outcurrentchecksum = ''.$checksumget.''; + $outcurrentchecksum = $checksumget; + } + } + else { + throw new RestException(404, 'No signature file known'); + } + + return array('resultcode'=>$resultcode, 'resultcomment'=>$resultcomment, 'expectedchecksum'=> $outexpectedchecksum, 'currentchecksum'=> $outcurrentchecksum, 'out'=>$out); + } + } diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 220a390d577..daf4621ebcb 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -2723,3 +2723,44 @@ function dol_readcachefile($directory, $filename) $object = unserialize(file_get_contents($cachefile)); return $object; } + + +/** + * Function to get list of updated or modified files. + * $file_list is used as global variable + * + * @param array $file_list Array for response + * @param SimpleXMLElement $dir SimpleXMLElement of files to test + * @param string $path Path of files relative to $pathref. We start with ''. Used by recursive calls. + * @param string $pathref Path ref (DOL_DOCUMENT_ROOT) + * @param array $checksumconcat Array of checksum + * @return array Array of filenames + */ +function getFilesUpdated(&$file_list, SimpleXMLElement $dir, $path = '', $pathref = '', &$checksumconcat = array()) +{ + $exclude = 'install'; + + foreach ($dir->md5file as $file) // $file is a simpleXMLElement + { + $filename = $path.$file['name']; + $file_list['insignature'][] = $filename; + + //if (preg_match('#'.$exclude.'#', $filename)) continue; + + if (!file_exists($pathref.'/'.$filename)) + { + $file_list['missing'][] = array('filename'=>$filename, 'expectedmd5'=>(string) $file); + } + else + { + $md5_local = md5_file($pathref.'/'.$filename); + if ($md5_local != (string) $file) $file_list['updated'][] = array('filename'=>$filename, 'expectedmd5'=>(string) $file, 'md5'=>(string) $md5_local); + $checksumconcat[] = $md5_local; + } + } + + foreach ($dir->dir as $subdir) getFilesUpdated($file_list, $subdir, $path.$subdir['name'].'/', $pathref, $checksumconcat); + + return $file_list; +} + From e90a6b8c0f8f1316672c85a0249d0793d7fff552 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 16 Dec 2017 20:52:49 +0100 Subject: [PATCH 16/27] Option THEME_HIDE_BORDER_ON_INPUT to restore border on inputfields work also with md theme. --- htdocs/core/class/conf.class.php | 2 ++ htdocs/theme/eldy/style.css.php | 6 ++---- htdocs/theme/md/style.css.php | 5 +---- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 2defcd0e2cc..0603ec93014 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -581,6 +581,8 @@ class Conf if (empty($this->global->MAIN_SIZE_SHORTLIST_LIMIT)) $this->global->MAIN_SIZE_SHORTLIST_LIMIT=3; + if (! isset($this->global->THEME_HIDE_BORDER_ON_INPUT)) $this->global->THEME_HIDE_BORDER_ON_INPUT=0; + // Save inconsistent option if (empty($conf->global->AGENDA_USE_EVENT_TYPE) && (! isset($conf->global->AGENDA_DEFAULT_FILTER_TYPE) || $conf->global->AGENDA_DEFAULT_FILTER_TYPE == 'AC_NON_AUTO')) { diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index 037c6a0f069..a39aff863d2 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -284,15 +284,13 @@ input[type=submit] { margin-left: 5px; } input, input.flat, form.flat select, select, select.flat, .dataTables_length label select { - global->THEME_ELDY_SHOW_BORDER_INPUT)) - print "border: none;" - ?> + border: none; } input, input.flat, textarea, textarea.flat, form.flat select, select, select.flat, .dataTables_length label select { font-family: ; outline: none; margin: 0px 0px 0px 0px; - border-bottom: solid 1px rgba(0,0,0,.2); + borderglobal->THEME_HIDE_BORDER_ON_INPUT)?'-bottom':''; ?>: solid 1px rgba(0,0,0,.2); } input { diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 8ab38157947..8d164280591 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -297,7 +297,7 @@ input, input.flat, textarea, textarea.flat, form.flat select, select, select.fla font-size: px; font-family: ; border: none; - border-bottom: solid 1px rgba(0,0,0,.1); + borderglobal->THEME_HIDE_BORDER_ON_INPUT)?'-bottom':''; ?>: solid 1px rgba(0,0,0,.2); outline: none; margin: 0px 0px 0px 0px; } @@ -317,9 +317,6 @@ input, select { margin-top:1px; } -input, select { - border-bottom: solid 1px rgba(0,0,0,.1); -} textarea { border-radius: 0; From 4abcbae79f92630f81a620a2ad13a5f8712c24bf Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 16 Dec 2017 21:36:36 +0100 Subject: [PATCH 17/27] NEW The unalterable log can be browse by any user with he permission --- htdocs/blockedlog/admin/blockedlog.php | 19 ++++++-- htdocs/blockedlog/admin/blockedlog_list.php | 50 ++++++++++++++------ htdocs/blockedlog/class/blockedlog.class.php | 4 +- htdocs/blockedlog/lib/blockedlog.lib.php | 6 +-- htdocs/core/class/conf.class.php | 2 +- htdocs/core/modules/modBlockedLog.class.php | 19 +++++++- htdocs/langs/en_US/blockedlog.lang | 5 +- 7 files changed, 77 insertions(+), 28 deletions(-) diff --git a/htdocs/blockedlog/admin/blockedlog.php b/htdocs/blockedlog/admin/blockedlog.php index 091e520c333..1970cafa0a6 100644 --- a/htdocs/blockedlog/admin/blockedlog.php +++ b/htdocs/blockedlog/admin/blockedlog.php @@ -81,12 +81,20 @@ $block_static = new BlockedLog($db); llxHeader('',$langs->trans("BlockedLogSetup")); -$linkback=''.$langs->trans("BackToModuleList").''; +$linkback=''; +if (GETPOST('withtab','alpha')) +{ + $linkback=''.$langs->trans("BackToModuleList").''; +} + print load_fiche_titre($langs->trans("ModuleSetup").' '.$langs->trans('BlockedLog'),$linkback); -$head=blockedlogadmin_prepare_head(); +if (GETPOST('withtab','alpha')) +{ + $head=blockedlogadmin_prepare_head(); + dol_fiche_head($head, 'blockedlog', '', -1); +} -dol_fiche_head($head, 'blockedlog', '', -1); print $langs->trans("BlockedLogDesc")."
\n"; @@ -148,7 +156,10 @@ print ''; print ''; -dol_fiche_end(); +if (GETPOST('withtab','alpha')) +{ + dol_fiche_end(); +} print '

'; diff --git a/htdocs/blockedlog/admin/blockedlog_list.php b/htdocs/blockedlog/admin/blockedlog_list.php index 5caf9ef501c..078501d5bd8 100644 --- a/htdocs/blockedlog/admin/blockedlog_list.php +++ b/htdocs/blockedlog/admin/blockedlog_list.php @@ -38,6 +38,7 @@ $optioncss = GETPOST('optioncss','aZ'); // Option for the css output $showonlyerrors = GETPOST('showonlyerrors','int'); +$search_fk_user=GETPOST('search_fk_user','intcomma'); $search_start = -1; if(GETPOST('search_startyear')!='') $search_start = dol_mktime(0, 0, 0, GETPOST('search_startmonth'), GETPOST('search_startday'), GETPOST('search_startyear')); $search_end = -1; @@ -72,6 +73,7 @@ $result = restrictedArea($user, 'blockedlog', 0, ''); // 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 { + $search_fk_user = ''; $search_start = -1; $search_end = -1; $search_ref = ''; @@ -156,45 +158,56 @@ $form=new Form($db); llxHeader('',$langs->trans("BlockedLogSetup")); -$blocks = $block_static->getLog('all', 0, GETPOST('all','alpha') ? 0 : 50, $sortfield, $sortorder, $search_start, $search_end, $search_ref, $search_amount); +$blocks = $block_static->getLog('all', 0, GETPOST('all','alpha') ? 0 : 50, $sortfield, $sortorder, $search_fk_user, $search_start, $search_end, $search_ref, $search_amount); if (! is_array($blocks)) { dol_print_error($block_static->db); exit; } -$linkback=''.$langs->trans("BackToModuleList").''; +$linkback=''; +if (GETPOST('withtab','alpha')) +{ + $linkback=''.$langs->trans("BackToModuleList").''; +} + print load_fiche_titre($langs->trans("ModuleSetup").' '.$langs->trans('BlockedLog'),$linkback); -$head=blockedlogadmin_prepare_head(); +if (GETPOST('withtab','alpha')) +{ + $head=blockedlogadmin_prepare_head(); + dol_fiche_head($head, 'fingerprints', '', -1); +} -dol_fiche_head($head, 'fingerprints', '', -1); - -print $langs->trans("FingerprintsDesc")."
\n"; +print ''.$langs->trans("FingerprintsDesc")."
\n"; print '
'; $param=''; if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.urlencode($contextpage); if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.urlencode($limit); -if ($search_start > 0) $param.='&search_startyear='.urlencode(GETPOST('search_startyear','int')).'&search_startmonth='.urlencode(GETPOST('search_startmonth','int')).'&search_startday='.urlencode(GETPOST('search_startday','int')); -if ($search_end > 0) $param.='&search_endyear='.urlencode(GETPOST('search_endyear','int')).'&search_endmonth='.urlencode(GETPOST('search_endmonth','int')).'&search_endday='.urlencode(GETPOST('search_endday','int')); -if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss); +if ($search_fk_user > 0) $param.='&search_fk_user='.urlencode($search_fk_user); +if ($search_start > 0) $param.='&search_startyear='.urlencode(GETPOST('search_startyear','int')).'&search_startmonth='.urlencode(GETPOST('search_startmonth','int')).'&search_startday='.urlencode(GETPOST('search_startday','int')); +if ($search_end > 0) $param.='&search_endyear='.urlencode(GETPOST('search_endyear','int')).'&search_endmonth='.urlencode(GETPOST('search_endmonth','int')).'&search_endday='.urlencode(GETPOST('search_endday','int')); +if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss); +if (GETPOST('withtab','alpha')) $param.='&withtab='.urlencode(GETPOST('withtab','alpha')); + // Add $param from extra fields //include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; print ''; print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table print ''; +print ''; print ''; print ''; @@ -206,7 +219,11 @@ print $form->select_date($search_start,'search_start'); print $form->select_date($search_end,'search_end'); print ''; -print ''; +// User +print ''; + print ''; // Ref @@ -373,7 +390,10 @@ if(!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY) && !empty($conf->globa } -dol_fiche_end(); +if (GETPOST('withtab','alpha')) +{ + dol_fiche_end(); +} print '

'; diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index bf9f59f14e2..5ca60997df9 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -658,13 +658,14 @@ class BlockedLog * @param int $limit max number of element, 0 for all * @param string $sortfield sort field * @param string $sortorder sort order + * @param int $search_fk_user id of user(s) * @param int $search_start start time limit * @param int $search_end end time limit * @param string $search_ref search ref * @param string $search_amount search amount * @return array array of object log */ - public function getLog($element, $fk_object, $limit = 0, $sortfield = '', $sortorder = '', $search_start = -1, $search_end = -1, $search_ref='', $search_amount='') + public function getLog($element, $fk_object, $limit = 0, $sortfield = '', $sortorder = '', $search_fk_user = -1, $search_start = -1, $search_end = -1, $search_ref='', $search_amount='') { global $conf, $cachedlogs; @@ -692,6 +693,7 @@ class BlockedLog WHERE entity=".$conf->entity." AND element='".$element."' AND fk_object=".(int) $fk_object; } + if ($search_fk_user > 0) $sql.=" AND fk_user IN (".$this->db->escape($search_fk_user).")"; if ($search_start > 0) $sql.=" AND date_creation >= '".$this->db->idate($search_start)."'"; if ($search_end > 0) $sql.=" AND date_creation <= '".$this->db->idate($search_end)."'"; if ($search_ref != '') $sql.=natural_search("ref_object", $search_ref); diff --git a/htdocs/blockedlog/lib/blockedlog.lib.php b/htdocs/blockedlog/lib/blockedlog.lib.php index 130ce9d19e0..8e715154c64 100644 --- a/htdocs/blockedlog/lib/blockedlog.lib.php +++ b/htdocs/blockedlog/lib/blockedlog.lib.php @@ -33,13 +33,13 @@ function blockedlogadmin_prepare_head() $h = 0; $head = array(); - $head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/blockedlog.php"; + $head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/blockedlog.php?withtab=1"; $head[$h][1] = $langs->trans("Setup"); $head[$h][2] = 'blockedlog'; $h++; - $head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/blockedlog_list.php"; - $head[$h][1] = $langs->trans("Fingerprints"); + $head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/blockedlog_list.php?withtab=1"; + $head[$h][1] = $langs->trans("BrowseBlockedLog"); require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; $b=new BlockedLog($db); diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 0603ec93014..dd8081754d8 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -503,7 +503,7 @@ class Conf if (! isset($this->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE)) $this->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE=1; // Define list of limited modules (value must be key found for "name" property of module, so for example 'supplierproposal' for Module "Supplier Proposal" - if (! isset($this->global->MAIN_MODULES_FOR_EXTERNAL)) $this->global->MAIN_MODULES_FOR_EXTERNAL='user,societe,propal,commande,facture,categorie,supplierproposal,fournisseur,contact,projet,contrat,ficheinter,expedition,agenda,resource,adherent'; // '' means 'all'. Note that contact is added here as it should be a module later. + if (! isset($this->global->MAIN_MODULES_FOR_EXTERNAL)) $this->global->MAIN_MODULES_FOR_EXTERNAL='user,societe,propal,commande,facture,categorie,supplierproposal,fournisseur,contact,projet,contrat,ficheinter,expedition,agenda,resource,adherent,blockedlog'; // '' means 'all'. Note that contact is added here as it should be a module later. // Enable select2 if (empty($this->global->MAIN_USE_JQUERY_MULTISELECT) || $this->global->MAIN_USE_JQUERY_MULTISELECT == '1') $this->global->MAIN_USE_JQUERY_MULTISELECT='select2'; diff --git a/htdocs/core/modules/modBlockedLog.class.php b/htdocs/core/modules/modBlockedLog.class.php index 56a9191866f..59fa600f894 100644 --- a/htdocs/core/modules/modBlockedLog.class.php +++ b/htdocs/core/modules/modBlockedLog.class.php @@ -110,6 +110,7 @@ class modBlockedLog extends DolibarrModules $this->boxes = array(); // Permissions + // ----------------- $this->rights = array(); // Permission array used by this module $r=0; @@ -120,8 +121,22 @@ class modBlockedLog extends DolibarrModules $this->rights[$r][5] = ''; // Main menu entries - //------------------ - $this->menu = array(); + // ----------------- + $r=0; + $this->menu[$r]=array( + 'fk_menu'=>'fk_mainmenu=tools', // Use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'mainmenu'=>'tools', + 'leftmenu'=>'blockedlogbrowser', + 'type'=>'left', // This is a Left menu entry + 'titre'=>'BrowseBlockedLog', + 'url'=>'/blockedlog/admin/blockedlog_list.php?mainmenu=tools&leftmenu=blockedlogbrowser', + 'langs'=>'blockedlog', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>200, + 'enabled'=>'$conf->blockedlog->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms'=>'$user->rights->blockedlog->read', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + $r++; } diff --git a/htdocs/langs/en_US/blockedlog.lang b/htdocs/langs/en_US/blockedlog.lang index ca99d42a6bf..19c919e1d0e 100644 --- a/htdocs/langs/en_US/blockedlog.lang +++ b/htdocs/langs/en_US/blockedlog.lang @@ -2,10 +2,11 @@ BlockedLog=Unalterable Logs Field=Field BlockedLogDesc=This module tracks some events into an unalterable log (that you can't modify once recorded) into a block chain, in real time. This module provides compatibility with requirements of laws of some countries (like France with the law Fincance 2016 - Norme NF535). Fingerprints=Archived events and fingerprints -FingerprintsDesc=This is the tool to browser the unalterable logs +FingerprintsDesc=This is the tool to browse the archived unalterable logs. Note that, by definition, there is no feature to purge this log and every change tried to be done directly into this log (by a hacker for example) will be reported with a non valid fingerprint. If you really need to purge this table because you used your application for a demo/test purpose and want to clean your data to start your production, you can ask your reseller or integrator to reset your database (all your data will be removed). CompanyInitialKey=Company initial key (hash of genesis block) +BrowseBlockedLog=Browse unalterable logs ShowAllFingerPrintsMightBeTooLong=Show all archived logs (might be long) -ShowAllFingerPrintsErrorsMightBeTooLong=Show all archive logs with error (might be long) +ShowAllFingerPrintsErrorsMightBeTooLong=Show all non valid archive logs (might be long) DownloadBlockChain=Download fingerprints KoCheckFingerprintValidity=Archived log is not valid. It means someone (a hacker ?) has modified some datas of this archived log after it was recorded, or has erased the previous archived record (check that line with previous # exists). OkCheckFingerprintValidity=Archived log is valid. It means all data on this line were not modified and record follow the previous one. From 9f2a42b67d3ac3120f543d220f411fdc51494467 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 16 Dec 2017 21:50:58 +0100 Subject: [PATCH 18/27] NEW Can filter on user on unalterable log --- htdocs/admin/modules.php | 6 ++++-- htdocs/core/modules/modBlockedLog.class.php | 2 +- htdocs/theme/eldy/style.css.php | 6 +++++- htdocs/theme/md/style.css.php | 6 +++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 747a3cd41c3..ee17e647863 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -740,11 +740,13 @@ if ($mode == 'common') { if (preg_match('/^([^@]+)@([^@]+)$/i',$urlpage,$regs)) { - print ''.img_picto($langs->trans("Setup"),"setup",'style="padding-right: 6px"').''; + $urltouse=dol_buildpath('/'.$regs[2].'/admin/'.$regs[1],1); + print ''.img_picto($langs->trans("Setup"),"setup",'style="padding-right: 6px"').''; } else { - print ''.img_picto($langs->trans("Setup"),"setup",'style="padding-right: 6px"').''; + $urltouse=$urlpage; + print ''.img_picto($langs->trans("Setup"),"setup",'style="padding-right: 6px"').''; } } } diff --git a/htdocs/core/modules/modBlockedLog.class.php b/htdocs/core/modules/modBlockedLog.class.php index 59fa600f894..eece7323c68 100644 --- a/htdocs/core/modules/modBlockedLog.class.php +++ b/htdocs/core/modules/modBlockedLog.class.php @@ -63,7 +63,7 @@ class modBlockedLog extends DolibarrModules // Config pages //------------- - $this->config_page_url = array('blockedlog.php@blockedlog'); + $this->config_page_url = array('blockedlog.php?withtab=1@blockedlog'); // Dependancies //------------- diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index a39aff863d2..c275927daba 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -4574,12 +4574,16 @@ dl.dropdown { /* ============================================================================== */ -/* Mardown rendering */ +/* Markdown rendering */ /* ============================================================================== */ .imgmd { width: 90%; } +.moduledesclong h1 { + padding-top: 10px; + padding-bottom: 20px; +} /* ============================================================================== */ diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 8d164280591..a1cc5789663 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -4557,12 +4557,16 @@ dl.dropdown { /* ============================================================================== */ -/* Mardown rendering */ +/* Markdown rendering */ /* ============================================================================== */ .imgmd { width: 90%; } +.moduledesclong h1 { + padding-top: 10px; + padding-bottom: 20px; +} /* ============================================================================== */ From d895e1be9fd897e1ad13cdde300daf9073dd32e4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 16 Dec 2017 22:26:25 +0100 Subject: [PATCH 19/27] NEW Show list of tracked events into the module config page. --- htdocs/blockedlog/admin/blockedlog.php | 17 ++++++- htdocs/blockedlog/class/blockedlog.class.php | 47 +++++++++++++++++++ ..._modBlockedlog_ActionsBlockedLog.class.php | 12 ++++- htdocs/langs/en_US/blockedlog.lang | 1 + 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/htdocs/blockedlog/admin/blockedlog.php b/htdocs/blockedlog/admin/blockedlog.php index 1970cafa0a6..5e34cb968ae 100644 --- a/htdocs/blockedlog/admin/blockedlog.php +++ b/htdocs/blockedlog/admin/blockedlog.php @@ -96,7 +96,7 @@ if (GETPOST('withtab','alpha')) } -print $langs->trans("BlockedLogDesc")."
\n"; +print ''.$langs->trans("BlockedLogDesc")."
\n"; print '
'; @@ -152,8 +152,23 @@ $seledted = empty($conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY) ? a print $form->multiselectarray('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY', $countryArray, $seledted); print ''; print ''; + +print ''; + + +print '
'; +print ''; +print ''; + print '
'; +print $form->select_users($search_fk_user, 'search_fk_user', 1); +print '
'; +print $langs->trans("ListOfTrackedEvents").''; +$arrayoftrackedevents=$block_static->trackedevents; +foreach($arrayoftrackedevents as $key => $val) +{ + print $key.'-'.$val.'
'; +} + print '
'; if (GETPOST('withtab','alpha')) diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index 5ca60997df9..becbe2bbe03 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -88,6 +88,12 @@ class BlockedLog public $object_data = null; + /** + * Array of tracked event codes + * @var string[] + */ + public $trackedevents = array(); + /** @@ -97,8 +103,49 @@ class BlockedLog */ public function __construct(DoliDB $db) { + global $conf; + $this->db = $db; + $this->trackedevents = array(); + + if ($conf->facture->enabled) $this->trackedevents['BILL_VALIDATE']='BillValidate'; + if ($conf->facture->enabled) $this->trackedevents['BILL_DELETE']='BillDelete'; + if ($conf->facture->enabled) $this->trackedevents['BILL_SENTBYMAIL']='BillSentByEmail'; + if ($conf->facture->enabled) $this->trackedevents['DOC_DOWNLOAD']='BillDownload'; + if ($conf->facture->enabled) $this->trackedevents['DOC_PREVIEW']='BillPreview'; + + if ($conf->facture->enabled) $this->trackedevents['PAYMENT_CUSTOMER_CREATE']='BillPaymentCreate'; + if ($conf->facture->enabled) $this->trackedevents['PAYMENT_CUSTOMER_DELETE']='BillPaymentDelete'; + + /* Supplier + if ($conf->fournisseur->enabled) $this->trackedevents['BILL_SUPPLIER_VALIDATE']='SupplierBillValidate'; + if ($conf->fournisseur->enabled) $this->trackedevents['BILL_SUPPLIER_DELETE']='SupplierBillDelete'; + if ($conf->fournisseur->enabled) $this->trackedevents['BILL_SUPPLIER_SENTBYMAIL']='SupplierBillSentByEmail'; // Trigger key does not exists, we want just into array to list it as done + if ($conf->fournisseur->enabled) $this->trackedevents['SUPPLIER_DOC_DOWNLOAD']='SupplierBillDownload'; // Trigger key does not exists, we want just into array to list it as done + if ($conf->fournisseur->enabled) $this->trackedevents['SUPPLIER_DOC_PREVIEW']='SupplierBillPreview'; // Trigger key does not exists, we want just into array to list it as done + + if ($conf->fournisseur->enabled) $this->trackedevents['PAYMENT_SUPPLIER_CREATE']='SupplierBillPaymentCreate'; + if ($conf->fournisseur->enabled) $this->trackedevents['PAYMENT_SUPPLIER_DELETE']='supplierBillPaymentCreate'; + */ + + if ($conf->don->enabled) $this->trackedevents['DON_CREATE']='DonationCreate'; + if ($conf->don->enabled) $this->trackedevents['DON_MODIFY']='DonationModify'; + if ($conf->don->enabled) $this->trackedevents['DON_DELETE']='DonationDelete'; + + /* + if ($conf->salary->enabled) $this->trackedevents['PAYMENT_SALARY_CREATE']='SalaryPaymentCreate'; + if ($conf->salary->enabled) $this->trackedevents['PAYMENT_SALARY_MODIFY']='SalaryPaymentCreate'; + if ($conf->salary->enabled) $this->trackedevents['PAYMENT_SALARY_DELETE']='SalaryPaymentCreate'; + */ + + if ($conf->adherent->enabled) $this->trackedevents['MEMBER_SUBSCRIPTION']='MemberSubscription'; + + /* + $trackedevents['PAYMENT_VARIOUS_CREATE']='VariousPaymentCreate'; + $trackedevents['PAYMENT_VARIOUS_MODIFY']='VariousPaymentModify'; + $trackedevents['PAYMENT_VARIOUS_DELETE']='VariousPaymentDelete'; + */ } /** diff --git a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php index d7e146938ac..64796c79654 100644 --- a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php +++ b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php @@ -55,10 +55,19 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + $b=new BlockedLog($this->db); + + // Tracked events + if (! in_array($action, array_keys($b->trackedevents))) + { + return 0; + } + // Event/record is qualified $qualified = 0; $amounts = 0; if ($action==='BILL_VALIDATE' || $action==='BILL_DELETE' || $action === 'BILL_SENTBYMAIL' + || $action==='BILL_SUPPLIER_VALIDATE' || $action==='BILL_SUPPLIER_DELETE' || $action === 'BILL_SUPPLIER_SENTBYMAIL' || (in_array($object->element, array('facture','suplier_invoice')) && $action === 'DOC_DOWNLOAD') || (in_array($object->element, array('facture','suplier_invoice')) && $action === 'DOC_PREVIEW') ) { @@ -88,13 +97,14 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers $amounts= (double) $object->amount; } + // Another protection. + // May be used when event is DOC_DOWNLOAD or DOC_PREVIEW and element is not an invoice if (! $qualified) { return 0; // not implemented action log } - $b=new BlockedLog($this->db); $result = $b->setObjectData($object, $action, $amounts); // Set field date_object, ref_object, fk_object, element, object_data if ($result < 0) { diff --git a/htdocs/langs/en_US/blockedlog.lang b/htdocs/langs/en_US/blockedlog.lang index 19c919e1d0e..a047b9ff0f0 100644 --- a/htdocs/langs/en_US/blockedlog.lang +++ b/htdocs/langs/en_US/blockedlog.lang @@ -25,6 +25,7 @@ logBILL_DELETE=Customer bill deleted logMODULE_RESET=Module BlockedLog was disabled logMODULE_SET=Module BlockedLog was enabled BlockedlogInfoDialog=Log Details +ListOfTrackedEvents=List of tracked events Fingerprint=Fingerprint DownloadLogCSV=Download archive logs (CSV) logDOC_PREVIEW=Preview of a validated document in order to print or download From 5cd003973b8435ecb6a4c371a34452c8b4cdcb11 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 16 Dec 2017 22:36:28 +0100 Subject: [PATCH 20/27] Fix add payment when using multiple payment --- htdocs/blockedlog/class/blockedlog.class.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index becbe2bbe03..47a02074dc3 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -353,9 +353,15 @@ class BlockedLog $this->object_data->note = $object->note; //var_dump($this->object_data);exit; + $totalamount=0; + $paymentpartnumber=0; foreach($object->amounts as $invoiceid => $amount) { + if (empty($amount)) continue; + + $totalamount += $amount; + if ($this->element == 'payment_supplier') { $tmpinvoice = new FactureFournisseur($this->db); @@ -406,6 +412,8 @@ class BlockedLog $paymentpartnumber++; $this->object_data->payment_part[$paymentpartnumber] = $paymentpart; } + + $this->object_data->amount = $totalamount; } elseif($this->element == 'payment_salary') { From 8d671b2b26ea426519f517f822df28dc03c22f9a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 17 Dec 2017 16:24:47 +0100 Subject: [PATCH 21/27] Debug website module --- htdocs/core/lib/website.lib.php | 2 +- htdocs/theme/eldy/style.css.php | 4 +++ htdocs/theme/md/style.css.php | 4 +++ htdocs/website/index.php | 44 ++++++++++++++++++++++++++++----- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index 08fcdd82a58..9dc1b2c3863 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -39,7 +39,7 @@ function dolWebsiteReplacementOfLinks($website, $content, $removephppart=0) if ($removephppart) $replacewith=''; $content = preg_replace('/value="<\?php((?!\?>).)*\?>\n*/ims', 'value="'.$replacewith.'"', $content); - $replacewith='...php...'; + $replacewith='...php...'; if ($removephppart) $replacewith=''; $content = preg_replace('/<\?php((?!\?>).)*\?>\n*/ims', $replacewith, $content); diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index c275927daba..596d8624232 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -3468,6 +3468,10 @@ tr.visible { /* Module website */ /* ============================================================================== */ +.phptag { + background: #ddd; border: 1px solid #ccc; border-radius: 4px; +} + .nobordertransp { border: 0px; background-color: transparent; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index a1cc5789663..2773be6f3e5 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -3533,6 +3533,10 @@ tr.visible { /* Module website */ /* ============================================================================== */ +.phptag { + background: #ddd; border: 1px solid #ccc; border-radius: 4px; +} + .nobordertransp { border: 0px; background-color: transparent; diff --git a/htdocs/website/index.php b/htdocs/website/index.php index d84c8fec11b..37e87c6367f 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -110,6 +110,15 @@ if ($pageid < 0) $pageid = 0; if (($pageid > 0 || $pageref) && $action != 'addcontainer') { $res = $objectpage->fetch($pageid, ($object->id > 0 ? $object->id : null), $pageref); + // Check if pageid is inside the new website, if not we reset param pageid + if ($object->id > 0 && ($objectpage->fk_website != $object->id)) + { + $res = $objectpage->fetch(0, $object->id, '');; + if ($res == 0) // Page was not found, we reset it + { + $objectpage=new WebsitePage($db); + } + } $pageid = $objectpage->id; } @@ -1202,6 +1211,7 @@ $arrayofjs = array( '/includes/ace/ext-statusbar.js', '/includes/ace/ext-language_tools.js', //'/includes/ace/ext-chromevox.js' + //'/includes/jquery/plugins/jqueryscoped/jquery.scoped.js', ); $arrayofcss = array(); @@ -2016,11 +2026,30 @@ if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpa // REPLACEMENT OF LINKS When page called by website editor - $out.=')', $objectpage->htmlheader); + $tmpstyleinheader =''; + $i=0; + foreach($tmp as $valtmp) + { + $i++; + if ($i % 2 == 0) $tmpstyleinheader.=$valtmp."\n"; + } + //$tmpstyleinheader.=''; + //$pos=strpos($tmpstyleinheader, ']*>)+/ims','aaa', $tmpstyleinheader); + //$tmpstyleinheader = preg_replace('/().*$/ims','$1', $tmpstyleinheader); + //$tmpstyleinheader = preg_replace('/.*]*>/ims','', $tmpstyleinheader); + $tmpout.= $tmpstyleinheader."\n"; + // Clean style that may affect global style of Dolibarr + $tmpout=preg_replace('/}[\s\n]*body\s*{[^}]+}/ims','}',$tmpout); + $out.=$tmpout; $out.=''."\n"; // Do not enable the contenteditable when page was grabbed, ckeditor is removing span and adding borders, @@ -2032,10 +2061,13 @@ if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpa $out.='
'; - $out.='
'; + $out.='
'; $out.= "\n".''."\n\n"; + // For jqueryscoped (does not work as expected) + //$out.=""; + print $out; /*file_put_contents($filetpl, $out); From d6fb3aecbae33c3b69cbf15d3c0264492122efbc Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 17 Dec 2017 16:26:34 +0100 Subject: [PATCH 22/27] Clean code --- htdocs/website/index.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/htdocs/website/index.php b/htdocs/website/index.php index 37e87c6367f..c8b9cb27202 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -2040,12 +2040,6 @@ if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpa $i++; if ($i % 2 == 0) $tmpstyleinheader.=$valtmp."\n"; } - //$tmpstyleinheader.=''; - //$pos=strpos($tmpstyleinheader, ']*>)+/ims','aaa', $tmpstyleinheader); - //$tmpstyleinheader = preg_replace('/().*$/ims','$1', $tmpstyleinheader); - //$tmpstyleinheader = preg_replace('/.*]*>/ims','', $tmpstyleinheader); $tmpout.= $tmpstyleinheader."\n"; // Clean style that may affect global style of Dolibarr $tmpout=preg_replace('/}[\s\n]*body\s*{[^}]+}/ims','}',$tmpout); From 713af7f6df6fdd9668ae437835d58b305571221f Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 17 Dec 2017 20:25:45 +0100 Subject: [PATCH 23/27] Debug module website --- htdocs/website/index.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/website/index.php b/htdocs/website/index.php index c8b9cb27202..d716fd4a9ad 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -1698,7 +1698,11 @@ if ($action == 'editcss') // Common HTML header print ''; - print $langs->trans('WEBSITE_HTML_HEADER'); + $htmlhelp=$langs->trans("Example").' :
'; + $htmlhelp.='<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous" ></script>
'; + $htmlhelp.='<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js" integrity="sha256-T0Vest3yCU7pafRw9r+settMBX6JkKN06dqBnpQ8d30=" crossorigin="anonymous" ></script>
'; + $htmlhelp.='<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
'; + print $form->textwithpicto($langs->trans('WEBSITE_HTML_HEADER'), $htmlhelp, 1, 'help', '', 0, 2, 'htmlheadertooltip'); print ''; $doleditor=new DolEditor('WEBSITE_HTML_HEADER', $htmlheader, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); From 6f9822ddb39669b79df904a7bd4a81efca2c4712 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 17 Dec 2017 22:03:42 +0100 Subject: [PATCH 24/27] Fix link for payment no set --- htdocs/core/class/html.formmail.class.php | 37 +++++++++-------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index 6423d9709e9..a3a37c86e8c 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -853,30 +853,23 @@ class FormMail extends Form // Complete substitution array $paymenturl=''; - if (! empty($conf->global->PAYMENT_ADD_PAYMENT_URL) // Option to enable to add online link into __PERSONALIZED__ - || (! empty($conf->paypal->enabled) && ! empty($conf->global->PAYPAL_ADD_PAYMENT_URL)) - ) + if (empty($this->substit['__REF__'])) { - if (empty($this->substit['__REF__'])) - { - //$paymenturl='LinkToPayOnlineNotAvailableInThisContext'; - $paymenturl=''; - } - else - { - // Set the online payment message and url link into __PERSONALIZED__ key - require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; - $langs->load('paypal'); - $typeforonlinepayment='free'; - if ($this->param["models"]=='order_send') $typeforonlinepayment='order'; // TODO use detection on something else than template - if ($this->param["models"]=='facture_send') $typeforonlinepayment='invoice'; // TODO use detection on something else than template - if ($this->param["models"]=='member_send') $typeforonlinepayment='member'; // TODO use detection on something else than template - $url=getOnlinePaymentUrl(0, $typeforonlinepayment, $this->substit['__REF__']); - //$paymenturl=str_replace('\n',"\n",$langs->transnoentitiesnoconv("PredefinedMailContentLink",$url)); - $paymenturl=$url; - } + $paymenturl=''; } - $this->substit['__PERSONALIZED__']=$paymenturl; // deprecated + else + { + // Set the online payment url link into __ONLINE_PAYMENT_URL__ key + require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; + $langs->load('paypal'); + $typeforonlinepayment='free'; + if ($this->param["models"]=='order_send') $typeforonlinepayment='order'; // TODO use detection on something else than template + if ($this->param["models"]=='facture_send') $typeforonlinepayment='invoice'; // TODO use detection on something else than template + if ($this->param["models"]=='member_send') $typeforonlinepayment='member'; // TODO use detection on something else than template + $url=getOnlinePaymentUrl(0, $typeforonlinepayment, $this->substit['__REF__']); + $paymenturl=$url; + } + $this->substit['__ONLINE_PAYMENT_URL__']=$paymenturl; //Add lines substitution key from each line From 54db0d31b4292ef986fb03a7fbc8e7583e9a958d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 18 Dec 2017 11:32:24 +0100 Subject: [PATCH 25/27] Fix GETPOST for intcomma --- htdocs/core/lib/functions.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 6b563dab8b3..ea71f3e1100 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -516,7 +516,7 @@ function GETPOST($paramname, $check='none', $method=0, $filter=NULL, $options=NU if (! is_numeric($out)) { $out=''; } break; case 'intcomma': - if (preg_match('/[^0-9,]+/i',$out)) $out=''; + if (preg_match('/[^0-9,-]+/i',$out)) $out=''; break; case 'alpha': if (! is_array($out)) From 8e12551f17b993ae51b82cb51e37b551b55143ef Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 18 Dec 2017 11:55:34 +0100 Subject: [PATCH 26/27] Fix not employee must not appear on page to create salaries --- htdocs/compta/salaries/card.php | 3 ++- htdocs/compta/salaries/index.php | 3 ++- htdocs/core/class/html.form.class.php | 4 ++-- htdocs/user/class/user.class.php | 5 +++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/htdocs/compta/salaries/card.php b/htdocs/compta/salaries/card.php index a456777f631..608b5a737b0 100644 --- a/htdocs/compta/salaries/card.php +++ b/htdocs/compta/salaries/card.php @@ -255,7 +255,8 @@ if ($action == 'create') // Employee print ''; print fieldLabel('Employee','fk_user',1).''; - print $form->select_dolusers(GETPOST('fk_user','int'), 'fk_user', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'maxwidth300'); + $noactive=0; // We keep active and unactive users + print $form->select_dolusers(GETPOST('fk_user','int'), 'fk_user', 1, '', 0, '', '', 0, 0, 0, 'AND employee=1', 0, '', 'maxwidth300', $noactive); print ''; // Label diff --git a/htdocs/compta/salaries/index.php b/htdocs/compta/salaries/index.php index 2fee94c3216..47cafad0f0a 100644 --- a/htdocs/compta/salaries/index.php +++ b/htdocs/compta/salaries/index.php @@ -100,7 +100,7 @@ $salstatic = new PaymentSalary($db); $userstatic = new User($db); $accountstatic = new Account($db); -$sql = "SELECT u.rowid as uid, u.lastname, u.firstname, u.login, u.email, u.admin, u.salary as current_salary, u.fk_soc as fk_soc,"; +$sql = "SELECT u.rowid as uid, u.lastname, u.firstname, u.login, u.email, u.admin, u.salary as current_salary, u.fk_soc as fk_soc, u.statut as status,"; $sql.= " s.rowid, s.fk_user, s.amount, s.salary, s.label, s.datep as datep, s.datev as datev, s.fk_typepayment as type, s.num_payment, s.fk_bank,"; $sql.= " ba.rowid as bid, ba.ref as bref, ba.number as bnumber, ba.account_number, ba.fk_accountancy_journal, ba.label as blabel,"; $sql.= " pst.code as payment_code"; @@ -222,6 +222,7 @@ if ($result) $userstatic->login=$obj->login; $userstatic->email=$obj->email; $userstatic->societe_id=$obj->fk_soc; + $userstatic->statut=$obj->status; $salstatic->id=$obj->rowid; $salstatic->ref=$obj->rowid; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index b7ac69d0fc8..085b9874aeb 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1442,7 +1442,7 @@ class Form * @param array $exclude Array list of users id to exclude * @param int $disabled If select list must be disabled * @param array|string $include Array list of users id to include or 'hierarchy' to have only supervised users or 'hierarchyme' to have supervised + me - * @param array $enableonly Array list of users id to be enabled. If defined, it means that other must be disabled + * @param array $enableonly Array list of users id to be enabled. If defined, it means that others will be disabled * @param int $force_entity 0 or Id of environment to force * @param int $maxlength Maximum length of string into list (0=no limit) * @param int $showstatus 0=show user status only if status is disabled, 1=always show user status into label, -1=never show user status @@ -1481,7 +1481,7 @@ class Form $out=''; - // On recherche les utilisateurs + // Forge request to select users $sql = "SELECT DISTINCT u.rowid, u.lastname as lastname, u.firstname, u.statut, u.login, u.admin, u.entity"; if (! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity) { diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 5a103871058..e7b31400bc0 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -44,6 +44,7 @@ class User extends CommonObject public $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe public $id=0; + public $statut; public $ldap_sid; public $search_sid; public $employee; @@ -56,7 +57,7 @@ class User extends CommonObject public $address; public $zip; public $town; - public $state_id; + public $state_id; // The state/department public $state_code; public $state; public $office_phone; @@ -101,7 +102,6 @@ class User extends CommonObject public $datelastlogin; public $datepreviouslogin; - public $statut; public $photo; public $lang; @@ -2102,6 +2102,7 @@ class User extends CommonObject } $type=($this->societe_id?$langs->trans("External").$company:$langs->trans("Internal")); $label.= '
' . $langs->trans("Type") . ': ' . $type; + $label.= '
' . $langs->trans("Status").': '.$this->getLibStatut(0); $label.=''; // Info Login From 98b82d712a7bec67ea2a8643978bd778ca2487dd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 18 Dec 2017 12:43:03 +0100 Subject: [PATCH 27/27] NEW Revenue stamp can be a percent FIX Revenue stamp not visible on the transfer payment page --- htdocs/admin/dict.php | 17 +++++----- htdocs/compta/facture/card.php | 31 +++++++++++++++++-- htdocs/compta/facture/prelevement.php | 14 ++------- htdocs/core/class/html.formother.class.php | 8 ++--- .../install/mysql/data/llx_c_revenuestamp.sql | 8 ++++- .../install/mysql/migration/6.0.0-7.0.0.sql | 2 ++ .../mysql/tables/llx_c_revenuestamp.sql | 1 + htdocs/langs/en_US/admin.lang | 1 + 8 files changed, 57 insertions(+), 25 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index cf620fae65f..a1fc7c87d68 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -197,7 +197,7 @@ $tabsql[19]= "SELECT id as rowid, code, libelle, active FROM ".MAIN_DB_PREF $tabsql[20]= "SELECT rowid as rowid, code, libelle, active FROM ".MAIN_DB_PREFIX."c_input_method"; $tabsql[21]= "SELECT c.rowid as rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_availability AS c"; $tabsql[22]= "SELECT rowid as rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_input_reason"; -$tabsql[23]= "SELECT t.rowid as rowid, t.taux, c.label as country, c.code as country_code, t.fk_pays as country_id, t.note, t.active, t.accountancy_code_sell, t.accountancy_code_buy FROM ".MAIN_DB_PREFIX."c_revenuestamp as t, ".MAIN_DB_PREFIX."c_country as c WHERE t.fk_pays=c.rowid"; +$tabsql[23]= "SELECT t.rowid as rowid, t.taux, t.revenuestamp_type, c.label as country, c.code as country_code, t.fk_pays as country_id, t.note, t.active, t.accountancy_code_sell, t.accountancy_code_buy FROM ".MAIN_DB_PREFIX."c_revenuestamp as t, ".MAIN_DB_PREFIX."c_country as c WHERE t.fk_pays=c.rowid"; $tabsql[24]= "SELECT rowid as rowid, code, label, active FROM ".MAIN_DB_PREFIX."c_type_resource"; //$tabsql[25]= "SELECT rowid as rowid, label, type_template, private, position, topic, content_lines, content, active FROM ".MAIN_DB_PREFIX."c_email_templates WHERE entity IN (".getEntity('email_template').")"; $tabsql[26]= "SELECT rowid as rowid, code, label, short_label, active FROM ".MAIN_DB_PREFIX."c_units"; @@ -275,7 +275,7 @@ $tabfield[19]= "code,libelle"; $tabfield[20]= "code,libelle"; $tabfield[21]= "code,label"; $tabfield[22]= "code,label"; -$tabfield[23]= "country_id,country,taux,accountancy_code_sell,accountancy_code_buy,note"; +$tabfield[23]= "country_id,country,taux,revenuestamp_type,accountancy_code_sell,accountancy_code_buy,note"; $tabfield[24]= "code,label"; //$tabfield[25]= "label,type_template,private,position,topic,content_lines,content"; $tabfield[26]= "code,label,short_label"; @@ -314,7 +314,7 @@ $tabfieldvalue[19]= "code,libelle"; $tabfieldvalue[20]= "code,libelle"; $tabfieldvalue[21]= "code,label"; $tabfieldvalue[22]= "code,label"; -$tabfieldvalue[23]= "country,taux,accountancy_code_sell,accountancy_code_buy,note"; +$tabfieldvalue[23]= "country,taux,revenuestamp_type,accountancy_code_sell,accountancy_code_buy,note"; $tabfieldvalue[24]= "code,label"; //$tabfieldvalue[25]= "label,type_template,private,position,topic,content_lines,content"; $tabfieldvalue[26]= "code,label,short_label"; @@ -353,7 +353,7 @@ $tabfieldinsert[19]= "code,libelle"; $tabfieldinsert[20]= "code,libelle"; $tabfieldinsert[21]= "code,label"; $tabfieldinsert[22]= "code,label"; -$tabfieldinsert[23]= "fk_pays,taux,accountancy_code_sell,accountancy_code_buy,note"; +$tabfieldinsert[23]= "fk_pays,taux,revenuestamp_type,accountancy_code_sell,accountancy_code_buy,note"; $tabfieldinsert[24]= "code,label"; //$tabfieldinsert[25]= "label,type_template,private,position,topic,content_lines,content,entity"; $tabfieldinsert[26]= "code,label,short_label"; @@ -472,7 +472,7 @@ $tabhelp[19] = array('code'=>$langs->trans("EnterAnyCode")); $tabhelp[20] = array('code'=>$langs->trans("EnterAnyCode")); $tabhelp[21] = array('code'=>$langs->trans("EnterAnyCode")); $tabhelp[22] = array('code'=>$langs->trans("EnterAnyCode")); -$tabhelp[23] = array(); +$tabhelp[23] = array('revenuestamp_type'=>'FixedOfPercent'); $tabhelp[24] = array('code'=>$langs->trans("EnterAnyCode")); //$tabhelp[25] = array('topic'=>$langs->trans('SeeSubstitutionVars'),'content'=>$langs->trans('SeeSubstitutionVars'),'content_lines'=>$langs->trans('SeeSubstitutionVars'),'type_template'=>$langs->trans("TemplateForElement"),'private'=>$langs->trans("TemplateIsVisibleByOwnerOnly"), 'position'=>$langs->trans("PositionIntoComboList")); $tabhelp[26] = array('code'=>$langs->trans("EnterAnyCode")); @@ -651,6 +651,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) if ($fieldnamekey == 'deductible') $fieldnamekey = 'Deductible'; if ($fieldnamekey == 'sortorder') $fieldnamekey = 'SortOrder'; if ($fieldnamekey == 'category_type') $fieldnamekey = 'Calculated'; + if ($fieldnamekey == 'revenuestamp_type') $fieldnamekey = 'TypeOfRevenueStamp'; setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities($fieldnamekey)), null, 'errors'); } @@ -1117,7 +1118,8 @@ if ($id) if ($fieldlist[$field]=='newbymonth') { $valuetoshow=$langs->trans("NewByMonth"); } if ($fieldlist[$field]=='fk_tva') { $valuetoshow=$langs->trans("VAT"); } if ($fieldlist[$field]=='range_ik') { $valuetoshow=$langs->trans("RangeIk"); } - if ($fieldlist[$field]=='fk_c_exp_tax_cat'){ $valuetoshow=$langs->trans("CarCategory"); } + if ($fieldlist[$field]=='fk_c_exp_tax_cat') { $valuetoshow=$langs->trans("CarCategory"); } + if ($fieldlist[$field]=='revenuestamp_type') { $valuetoshow=$langs->trans('TypeOfRevenueStamp'); } if ($id == 2) // Special cas for state page { @@ -1343,7 +1345,8 @@ if ($id) if ($fieldlist[$field]=='newbymonth') { $valuetoshow=$langs->trans("NewByMonth"); } if ($fieldlist[$field]=='fk_tva') { $valuetoshow=$langs->trans("VAT"); } if ($fieldlist[$field]=='range_ik') { $valuetoshow=$langs->trans("RangeIk"); } - if ($fieldlist[$field]=='fk_c_exp_tax_cat'){ $valuetoshow=$langs->trans("CarCategory"); } + if ($fieldlist[$field]=='fk_c_exp_tax_cat') { $valuetoshow=$langs->trans("CarCategory"); } + if ($fieldlist[$field]=='revenuestamp_type') { $valuetoshow=$langs->trans('TypeOfRevenueStamp'); } // Affiche nom du champ if ($showfield) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 50ff7059f91..6def698a916 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -3707,10 +3707,37 @@ else if ($id > 0 || ! empty($ref)) print '
'; print ''; print ''; - print $formother->select_revenue_stamp(GETPOST('revenuestamp'), 'revenuestamp', $mysoc->country_code); - // print ''; + print ''; + print $formother->select_revenue_stamp('', 'revenuestamp_type', $mysoc->country_code); + print ' → '; print ' '; print '
'; + print " "; } else { print price($object->revenuestamp, 1, '', 1, - 1, - 1, $conf->currency); } diff --git a/htdocs/compta/facture/prelevement.php b/htdocs/compta/facture/prelevement.php index 8daee472e9e..cdeda46b768 100644 --- a/htdocs/compta/facture/prelevement.php +++ b/htdocs/compta/facture/prelevement.php @@ -120,6 +120,8 @@ $form = new Form($db); if ($object->id > 0) { + $selleruserevenustamp = $mysoc->useRevenueStamp(); + $totalpaye = $object->getSommePaiement(); $totalcreditnotes = $object->getSumCreditNotesUsed(); $totaldeposits = $object->getSumDepositsUsed(); @@ -486,17 +488,7 @@ if ($object->id > 0) } print ''; print ''; - if ($action == 'editrevenuestamp') { - print '
'; - print ''; - print ''; - print $formother->select_revenue_stamp(GETPOST('revenuestamp'), 'revenuestamp', $mysoc->country_code); - // print ''; - print ' '; - print '
'; - } else { - print price($object->revenuestamp, 1, '', 1, - 1, - 1, $conf->currency); - } + print price($object->revenuestamp, 1, '', 1, - 1, - 1, $conf->currency); print ''; } diff --git a/htdocs/core/class/html.formother.class.php b/htdocs/core/class/html.formother.class.php index 565cd4310b4..dfd70a075f0 100644 --- a/htdocs/core/class/html.formother.class.php +++ b/htdocs/core/class/html.formother.class.php @@ -222,7 +222,7 @@ class FormOther $out=''; - $sql = "SELECT r.taux"; + $sql = "SELECT r.taux, r.revenuestamp_type"; $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."'"; @@ -242,14 +242,14 @@ class FormOther $obj = $this->db->fetch_object($resql); if (($selected && $selected == $obj->taux) || $num == 1) { - $out.=''; $i++; } diff --git a/htdocs/install/mysql/data/llx_c_revenuestamp.sql b/htdocs/install/mysql/data/llx_c_revenuestamp.sql index 040a8370485..ee4e9ab7873 100644 --- a/htdocs/install/mysql/data/llx_c_revenuestamp.sql +++ b/htdocs/install/mysql/data/llx_c_revenuestamp.sql @@ -27,4 +27,10 @@ delete from llx_c_revenuestamp; -- TUNISIA (id country=10) -- -insert into llx_c_revenuestamp(rowid,fk_pays,taux,note,active) values (101, 10, 0.4, 'Revenue stamp tunisia', 1); +insert into llx_c_revenuestamp(rowid,fk_pays,taux,revenuestamp_type,note,active) values (101, 10, 0.4, 'fixed', 'Revenue stamp tunisia', 1); + + +-- MEXICO (id country=154) -- +insert into llx_c_revenuestamp(rowid,fk_pays,taux,revenuestamp_type,note,active) values (1541, 154, 1.5, 'percent', 'Revenue stamp mexico', 1); +insert into llx_c_revenuestamp(rowid,fk_pays,taux,revenuestamp_type,note,active) values (1542, 154, 3, 'percent', 'Revenue stamp mexico', 1); + 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 dbff8454417..f042cb83556 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 @@ -71,6 +71,8 @@ ALTER TABLE llx_website_page ADD COLUMN type_container varchar(16) NOT NULL DEFA -- For 7.0 +ALTER TABLE llx_c_revenuestamp ADD COLUMN revenuestamp_type varchar(16) DEFAULT 'fixed' NOT NULL; + UPDATE llx_contrat SET ref = rowid WHERE ref IS NULL OR ref = ''; ALTER TABLE llx_contratdet ADD COLUMN vat_src_code varchar(10) DEFAULT ''; diff --git a/htdocs/install/mysql/tables/llx_c_revenuestamp.sql b/htdocs/install/mysql/tables/llx_c_revenuestamp.sql index 0eb5a46216d..9bdff7f0053 100644 --- a/htdocs/install/mysql/tables/llx_c_revenuestamp.sql +++ b/htdocs/install/mysql/tables/llx_c_revenuestamp.sql @@ -21,6 +21,7 @@ create table llx_c_revenuestamp rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, fk_pays integer NOT NULL, taux double NOT NULL, + revenuestamp_type varchar(16) DEFAULT 'fixed' NOT NULL, note varchar(128), active tinyint DEFAULT 1 NOT NULL, accountancy_code_sell varchar(32) DEFAULT NULL, diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 372d1a40aca..a4ece445581 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -904,6 +904,7 @@ SetupSaved=Setup saved SetupNotSaved=Setup not saved BackToModuleList=Back to modules list BackToDictionaryList=Back to dictionaries list +TypeOfRevenueStamp=Type of revenue stamp VATManagement=VAT Management VATIsUsedDesc=By default when creating prospects, invoices, orders etc the VAT rate follows the active standard rule:
If the seller is not subjected to VAT, then VAT defaults to 0. End of rule.
If the (selling country= buying country), then the VAT by default equals the VAT of the product in the selling country. End of rule.
If seller and buyer are both in the European Community and goods are transport products (car, ship, plane), the default VAT is 0 ( The VAT should be paid by the buyer to the customoffice of his country and not to the seller). End of rule.
If seller and buyer are both in the European Community and the buyer is not a company, then the VAT by defaults to the VAT of the product sold. End of rule.
If seller and buyer are both in the European Community and the buyer is a company, then the VAT is 0 by default . End of rule.
In any othe case the proposed default is VAT=0. End of rule. VATIsNotUsedDesc=By default the proposed VAT is 0 which can be used for cases like associations, individuals ou small companies.