1<?php
2/* Copyright (C) 2004       Rodolphe Quiedeville    <rodolphe@quiedeville.org>
3 * Copyright (C) 2010       Laurent Destailleur     <eldy@users.sourceforge.net>
4 * Copyright (C) 2019       Alexandre Spangaro      <aspangaro@open-dsi.fr>
5 * Copyright (C) 2019       Frédéric France         <frederic.france@netlogic.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * or see https://www.gnu.org/
20 */
21
22/**
23 *      \file       htdocs/core/modules/societe/mod_codecompta_digitaria.php
24 *      \ingroup    societe
25 *      \brief      File of class to manage accountancy code of thirdparties with Digitaria rules
26 */
27require_once DOL_DOCUMENT_ROOT.'/core/modules/societe/modules_societe.class.php';
28
29
30/**
31 *		Class to manage accountancy code of thirdparties with Digitaria rules
32 */
33class mod_codecompta_digitaria extends ModeleAccountancyCode
34{
35	/**
36	 * @var string model name
37	 */
38	public $name = 'Digitaria';
39
40	/**
41	 * Dolibarr version of the loaded document
42	 * @var string
43	 */
44	public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr'
45
46	/**
47	 * Prefix customer accountancy code
48	 * @var string
49	 */
50	public $prefixcustomeraccountancycode;
51
52	/**
53	 * Prefix supplier accountancy code
54	 * @var string
55	 */
56	public $prefixsupplieraccountancycode;
57
58	public $position = 30;
59
60
61	/**
62	 * 	Constructor
63	 */
64	public function __construct()
65	{
66		global $conf, $langs;
67		if (!isset($conf->global->COMPANY_DIGITARIA_MASK_CUSTOMER) || trim($conf->global->COMPANY_DIGITARIA_MASK_CUSTOMER) == '') {
68			$conf->global->COMPANY_DIGITARIA_MASK_CUSTOMER = '411';
69		}
70		if (!isset($conf->global->COMPANY_DIGITARIA_MASK_SUPPLIER) || trim($conf->global->COMPANY_DIGITARIA_MASK_SUPPLIER) == '') {
71			$conf->global->COMPANY_DIGITARIA_MASK_SUPPLIER = '401';
72		}
73		$this->prefixcustomeraccountancycode = $conf->global->COMPANY_DIGITARIA_MASK_CUSTOMER;
74		$this->prefixsupplieraccountancycode = $conf->global->COMPANY_DIGITARIA_MASK_SUPPLIER;
75
76		if (!isset($conf->global->COMPANY_DIGITARIA_MASK_NBCHARACTER_CUSTOMER) || trim($conf->global->COMPANY_DIGITARIA_MASK_NBCHARACTER_CUSTOMER) == '') {
77			$conf->global->COMPANY_DIGITARIA_MASK_NBCHARACTER_CUSTOMER = '5';
78		}
79		if (!isset($conf->global->COMPANY_DIGITARIA_MASK_NBCHARACTER_SUPPLIER) || trim($conf->global->COMPANY_DIGITARIA_MASK_NBCHARACTER_SUPPLIER) == '') {
80			$conf->global->COMPANY_DIGITARIA_MASK_NBCHARACTER_SUPPLIER = '5';
81		}
82		$this->customeraccountancycodecharacternumber = $conf->global->COMPANY_DIGITARIA_MASK_NBCHARACTER_CUSTOMER;
83		$this->supplieraccountancycodecharacternumber = $conf->global->COMPANY_DIGITARIA_MASK_NBCHARACTER_SUPPLIER;
84	}
85
86	/**
87	 * Return description of module
88	 *
89	 * @param	Translate	$langs	Object langs
90	 * @return 	string      		Description of module
91	 */
92	public function info($langs)
93	{
94		global $conf, $form;
95
96		$tooltip = '';
97		$texte = '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
98		$texte .= '<input type="hidden" name="token" value="'.newToken().'">';
99		$texte .= '<input type="hidden" name="action" value="setModuleOptions">';
100		$texte .= '<input type="hidden" name="param1" value="COMPANY_DIGITARIA_MASK_SUPPLIER">';
101		$texte .= '<input type="hidden" name="param2" value="COMPANY_DIGITARIA_MASK_CUSTOMER">';
102		$texte .= '<input type="hidden" name="param3" value="COMPANY_DIGITARIA_MASK_NBCHARACTER_SUPPLIER">';
103		$texte .= '<input type="hidden" name="param4" value="COMPANY_DIGITARIA_MASK_NBCHARACTER_CUSTOMER">';
104		$texte .= '<table class="nobordernopadding" width="100%">';
105		$s1 = $form->textwithpicto('<input type="text" class="flat" size="4" name="value1" value="'.$conf->global->COMPANY_DIGITARIA_MASK_SUPPLIER.'">', $tooltip, 1, 1);
106		$s2 = $form->textwithpicto('<input type="text" class="flat" size="4" name="value2" value="'.$conf->global->COMPANY_DIGITARIA_MASK_CUSTOMER.'">', $tooltip, 1, 1);
107		$s3 = $form->textwithpicto('<input type="text" class="flat" size="2" name="value3" value="'.$conf->global->COMPANY_DIGITARIA_MASK_NBCHARACTER_SUPPLIER.'">', $tooltip, 1, 1);
108		$s4 = $form->textwithpicto('<input type="text" class="flat" size="2" name="value4" value="'.$conf->global->COMPANY_DIGITARIA_MASK_NBCHARACTER_CUSTOMER.'">', $tooltip, 1, 1);
109		$texte .= '<tr><td>';
110		// trans remove html entities
111		$texte .= $langs->trans("ModuleCompanyCodeCustomer".$this->name, '{s2}', '{s4}')."<br>\n";
112		$texte .= $langs->trans("ModuleCompanyCodeSupplier".$this->name, '{s1}', '{s3}')."<br>\n";
113		$texte = str_replace(array('{s1}', '{s2}', '{s3}', '{s4}'), array($s1, $s2, $s3, $s4), $texte);
114		$texte .= "<br>\n";
115		// Remove special char if COMPANY_DIGITARIA_REMOVE_SPECIAL is set to 1 or not set (default)
116		if (!isset($conf->global->COMPANY_DIGITARIA_REMOVE_SPECIAL) || !empty($conf->global->$conf->global->COMPANY_DIGITARIA_REMOVE_SPECIAL)) {
117			$texte .= $langs->trans('RemoveSpecialChars').' = '.yn(1)."<br>\n";
118		}
119		// Apply a regex replacement pattern on code if COMPANY_DIGITARIA_CLEAN_REGEX is set. Value must be a regex with parenthesis. The part into parenthesis is kept, the rest removed.
120		if (!empty($conf->global->COMPANY_DIGITARIA_CLEAN_REGEX)) {
121			$texte .= $langs->trans('COMPANY_DIGITARIA_CLEAN_REGEX').' = '.$conf->global->COMPANY_DIGITARIA_CLEAN_REGEX."<br>\n";
122		}
123		// Unique index on code if COMPANY_DIGITARIA_UNIQUE_CODE is set to 1 or not set (default)
124		if (!isset($conf->global->COMPANY_DIGITARIA_UNIQUE_CODE) || !empty($conf->global->COMPANY_DIGITARIA_UNIQUE_CODE)) {
125			$texte .= $langs->trans('COMPANY_DIGITARIA_UNIQUE_CODE').' = '.yn(1)."<br>\n";
126		}
127		$texte .= '</td>';
128		$texte .= '<td class="right"><input type="submit" class="button" value="'.$langs->trans("Modify").'" name="Button"></td>';
129		$texte .= '</tr></table>';
130		$texte .= '</form>';
131
132		return $texte;
133	}
134
135	/**
136	 *  Return an example of result returned by getNextValue
137	 *
138	 *  @param	Translate	$langs		Object langs
139	 *  @param	Societe		$objsoc		Object thirdparty
140	 *  @param	int			$type		Type of third party (1:customer, 2:supplier, -1:autodetect)
141	 *  @return	string					Example
142	 */
143	public function getExample($langs, $objsoc = 0, $type = -1)
144	{
145		global $conf, $mysoc;
146
147		$s = $langs->trans("ThirdPartyName").": ".$mysoc->name;
148		$s .= "<br>\n";
149
150		if (!isset($conf->global->COMPANY_DIGITARIA_REMOVE_SPECIAL)) {
151			$thirdpartylabelexample = preg_replace('/([^a-z0-9])/i', '', $mysoc->name);
152		}
153		$s .= "<br>\n";
154		$s .= $this->prefixcustomeraccountancycode.strtoupper(substr($thirdpartylabelexample, 0, $this->customeraccountancycodecharacternumber));
155		$s .= "<br>\n";
156		$s .= $this->prefixsupplieraccountancycode.strtoupper(substr($thirdpartylabelexample, 0, $this->supplieraccountancycodecharacternumber));
157		return $s;
158	}
159
160	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
161	/**
162	 *  Set accountancy account code for a third party into this->code
163	 *
164	 *  @param	DoliDB	$db              Database handler
165	 *  @param  Societe	$societe         Third party object
166	 *  @param  int		$type			'customer' or 'supplier'
167	 *  @return	int						>=0 if OK, <0 if KO
168	 */
169	public function get_code($db, $societe, $type = '')
170	{
171		// phpcs:enable
172		global $conf;
173		$i = 0;
174		$this->code = '';
175
176		$disponibility = 0;
177
178		if (is_object($societe)) {
179			dol_syslog("mod_codecompta_digitaria::get_code search code for type=".$type." & company=".(!empty($societe->name) ? $societe->name : ''));
180
181			if ($type == 'supplier') {
182				$codetouse = $societe->name;
183				$prefix = $this->prefixsupplieraccountancycode;
184				$width = $this->supplieraccountancycodecharacternumber;
185			} elseif ($type == 'customer') {
186				$codetouse = $societe->name;
187				$prefix = $this->prefixcustomeraccountancycode;
188				$width = $this->customeraccountancycodecharacternumber;
189			} else {
190				$this->error = 'Bad value for parameter type';
191				return -1;
192			}
193
194			// Remove special char if COMPANY_DIGITARIA_REMOVE_SPECIAL is set to 1 or not set (default)
195			if (!isset($conf->global->COMPANY_DIGITARIA_REMOVE_SPECIAL) || !empty($conf->global->COMPANY_DIGITARIA_REMOVE_SPECIAL)) {
196				$codetouse = preg_replace('/([^a-z0-9])/i', '', $codetouse);
197			}
198			// Apply a regex replacement pattern on code if COMPANY_DIGITARIA_CLEAN_REGEX is set. Value must be a regex with parenthesis. The part into parenthesis is kept, the rest removed.
199			if (!empty($conf->global->COMPANY_DIGITARIA_CLEAN_REGEX)) {	// Example: $conf->global->COMPANY_DIGITARIA_CLEAN_REGEX='^..(..)..';
200				$codetouse = preg_replace('/'.$conf->global->COMPANY_DIGITARIA_CLEAN_REGEX.'/', '\1\2\3', $codetouse);
201			}
202
203			$this->code = $prefix.strtoupper(substr($codetouse, 0, $width));
204			dol_syslog("mod_codecompta_digitaria::get_code search code proposed=".$this->code);
205
206			// Unique index on code if COMPANY_DIGITARIA_UNIQUE_CODE is set to 1 or not set (default)
207			if (!isset($conf->global->COMPANY_DIGITARIA_UNIQUE_CODE) || !empty($conf->global->COMPANY_DIGITARIA_UNIQUE_CODE)) {
208				$disponibility = $this->checkIfAccountancyCodeIsAlreadyUsed($db, $this->code, $type);
209
210				while ($disponibility <> 0 && $i < 1000) {
211					$widthsupplier = $this->supplieraccountancycodecharacternumber;
212					$widthcustomer = $this->customeraccountancycodecharacternumber;
213
214					if ($i <= 9) {
215						$a = 1;
216					}
217					if ($i >= 10 && $i <= 99) {
218						$a = 2;
219					}
220					if ($i >= 100 && $i <= 999) {
221						$a = 3;
222					}
223
224					if ($type == 'supplier') {
225						$this->code = $prefix.strtoupper(substr($codetouse, 0, $widthsupplier - $a)).$i;
226					} elseif ($type == 'customer') {
227						$this->code = $prefix.strtoupper(substr($codetouse, 0, $widthcustomer - $a)).$i;
228					}
229					$disponibility = $this->checkIfAccountancyCodeIsAlreadyUsed($db, $this->code, $type);
230
231					$i++;
232				}
233			} else {
234				$disponibility == 0;
235			}
236		}
237
238		if ($disponibility == 0) {
239			return 0; // return ok
240		} else {
241			return -1; // return ko
242		}
243	}
244
245	/**
246	 *  Check accountancy account code for a third party into this->code
247	 *
248	 *  @param	DoliDB	$db             Database handler
249	 *  @param  string	$code           Code of third party
250	 *  @param  int		$type			'customer' or 'supplier'
251	 *  @return	int						>=0 if OK, <0 if KO
252	 */
253	public function checkIfAccountancyCodeIsAlreadyUsed($db, $code, $type = '')
254	{
255		if ($type == 'supplier') {
256			$typethirdparty = 'code_compta_fournisseur';
257		} elseif ($type == 'customer') {
258			$typethirdparty = 'code_compta';
259		} else {
260			$this->error = 'Bad value for parameter type';
261			return -1;
262		}
263
264		$sql = "SELECT ".$typethirdparty." FROM ".MAIN_DB_PREFIX."societe";
265		$sql .= " WHERE ".$typethirdparty." = '".$db->escape($code)."'";
266
267		$resql = $db->query($sql);
268		if ($resql) {
269			if ($db->num_rows($resql) == 0) {
270				dol_syslog("mod_codecompta_digitaria::checkIfAccountancyCodeIsAlreadyUsed '".$code."' available");
271				return 0; // Available
272			} else {
273				dol_syslog("mod_codecompta_digitaria::checkIfAccountancyCodeIsAlreadyUsed '".$code."' not available");
274				return -1; // Not available
275			}
276		} else {
277			$this->error = $db->error()." sql=".$sql;
278			return -2; // Error
279		}
280	}
281}
282