Passed
Branch develop (356b3a)
by
unknown
98:06
created

Societe   F

Complexity

Total Complexity 878

Size/Duplication

Total Lines 5133
Duplicated Lines 0 %

Importance

Changes 4
Bugs 1 Features 0
Metric Value
eloc 2614
dl 0
loc 5133
rs 0.8
c 4
b 1
f 0
wmc 878

74 Methods

Rating   Name   Duplication   Size   Complexity  
B set_remise_except() 0 59 7
A set_as_client() 0 21 5
A del_commercial() 0 17 5
F verify() 0 116 42
A getAvailableDiscounts() 0 11 2
F fetch() 0 278 44
A __construct() 0 19 2
B add_commercial() 0 50 10
B getSalesRepresentatives() 0 58 8
A set_remise_supplier() 0 50 5
F delete() 0 143 30
A setPriceLevel() 0 25 4
C create_individual() 0 65 12
F update() 0 428 128
A set_remise_client() 0 48 5
F create() 0 169 33
A has_projects() 0 14 2
A thirdparty_and_contact_phone_array() 0 15 3
B codefournisseur_modifiable() 0 30 9
D getTypeUrl() 0 21 18
B setNoEmail() 0 49 8
B get_codecompta() 0 43 9
A getLibProspLevel() 0 3 1
A contact_array() 0 21 4
A isInEEC() 0 4 1
A getNbOfEMailings() 0 17 2
F getTooltipContentArray() 0 125 60
A get_all_rib() 0 21 4
A LibCustProspStatut() 0 17 5
A setThirdpartyType() 0 18 3
A useNPR() 0 13 2
A LibProspLevel() 0 11 2
A useRevenueStamp() 0 15 3
F getOutstandingBills() 0 82 18
B codeclient_modifiable() 0 30 9
A fetchPartnerships() 0 10 1
A contact_array_objects() 0 24 4
A replaceThirdparty() 0 36 3
B getOutstandingOrders() 0 34 6
F create_from_member() 0 90 19
C id_prof_exists() 0 49 14
A AddFournisseurInCategory() 0 14 4
D contact_property_array() 0 56 18
A thirdparty_and_contact_email_array() 0 14 4
A getLibCustProspStatut() 0 3 1
A LibStatut() 0 19 4
D id_prof_url() 0 45 17
A validateFamilyTree() 0 23 5
A getLibProspCommStatut() 0 3 1
A info() 0 25 4
A getNoEmail() 0 16 3
A setAccountancyCode() 0 42 5
B setParent() 0 29 7
F getNomUrl() 0 146 57
C id_prof_verifiable() 0 29 13
A LoadSupplierCateg() 0 16 3
B setSalesRep() 0 37 8
F setMysoc() 0 120 21
A get_codeclient() 0 20 4
A check_codefournisseur() 0 26 5
A contact_get_property() 0 32 6
D LibProspCommStatut() 0 51 39
B getOutstandingProposals() 0 35 6
A initAsSpecimen() 0 49 1
A get_codefournisseur() 0 19 4
A display_rib() 0 26 6
A getLibStatut() 0 3 1
C isACompany() 0 20 12
A check_codeclient() 0 26 5
A setCategories() 0 11 2
F id_prof_check() 0 179 41
A useLocalTax() 0 19 5
B generateDocument() 0 42 8
A getParentsForCompany() 0 20 6

How to fix   Complexity   

Complex Class

Complex classes like Societe often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Societe, and based on these observations, apply Extract Interface, too.

1
<?php
2
/* Copyright (C) 2002-2006  Rodolphe Quiedeville    <[email protected]>
3
 * Copyright (C) 2004-2021  Laurent Destailleur     <[email protected]>
4
 * Copyright (C) 2004       Eric Seigne             <[email protected]>
5
 * Copyright (C) 2003       Brian Fraval            <[email protected]>
6
 * Copyright (C) 2006       Andre Cianfarani        <[email protected]>
7
 * Copyright (C) 2005-2017  Regis Houssin           <[email protected]>
8
 * Copyright (C) 2008       Patrick Raguin          <[email protected]>
9
 * Copyright (C) 2010-2018  Juanjo Menent           <[email protected]>
10
 * Copyright (C) 2013       Florian Henry           <[email protected]>
11
 * Copyright (C) 2013-2021  Alexandre Spangaro      <[email protected]>
12
 * Copyright (C) 2013       Peter Fontaine          <[email protected]>
13
 * Copyright (C) 2014-2015  Marcos García           <[email protected]>
14
 * Copyright (C) 2015       Raphaël Doursenaud      <[email protected]>
15
 * Copyright (C) 2017       Rui Strecht			    <[email protected]>
16
 * Copyright (C) 2018	    Philippe Grand	        <[email protected]>
17
 * Copyright (C) 2019-2020  Josep Lluís Amador      <[email protected]>
18
 * Copyright (C) 2019-2023  Frédéric France         <[email protected]>
19
 * Copyright (C) 2020       Open-Dsi         		<[email protected]>
20
 * Copyright (C) 2022		ButterflyOfFire         <[email protected]>
21
 *
22
 * This program is free software; you can redistribute it and/or modify
23
 * it under the terms of the GNU General Public License as published by
24
 * the Free Software Foundation; either version 3 of the License, or
25
 * (at your option) any later version.
26
 *
27
 * This program is distributed in the hope that it will be useful,
28
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30
 * GNU General Public License for more details.
31
 *
32
 * You should have received a copy of the GNU General Public License
33
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
34
 */
35
36
/**
37
 *	\file       htdocs/societe/class/societe.class.php
38
 *	\ingroup    societe
39
 *	\brief      File for third party class
40
 */
41
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
42
require_once DOL_DOCUMENT_ROOT.'/core/class/commonincoterm.class.php';
43
require_once DOL_DOCUMENT_ROOT.'/core/class/commonsocialnetworks.class.php';
44
require_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
45
46
47
/**
48
 *	Class to manage third parties objects (customers, suppliers, prospects...)
49
 */
50
class Societe extends CommonObject
51
{
52
	use CommonIncoterm;
53
	use CommonSocialNetworks;
54
55
	/**
56
	 * @var string ID to identify managed object
57
	 */
58
	public $element = 'societe';
59
60
	/**
61
	 * @var string Name of table without prefix where object is stored
62
	 */
63
	public $table_element = 'societe';
64
65
	/**
66
	 * @var string Field with ID of parent key if this field has a parent or for child tables
67
	 */
68
	public $fk_element = 'fk_soc';
69
70
	/**
71
	 * @var string Fields for combobox
72
	 */
73
	public $fieldsforcombobox = 'nom,name_alias';
74
75
	/**
76
	 * @var array	List of child tables. To test if we can delete object.
77
	 */
78
	protected $childtables = array(
79
		'supplier_proposal' => array('name' => 'SupplierProposal'),
80
		'propal' => array('name' => 'Proposal'),
81
		'commande' => array('name' => 'Order'),
82
		'facture' => array('name' => 'Invoice'),
83
		'facture_rec' => array('name' => 'RecurringInvoiceTemplate'),
84
		'contrat' => array('name' => 'Contract'),
85
		'fichinter' => array('name' => 'Fichinter'),
86
		'facture_fourn' => array('name' => 'SupplierInvoice'),
87
		'commande_fournisseur' => array('name' => 'SupplierOrder'),
88
		'projet' => array('name' => 'Project'),
89
		'expedition' => array('name' => 'Shipment'),
90
		'prelevement_lignes' => array('name' => 'DirectDebitRecord'),
91
	);
92
93
	/**
94
	 * @var array    List of child tables. To know object to delete on cascade.
95
	 *               if name like with @ClassName:FilePathClass:ParentFkFieldName' it will call method deleteByParentField (with parentId as parameters) and FieldName to fetch and delete child object
96
	 */
97
	protected $childtablesoncascade = array(
98
		'societe_prices',
99
		'societe_address',
100
		'product_fournisseur_price',
101
		'product_customer_price_log',
102
		'product_customer_price',
103
		'@Contact:/contact/class/contact.class.php:fk_soc',
104
		'adherent',
105
		'societe_account',
106
		'societe_rib',
107
		'societe_remise',
108
		'societe_remise_except',
109
		'societe_commerciaux',
110
		'categorie',
111
		'notify',
112
		'notify_def',
113
		'actioncomm',
114
	);
115
116
	/**
117
	 * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
118
	 */
119
	public $picto = 'company';
120
121
	/**
122
	 * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
123
	 * @var int
124
	 */
125
	public $ismultientitymanaged = 1;
126
127
	/**
128
	 * 0=Default, 1=View may be restricted to sales representative only if no permission to see all or to company of external user if external user
129
	 * @var integer
130
	 */
131
	public $restrictiononfksoc = 1;
132
133
	/**
134
	 * @var Societe To store a cloned copy of object before to edit it and keep track of old properties
135
	 */
136
	public $oldcopy;
137
138
	/**
139
	 * array of supplier categories
140
	 * @var array
141
	 */
142
	public $SupplierCategories = array();
143
144
	/**
145
	 * prefixCustomerIsRequired
146
	 * @var int
147
	 */
148
	public $prefixCustomerIsRequired;
149
150
	/**
151
	 *  'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter]]', 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter]]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password')
152
	 *         Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)"
153
	 *  'label' the translation key.
154
	 *  'picto' is code of a picto to show before value in forms
155
	 *  'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM)
156
	 *  'position' is the sort order of field.
157
	 *  'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0).
158
	 *  'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing)
159
	 *  'noteditable' says if field is not editable (1 or 0)
160
	 *  'default' is a default value for creation (can still be overwrote by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created.
161
	 *  'index' if we want an index in database.
162
	 *  'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...).
163
	 *  'searchall' is 1 if we want to search in this field when making a search from the quick search button.
164
	 *  'isameasure' must be set to 1 if you want to have a total on list for this field. Field type must be summable like integer or double(24,8).
165
	 *  'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'maxwidth200', 'wordbreak', 'tdoverflowmax200'
166
	 *  'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click.
167
	 *  'showoncombobox' if value of the field must be visible into the label of the combobox that list record
168
	 *  'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code.
169
	 *  'arrayofkeyval' to set list of value if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel")
170
	 *  'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1.
171
	 *  'comment' is not used. You can store here any text of your choice. It is not used by application.
172
	 *
173
	 *  Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor.
174
	 */
175
176
	/**
177
	 * @var array  Array with all fields and their property. Do not use it as a static var. It may be modified by constructor.
178
	 */
179
	public $fields = array(
180
		'rowid' =>array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>10),
181
		'parent' =>array('type'=>'integer', 'label'=>'Parent', 'enabled'=>1, 'visible'=>-1, 'position'=>20),
182
		'tms' =>array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>25),
183
		'datec' =>array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-1, 'position'=>30),
184
		'nom' =>array('type'=>'varchar(128)', 'label'=>'Nom', 'enabled'=>1, 'visible'=>-1, 'position'=>35, 'showoncombobox'=>1),
185
		'name_alias' =>array('type'=>'varchar(128)', 'label'=>'Name alias', 'enabled'=>1, 'visible'=>-1, 'position'=>36, 'showoncombobox'=>2),
186
		'entity' =>array('type'=>'integer', 'label'=>'Entity', 'default'=>1, 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>40, 'index'=>1),
187
		'ref_ext' =>array('type'=>'varchar(255)', 'label'=>'RefExt', 'enabled'=>1, 'visible'=>0, 'position'=>45),
188
		'code_client' =>array('type'=>'varchar(24)', 'label'=>'CustomerCode', 'enabled'=>1, 'visible'=>-1, 'position'=>55),
189
		'code_fournisseur' =>array('type'=>'varchar(24)', 'label'=>'SupplierCode', 'enabled'=>1, 'visible'=>-1, 'position'=>60),
190
		'code_compta' =>array('type'=>'varchar(24)', 'label'=>'CodeCompta', 'enabled'=>1, 'visible'=>-1, 'position'=>65),
191
		'code_compta_fournisseur' =>array('type'=>'varchar(24)', 'label'=>'CodeComptaSupplier', 'enabled'=>1, 'visible'=>-1, 'position'=>70),
192
		'address' =>array('type'=>'varchar(255)', 'label'=>'Address', 'enabled'=>1, 'visible'=>-1, 'position'=>75),
193
		'zip' =>array('type'=>'varchar(25)', 'label'=>'Zip', 'enabled'=>1, 'visible'=>-1, 'position'=>80),
194
		'town' =>array('type'=>'varchar(50)', 'label'=>'Town', 'enabled'=>1, 'visible'=>-1, 'position'=>85),
195
		'fk_departement' =>array('type'=>'integer', 'label'=>'State', 'enabled'=>1, 'visible'=>-1, 'position'=>90),
196
		'fk_pays' =>array('type'=>'integer:Ccountry:core/class/ccountry.class.php', 'label'=>'Country', 'enabled'=>1, 'visible'=>-1, 'position'=>95),
197
		'phone' =>array('type'=>'varchar(20)', 'label'=>'Phone', 'enabled'=>1, 'visible'=>-1, 'position'=>100),
198
		'fax' =>array('type'=>'varchar(20)', 'label'=>'Fax', 'enabled'=>1, 'visible'=>-1, 'position'=>105),
199
		'url' =>array('type'=>'varchar(255)', 'label'=>'Url', 'enabled'=>1, 'visible'=>-1, 'position'=>110),
200
		'email' =>array('type'=>'varchar(128)', 'label'=>'Email', 'enabled'=>1, 'visible'=>-1, 'position'=>115),
201
		'socialnetworks' =>array('type'=>'text', 'label'=>'Socialnetworks', 'enabled'=>1, 'visible'=>-1, 'position'=>120),
202
		'fk_effectif' =>array('type'=>'integer', 'label'=>'Workforce', 'enabled'=>1, 'visible'=>-1, 'position'=>170),
203
		'fk_typent' =>array('type'=>'integer', 'label'=>'TypeOfCompany', 'enabled'=>1, 'visible'=>-1, 'position'=>175, 'csslist'=>'minwidth200'),
204
		'fk_forme_juridique' =>array('type'=>'integer', 'label'=>'JuridicalStatus', 'enabled'=>1, 'visible'=>-1, 'position'=>180),
205
		'fk_currency' =>array('type'=>'varchar(3)', 'label'=>'Currency', 'enabled'=>1, 'visible'=>-1, 'position'=>185),
206
		'siren' =>array('type'=>'varchar(128)', 'label'=>'Idprof1', 'enabled'=>1, 'visible'=>-1, 'position'=>190),
207
		'siret' =>array('type'=>'varchar(128)', 'label'=>'Idprof2', 'enabled'=>1, 'visible'=>-1, 'position'=>195),
208
		'ape' =>array('type'=>'varchar(128)', 'label'=>'Idprof3', 'enabled'=>1, 'visible'=>-1, 'position'=>200),
209
		'idprof4' =>array('type'=>'varchar(128)', 'label'=>'Idprof4', 'enabled'=>1, 'visible'=>-1, 'position'=>205),
210
		'idprof5' =>array('type'=>'varchar(128)', 'label'=>'Idprof5', 'enabled'=>1, 'visible'=>-1, 'position'=>206),
211
		'idprof6' =>array('type'=>'varchar(128)', 'label'=>'Idprof6', 'enabled'=>1, 'visible'=>-1, 'position'=>207),
212
		'tva_intra' =>array('type'=>'varchar(20)', 'label'=>'Tva intra', 'enabled'=>1, 'visible'=>-1, 'position'=>210),
213
		'capital' =>array('type'=>'double(24,8)', 'label'=>'Capital', 'enabled'=>1, 'visible'=>-1, 'position'=>215),
214
		'fk_stcomm' =>array('type'=>'integer', 'label'=>'CommercialStatus', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>220),
215
		'note_public' =>array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>225),
216
		'note_private' =>array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>230),
217
		'prefix_comm' =>array('type'=>'varchar(5)', 'label'=>'Prefix comm', 'enabled'=>"getDolGlobalInt('SOCIETE_USEPREFIX')", 'visible'=>-1, 'position'=>235),
218
		'client' =>array('type'=>'tinyint(4)', 'label'=>'Client', 'enabled'=>1, 'visible'=>-1, 'position'=>240),
219
		'fournisseur' =>array('type'=>'tinyint(4)', 'label'=>'Fournisseur', 'enabled'=>1, 'visible'=>-1, 'position'=>245),
220
		'supplier_account' =>array('type'=>'varchar(32)', 'label'=>'Supplier account', 'enabled'=>1, 'visible'=>-1, 'position'=>250),
221
		'fk_prospectlevel' =>array('type'=>'varchar(12)', 'label'=>'ProspectLevel', 'enabled'=>1, 'visible'=>-1, 'position'=>255),
222
		'customer_bad' =>array('type'=>'tinyint(4)', 'label'=>'Customer bad', 'enabled'=>1, 'visible'=>-1, 'position'=>260),
223
		'customer_rate' =>array('type'=>'double', 'label'=>'Customer rate', 'enabled'=>1, 'visible'=>-1, 'position'=>265),
224
		'supplier_rate' =>array('type'=>'double', 'label'=>'Supplier rate', 'enabled'=>1, 'visible'=>-1, 'position'=>270),
225
		'fk_user_creat' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'position'=>275),
226
		'fk_user_modif' =>array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>1, 'visible'=>-2, 'notnull'=>-1, 'position'=>280),
227
		//'remise_client' =>array('type'=>'double', 'label'=>'CustomerDiscount', 'enabled'=>1, 'visible'=>-1, 'position'=>285, 'isameasure'=>1),
228
		//'remise_supplier' =>array('type'=>'double', 'label'=>'SupplierDiscount', 'enabled'=>1, 'visible'=>-1, 'position'=>290, 'isameasure'=>1),
229
		'mode_reglement' =>array('type'=>'tinyint(4)', 'label'=>'Mode reglement', 'enabled'=>1, 'visible'=>-1, 'position'=>295),
230
		'cond_reglement' =>array('type'=>'tinyint(4)', 'label'=>'Cond reglement', 'enabled'=>1, 'visible'=>-1, 'position'=>300),
231
		'deposit_percent' =>array('type'=>'varchar(63)', 'label'=>'DepositPercent', 'enabled'=>1, 'visible'=>-1, 'position'=>301),
232
		'mode_reglement_supplier' =>array('type'=>'integer', 'label'=>'Mode reglement supplier', 'enabled'=>1, 'visible'=>-1, 'position'=>305),
233
		'cond_reglement_supplier' =>array('type'=>'integer', 'label'=>'Cond reglement supplier', 'enabled'=>1, 'visible'=>-1, 'position'=>308),
234
		'outstanding_limit' =>array('type'=>'double(24,8)', 'label'=>'OutstandingBill', 'enabled'=>1, 'visible'=>-1, 'position'=>310, 'isameasure'=>1),
235
		'order_min_amount' =>array('type'=>'double(24,8)', 'label'=>'Order min amount', 'enabled'=>'isModEnabled("commande") && !empty($conf->global->ORDER_MANAGE_MIN_AMOUNT)', 'visible'=>-1, 'position'=>315, 'isameasure'=>1),
236
		'supplier_order_min_amount' =>array('type'=>'double(24,8)', 'label'=>'Supplier order min amount', 'enabled'=>'isModEnabled("commande") && !empty($conf->global->ORDER_MANAGE_MIN_AMOUNT)', 'visible'=>-1, 'position'=>320, 'isameasure'=>1),
237
		'fk_shipping_method' =>array('type'=>'integer', 'label'=>'Fk shipping method', 'enabled'=>1, 'visible'=>-1, 'position'=>330),
238
		'tva_assuj' =>array('type'=>'tinyint(4)', 'label'=>'Tva assuj', 'enabled'=>1, 'visible'=>-1, 'position'=>335),
239
		'localtax1_assuj' =>array('type'=>'tinyint(4)', 'label'=>'Localtax1 assuj', 'enabled'=>1, 'visible'=>-1, 'position'=>340),
240
		'localtax1_value' =>array('type'=>'double(6,3)', 'label'=>'Localtax1 value', 'enabled'=>1, 'visible'=>-1, 'position'=>345),
241
		'localtax2_assuj' =>array('type'=>'tinyint(4)', 'label'=>'Localtax2 assuj', 'enabled'=>1, 'visible'=>-1, 'position'=>350),
242
		'localtax2_value' =>array('type'=>'double(6,3)', 'label'=>'Localtax2 value', 'enabled'=>1, 'visible'=>-1, 'position'=>355),
243
		'barcode' =>array('type'=>'varchar(255)', 'label'=>'Barcode', 'enabled'=>1, 'visible'=>-1, 'position'=>360),
244
		'price_level' =>array('type'=>'integer', 'label'=>'Price level', 'enabled'=>'$conf->global->PRODUIT_MULTIPRICES || $conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES', 'visible'=>-1, 'position'=>365),
245
		'default_lang' =>array('type'=>'varchar(6)', 'label'=>'Default lang', 'enabled'=>1, 'visible'=>-1, 'position'=>370),
246
		'canvas' =>array('type'=>'varchar(32)', 'label'=>'Canvas', 'enabled'=>1, 'visible'=>-1, 'position'=>375),
247
		'fk_barcode_type' =>array('type'=>'integer', 'label'=>'Fk barcode type', 'enabled'=>1, 'visible'=>-1, 'position'=>405),
248
		'webservices_url' =>array('type'=>'varchar(255)', 'label'=>'Webservices url', 'enabled'=>1, 'visible'=>-1, 'position'=>410),
249
		'webservices_key' =>array('type'=>'varchar(128)', 'label'=>'Webservices key', 'enabled'=>1, 'visible'=>-1, 'position'=>415),
250
		'fk_incoterms' =>array('type'=>'integer', 'label'=>'Fk incoterms', 'enabled'=>1, 'visible'=>-1, 'position'=>425),
251
		'location_incoterms' =>array('type'=>'varchar(255)', 'label'=>'Location incoterms', 'enabled'=>1, 'visible'=>-1, 'position'=>430),
252
		'model_pdf' =>array('type'=>'varchar(255)', 'label'=>'Model pdf', 'enabled'=>1, 'visible'=>0, 'position'=>435),
253
		'last_main_doc' =>array('type'=>'varchar(255)', 'label'=>'LastMainDoc', 'enabled'=>1, 'visible'=>-1, 'position'=>270),
254
		'fk_multicurrency' =>array('type'=>'integer', 'label'=>'Fk multicurrency', 'enabled'=>1, 'visible'=>-1, 'position'=>440),
255
		'multicurrency_code' =>array('type'=>'varchar(255)', 'label'=>'Multicurrency code', 'enabled'=>1, 'visible'=>-1, 'position'=>445),
256
		'fk_account' =>array('type'=>'integer', 'label'=>'AccountingAccount', 'enabled'=>1, 'visible'=>-1, 'position'=>450),
257
		'fk_warehouse' =>array('type'=>'integer', 'label'=>'Warehouse', 'enabled'=>1, 'visible'=>-1, 'position'=>455),
258
		'logo' =>array('type'=>'varchar(255)', 'label'=>'Logo', 'enabled'=>1, 'visible'=>-1, 'position'=>400),
259
		'logo_squarred' =>array('type'=>'varchar(255)', 'label'=>'Logo squarred', 'enabled'=>1, 'visible'=>-1, 'position'=>401),
260
		'status' =>array('type'=>'tinyint(4)', 'label'=>'Status', 'enabled'=>1, 'visible'=>-1, 'position'=>500),
261
		'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>1000),
262
	);
263
264
	/**
265
	 * @var int Entity
266
	 */
267
	public $entity;
268
269
	/**
270
	 * Thirdparty name
271
	 * @var string
272
	 * @deprecated Use $name instead
273
	 * @see $name
274
	 */
275
	public $nom;
276
277
	/**
278
	 * @var string Thirdparty name
279
	 */
280
	public $name;
281
282
	/**
283
	 * Alias names (commercial, trademark or alias names)
284
	 * @var string
285
	 */
286
	public $name_alias;
287
288
	/**
289
	 * @var int Physical thirdparty not a company
290
	 */
291
	public $particulier;
292
293
	/**
294
	 * @var string Address
295
	 */
296
	public $address;
297
298
	/**
299
	 * @var string Zip code of thirdparty
300
	 */
301
	public $zip;
302
303
	/**
304
	 * @var string Town of thirdparty
305
	 */
306
	public $town;
307
308
	/**
309
	 * Thirdparty status : 0=activity ceased, 1= in activity
310
	 * @var int
311
	 */
312
	public $status = 1;
313
314
	/**
315
	 * Id of department
316
	 * @var int
317
	 */
318
	public $state_id;
319
320
	/**
321
	 * @var string State code
322
	 */
323
	public $state_code;
324
325
	/**
326
	 * @var string State name
327
	 */
328
	public $state;
329
330
	/**
331
	 * Id of region
332
	 * @var int
333
	 */
334
	public $region_code;
335
336
	/**
337
	 * @var string Region name
338
	 */
339
	public $region;
340
341
	/**
342
	 * @var string State code
343
	 * @deprecated Use state_code instead
344
	 * @see $state_code
345
	 */
346
	public $departement_code;
347
348
	/**
349
	 * @var string
350
	 * @deprecated Use state instead
351
	 * @see $state
352
	 */
353
	public $departement;
354
355
	/**
356
	 * @var string
357
	 * @deprecated Use country instead
358
	 * @see $country
359
	 */
360
	public $pays;
361
362
	/**
363
	 * Phone number
364
	 * @var string
365
	 */
366
	public $phone;
367
	/**
368
	 * Fax number
369
	 * @var string
370
	 */
371
	public $fax;
372
373
	/**
374
	 * Email
375
	 * @var string
376
	 */
377
	public $email;
378
379
	/**
380
	 * No Email
381
	 * @var int		Set if company email found into unsubscribe of emailing list table
382
	 */
383
	public $no_email;
384
385
	/**
386
	 * Skype username
387
	 * @var string
388
	 * @deprecated
389
	 */
390
	public $skype;
391
392
	/**
393
	 * Twitter username
394
	 * @var string
395
	 * @deprecated
396
	 */
397
	public $twitter;
398
399
	/**
400
	 * Facebook username
401
	 * @var string
402
	 * @deprecated
403
	 */
404
	public $facebook;
405
406
	/**
407
	 * LinkedIn username
408
	 * @var string
409
	 * @deprecated
410
	 */
411
	public $linkedin;
412
413
	/**
414
	 * Webpage
415
	 * @var string
416
	 */
417
	public $url;
418
419
	/**
420
	 * Barcode value
421
	 * @var string
422
	 */
423
	public $barcode;
424
425
	// 6 professional id (usage depends on country)
426
427
	/**
428
	 * Professional ID 1 (Ex: Siren in France)
429
	 * @var string
430
	 */
431
	public $idprof1;
432
433
	/**
434
	 * @var string Professional ID 1
435
	 * @deprecated
436
	 * @see $idprof1
437
	 */
438
	public $siren;
439
440
441
	/**
442
	 * Professional ID 2 (Ex: Siret in France)
443
	 * @var string
444
	 */
445
	public $idprof2;
446
447
	/**
448
	 * @var string Professional ID 2
449
	 * @deprecated
450
	 * @see $idprof2
451
	 */
452
	public $siret;
453
454
	/**
455
	 * Professional ID 3 (Ex: Ape in France)
456
	 * @var string
457
	 */
458
	public $idprof3;
459
460
	/**
461
	 * @var string Professional ID 3
462
	 * @deprecated
463
	 * @see $idprof3
464
	 */
465
	public $ape;
466
467
	/**
468
	 * Professional ID 4 (Ex: RCS in France)
469
	 * @var string
470
	 */
471
	public $idprof4;
472
473
	/**
474
	 * Professional ID 5
475
	 * @var string
476
	 */
477
	public $idprof5;
478
479
	/**
480
	 * Professional ID 6
481
	 * @var string
482
	 */
483
	public $idprof6;
484
485
	/**
486
	 * Social object of the company
487
	 * @var string
488
	 */
489
	public $socialobject;
490
491
	/**
492
	 * @var string Prefix comm
493
	 */
494
	public $prefix_comm;
495
496
	/**
497
	 * @var int Vat concerned
498
	 */
499
	public $tva_assuj = 1;
500
501
	/**
502
	 * Intracommunitary VAT ID
503
	 * @var string
504
	 */
505
	public $tva_intra;
506
507
	// Local taxes
508
	public $localtax1_assuj;
509
	public $localtax1_value;
510
	public $localtax2_assuj;
511
	public $localtax2_value;
512
513
	/**
514
	 * @var string Manager
515
	 */
516
	public $managers;
517
518
	/**
519
	 * @var float Capital
520
	 */
521
	public $capital;
522
523
	/**
524
	 * @var int Type thirdparty
525
	 */
526
	public $typent_id = 0;
527
	public $typent_code;
528
	public $effectif;
529
	public $effectif_id = 0;
530
	public $forme_juridique_code;
531
	public $forme_juridique = 0;
532
533
	public $remise_percent;
534
	public $remise_supplier_percent;
535
536
	public $mode_reglement_id;
537
	public $cond_reglement_id;
538
	public $deposit_percent;
539
	public $mode_reglement_supplier_id;
540
	public $cond_reglement_supplier_id;
541
	public $transport_mode_supplier_id;
542
543
	/**
544
	 * @var int ID
545
	 */
546
	public $fk_prospectlevel;
547
548
	/**
549
	 * @var string second name
550
	 */
551
	public $name_bis;
552
553
	//Log data
554
555
	/**
556
	 * Date of last update
557
	 * @var integer|string
558
	 */
559
	public $date_modification;
560
561
	/**
562
	 * User that made last update
563
	 * @var User
564
	 */
565
	public $user_modification;
566
567
	/**
568
	 * Date of creation
569
	 * @var integer|string
570
	 */
571
	public $date_creation;
572
573
	/**
574
	 * User that created the thirdparty
575
	 * @var User
576
	 */
577
	public $user_creation;
578
579
	/**
580
	 * 0=no customer, 1=customer, 2=prospect, 3=customer and prospect
581
	 * @var int
582
	 */
583
	public $client = 0;
584
585
	/**
586
	 * 0=no prospect, 1=prospect
587
	 * @var int
588
	 */
589
	public $prospect = 0;
590
591
	/**
592
	 * 0=no supplier, 1=supplier
593
	 * @var int
594
	 */
595
	public $fournisseur;
596
597
	/**
598
	 * Client code. E.g: CU2014-003
599
	 * @var string
600
	 */
601
	public $code_client;
602
603
	/**
604
	 * Supplier code. E.g: SU2014-003
605
	 * @var string
606
	 */
607
	public $code_fournisseur;
608
609
	/**
610
	 * Accounting code for client
611
	 * @var string
612
	 */
613
	public $code_compta_client;
614
615
	/**
616
	 * Duplicate of code_compta_client (for backward compatibility)
617
	 * @var string
618
	 */
619
	public $code_compta;
620
621
622
	/**
623
	 * Accounting code for customer
624
	 * @var string
625
	 */
626
	public $accountancy_code_customer;
627
628
	/**
629
	 * Accounting code for supplier
630
	 * @var string
631
	 */
632
	public $code_compta_fournisseur;
633
634
	/**
635
	 * Accounting code for supplier
636
	 * @var string
637
	 */
638
	public $accountancy_code_supplier;
639
640
641
	/**
642
	 * Accounting code for product (for level 3 of suggestion of prouct accounting account)
643
	 * @var string
644
	 */
645
	public $code_compta_product;
646
647
648
	/**
649
	 * @var string
650
	 * @deprecated Note is split in public and private notes
651
	 * @see $note_public, $note_private
652
	 */
653
	public $note;
654
655
	/**
656
	 * Private note
657
	 * @var string
658
	 */
659
	public $note_private;
660
661
	/**
662
	 * Public note
663
	 * @var string
664
	 */
665
	public $note_public;
666
667
	/**
668
	 * Status prospect id
669
	 * @var int
670
	 */
671
	public $stcomm_id;
672
673
	/**
674
	 * Status prospect picto
675
	 * @var string
676
	 */
677
	public $stcomm_picto;
678
679
	/**
680
	 * Status prospect label
681
	 * @var int
682
	 */
683
	public $status_prospect_label;
684
685
	/**
686
	 * Assigned price level
687
	 * @var int
688
	 */
689
	public $price_level;
690
691
	/**
692
	 * @var string outstanding limit
693
	 */
694
	public $outstanding_limit;
695
696
	/**
697
	 * @var string Min order amount
698
	 */
699
	public $order_min_amount;
700
701
	/**
702
	 * @var string Supplier min order amount
703
	 */
704
	public $supplier_order_min_amount;
705
706
	/**
707
	 * Id of sales representative to link (used for thirdparty creation). Not filled by a fetch, because we can have several sales representatives.
708
	 * @var int
709
	 */
710
	public $commercial_id;
711
712
	/**
713
	 * Id of parent thirdparty (if one)
714
	 * @var int
715
	 */
716
	public $parent;
717
718
	/**
719
	 * Default language code of thirdparty (en_US, ...)
720
	 * @var string
721
	 */
722
	public $default_lang;
723
724
	/**
725
	 * @var string Ref
726
	 */
727
	public $ref;
728
729
	/**
730
	 * External user reference.
731
	 * This is to allow external systems to store their id and make self-developed synchronizing functions easier to build.
732
	 * @var string
733
	 */
734
	public $ref_ext;
735
736
	/**
737
	 * Import key.
738
	 * Set when the thirdparty has been created through an import process. This is to relate those created thirdparties
739
	 * to an import process
740
	 * @var string
741
	 */
742
	public $import_key;
743
744
	/**
745
	 * Supplier WebServices URL
746
	 * @var string
747
	 */
748
	public $webservices_url;
749
750
	/**
751
	 * Supplier WebServices Key
752
	 * @var string
753
	 */
754
	public $webservices_key;
755
756
	/**
757
	 * @var string Logo
758
	 */
759
	public $logo;
760
761
	/**
762
	 * @var string logo small
763
	 */
764
	public $logo_small;
765
766
	/**
767
	 * @var string Logo mini
768
	 */
769
	public $logo_mini;
770
771
	/**
772
	 * @var string Logo squarred
773
	 */
774
	public $logo_squarred;
775
776
	/**
777
	 * @var string Logo squarred small
778
	 */
779
	public $logo_squarred_small;
780
781
	/**
782
	 * @var string Logo squarred mini
783
	 */
784
	public $logo_squarred_mini;
785
786
	/**
787
	 * @var string Accountancy account for sales
788
	 */
789
	public $accountancy_code_sell;
790
791
	/**
792
	 * @var string Accountancy account for bought
793
	 */
794
	public $accountancy_code_buy;
795
796
	// Multicurrency
797
	/**
798
	 * @var int ID
799
	 */
800
	public $fk_multicurrency;
801
802
	// Warehouse
803
	/**
804
	 * @var int ID
805
	 */
806
	public $fk_warehouse;
807
808
	/**
809
	 * @var string Multicurrency code
810
	 */
811
	public $multicurrency_code;
812
813
	// Fields loaded by fetchPartnerships()
814
815
	public $partnerships = array();
816
817
818
	/**
819
	 * @var Account|string Default BAN account
820
	 */
821
	public $bank_account;
822
823
824
	const STATUS_CEASED = 0;
825
	const STATUS_INACTIVITY = 1;
826
827
	/**
828
	 * Third party type is no customer
829
	 */
830
	const NO_CUSTOMER = 0;
831
832
	/**
833
	 * Third party type is a customer
834
	 */
835
	const CUSTOMER = 1;
836
837
	/**
838
	 * Third party type is a prospect
839
	 */
840
	const PROSPECT = 2;
841
842
	/**
843
	 * Third party type is a customer and a prospect
844
	 */
845
	const CUSTOMER_AND_PROSPECT = 3;
846
847
	/**
848
	 * Third party supplier flag is not supplier
849
	 */
850
	const NO_SUPPLIER = 0;
851
852
	/**
853
	 * Third party supplier flag is a supplier
854
	 */
855
	const SUPPLIER = 1;
856
857
858
	/**
859
	 *    Constructor
860
	 *
861
	 *    @param	DoliDB		$db		Database handler
862
	 */
863
	public function __construct($db)
864
	{
865
		global $conf;
866
867
		$this->db = $db;
868
869
		$this->client = 0;
870
		$this->prospect = 0;
871
		$this->fournisseur = 0;
872
		$this->typent_id = 0;
873
		$this->effectif_id = 0;
874
		$this->forme_juridique_code = 0;
875
		$this->tva_assuj = 1;
876
		$this->status = 1;
877
878
		if (!empty($conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST)) {
879
			$this->fields['address']['showoncombobox'] = $conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST;
880
			$this->fields['zip']['showoncombobox'] = $conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST;
881
			$this->fields['town']['showoncombobox'] = $conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST;
882
			//$this->fields['fk_pays']['showoncombobox'] = $conf->global->COMPANY_SHOW_ADDRESS_SELECTLIST;
883
		}
884
	}
885
886
887
	/**
888
	 *    Create third party in database.
889
	 *    $this->code_client = -1 and $this->code_fournisseur = -1 means automatic assignement.
890
	 *
891
	 *    @param	User	$user       Object of user that ask creation
892
	 *    @return   int         		>=0 if OK, <0 if KO
893
	 */
894
	public function create(User $user)
895
	{
896
		global $langs, $conf, $mysoc;
897
898
		$error = 0;
899
900
		// Clean parameters
901
		if (empty($this->status)) {
902
			$this->status = 0;
903
		}
904
		$this->name = $this->name ?trim($this->name) : trim($this->nom);
905
		$this->setUpperOrLowerCase();
906
		$this->nom = $this->name; // For backward compatibility
907
		if (empty($this->client)) {
908
			$this->client = 0;
909
		}
910
		if (empty($this->fournisseur)) {
911
			$this->fournisseur = 0;
912
		}
913
		$this->import_key = trim($this->import_key);
914
915
		$this->accountancy_code_customer = trim($this->code_compta);
916
		$this->accountancy_code_supplier = trim($this->code_compta_fournisseur);
917
		$this->accountancy_code_buy = trim($this->accountancy_code_buy);
918
		$this->accountancy_code_sell = trim($this->accountancy_code_sell);
919
920
		if (!empty($this->multicurrency_code)) {
921
			$this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code);
922
		}
923
		if (empty($this->fk_multicurrency)) {
924
			$this->multicurrency_code = '';
925
			$this->fk_multicurrency = 0;
926
		}
927
928
		dol_syslog(get_class($this)."::create ".$this->name);
929
930
		$now = dol_now();
931
932
		$this->db->begin();
933
934
		// For automatic creation during create action (not used by Dolibarr GUI, can be used by scripts)
935
		if ($this->code_client == -1 || $this->code_client === 'auto') {
936
			$this->get_codeclient($this, 0);
937
		}
938
		if ($this->code_fournisseur == -1 || $this->code_fournisseur === 'auto') {
939
			$this->get_codefournisseur($this, 1);
940
		}
941
942
		// Check more parameters (including mandatory setup
943
		// If error, this->errors[] is filled
944
		$result = $this->verify();
945
946
		if ($result >= 0) {
947
			$this->entity = ((isset($this->entity) && is_numeric($this->entity)) ? $this->entity : $conf->entity);
948
949
			$sql = "INSERT INTO ".MAIN_DB_PREFIX."societe (";
950
			$sql .= "nom";
951
			$sql .= ", name_alias";
952
			$sql .= ", entity";
953
			$sql .= ", datec";
954
			$sql .= ", fk_user_creat";
955
			$sql .= ", fk_typent";
956
			$sql .= ", canvas";
957
			$sql .= ", status";
958
			$sql .= ", ref_ext";
959
			$sql .= ", fk_stcomm";
960
			$sql .= ", fk_incoterms";
961
			$sql .= ", location_incoterms";
962
			$sql .= ", import_key";
963
			$sql .= ", fk_multicurrency";
964
			$sql .= ", multicurrency_code";
965
			if (empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) {
966
				$sql .= ", accountancy_code_buy";
967
				$sql .= ", accountancy_code_sell";
968
			}
969
			$sql .= ") VALUES ('".$this->db->escape($this->name)."', '".$this->db->escape($this->name_alias)."', ".((int) $this->entity).", '".$this->db->idate($now)."'";
970
			$sql .= ", ".(!empty($user->id) ? ((int) $user->id) : "null");
971
			$sql .= ", ".(!empty($this->typent_id) ? ((int) $this->typent_id) : "null");
972
			$sql .= ", ".(!empty($this->canvas) ? "'".$this->db->escape($this->canvas)."'" : "null");
973
			$sql .= ", ".((int) $this->status);
974
			$sql .= ", ".(!empty($this->ref_ext) ? "'".$this->db->escape($this->ref_ext)."'" : "null");
975
			$sql .= ", 0";
976
			$sql .= ", ".(int) $this->fk_incoterms;
977
			$sql .= ", '".$this->db->escape($this->location_incoterms)."'";
978
			$sql .= ", ".(!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null");
979
			$sql .= ", ".(int) $this->fk_multicurrency;
980
			$sql .= ", '".$this->db->escape($this->multicurrency_code)."'";
981
			if (empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) {
982
				$sql .= ", '".$this->db->escape($this->accountancy_code_buy)."'";
983
				$sql .= ", '".$this->db->escape($this->accountancy_code_sell)."'";
984
			}
985
			$sql .= ")";
986
987
			dol_syslog(get_class($this)."::create", LOG_DEBUG);
988
			$result = $this->db->query($sql);
989
			if ($result) {
990
				$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."societe");
991
992
				$ret = $this->update($this->id, $user, 0, 1, 1, 'add');
993
994
				// update accountancy for this entity
995
				if (!$error && !empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) {
996
					$this->db->query("DELETE FROM ".MAIN_DB_PREFIX."societe_perentity WHERE fk_soc = ".((int) $this->id)." AND entity = ".((int) $conf->entity));
997
998
					$sql = "INSERT INTO ".MAIN_DB_PREFIX."societe_perentity (";
999
					$sql .= " fk_soc";
1000
					$sql .= ", entity";
1001
					$sql .= ", accountancy_code_customer";
1002
					$sql .= ", accountancy_code_supplier";
1003
					$sql .= ", accountancy_code_buy";
1004
					$sql .= ", accountancy_code_sell";
1005
					$sql .= ") VALUES (";
1006
					$sql .= $this->id;
1007
					$sql .= ", ".((int) $conf->entity);
1008
					$sql .= ", '".$this->db->escape($this->accountancy_code_customer)."'";
1009
					$sql .= ", '".$this->db->escape($this->accountancy_code_supplier)."'";
1010
					$sql .= ", '".$this->db->escape($this->accountancy_code_buy)."'";
1011
					$sql .= ", '".$this->db->escape($this->accountancy_code_sell)."'";
1012
					$sql .= ")";
1013
					$result = $this->db->query($sql);
1014
					if (!$result) {
1015
						$error++;
1016
						$this->error = 'ErrorFailedToUpdateAccountancyForEntity';
1017
					}
1018
				}
1019
1020
				// Ajout du commercial affecte
1021
				if ($this->commercial_id != '' && $this->commercial_id != -1) {
1022
					$this->add_commercial($user, $this->commercial_id);
1023
				} elseif (empty($user->rights->societe->client->voir)) {
1024
					// si un commercial cree un client il lui est affecte automatiquement
1025
					$this->add_commercial($user, $user->id);
1026
				}
1027
1028
				if ($ret >= 0) {
1029
					// Call trigger
1030
					$result = $this->call_trigger('COMPANY_CREATE', $user);
1031
					if ($result < 0) {
1032
						$error++;
1033
					}
1034
					// End call triggers
1035
				} else {
1036
					$error++;
1037
				}
1038
1039
				if (!$error) {
1040
					dol_syslog(get_class($this)."::Create success id=".$this->id);
1041
					$this->db->commit();
1042
					return $this->id;
1043
				} else {
1044
					dol_syslog(get_class($this)."::Create echec update ".$this->error.(empty($this->errors) ? '' : ' '.join(',', $this->errors)), LOG_ERR);
1045
					$this->db->rollback();
1046
					return -4;
1047
				}
1048
			} else {
1049
				if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
1050
					$this->error = $langs->trans("ErrorCompanyNameAlreadyExists", $this->name); // duplicate on a field (code or profid or ...)
1051
					$result = -1;
1052
				} else {
1053
					$this->error = $this->db->lasterror();
1054
					$result = -2;
1055
				}
1056
				$this->db->rollback();
1057
				return $result;
1058
			}
1059
		} else {
1060
			$this->db->rollback();
1061
			dol_syslog(get_class($this)."::Create fails verify ".join(',', $this->errors), LOG_WARNING);
1062
			return -3;
1063
		}
1064
	}
1065
1066
1067
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1068
	/**
1069
	 * Create a contact/address from thirdparty
1070
	 *
1071
	 * @param 	User	$user		Object user
1072
	 * @param 	int		$no_email	1=Do not send mailing, 0=Ok to recieve mailling
1073
	 * @param 	array	$tags		Array of tag to affect to contact
1074
	 * @return 	int					<0 if KO, >0 if OK
1075
	 */
1076
	public function create_individual(User $user, $no_email = 0, $tags = array())
1077
	{
1078
		global $conf;
1079
1080
		$error = 0;
1081
1082
		$this->db->begin();
1083
1084
		// phpcs:enable
1085
		require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
1086
		$contact = new Contact($this->db);
1087
1088
		$contact->name              = $this->name_bis;
1089
		$contact->firstname         = $this->firstname;
1090
		$contact->civility_id       = $this->civility_id;
1091
		$contact->socid             = $this->id; // fk_soc
1092
		$contact->statut            = 1; // deprecated
1093
		$contact->status            = 1;
1094
		$contact->priv              = 0;
1095
		$contact->country_id        = $this->country_id;
1096
		$contact->state_id          = $this->state_id;
1097
		$contact->address           = $this->address;
1098
		$contact->email             = $this->email;
1099
		$contact->zip               = $this->zip;
1100
		$contact->town              = $this->town;
1101
		$this->setUpperOrLowerCase();
1102
		$contact->phone_pro         = $this->phone;
1103
1104
		$contactId = $contact->create($user);
1105
		if ($contactId < 0) {
1106
			$error++;
1107
			$this->error = $contact->error;
1108
			$this->errors = $contact->errors;
1109
			dol_syslog(get_class($this)."::create_individual ERROR:".$this->error, LOG_ERR);
1110
		}
1111
1112
		if (empty($error) && is_array($tags) && !empty($tags)) {
1113
			$result = $contact->setCategories($tags);
1114
			if ($result < 0) {
1115
				$error++;
1116
				$this->error = $contact->error;
1117
				$this->errors = array_merge($this->errors, $contact->errors);
1118
				dol_syslog(get_class($this)."::create_individual Affect Tag ERROR:".$this->error, LOG_ERR);
1119
				$contactId = $result;
1120
			}
1121
		}
1122
1123
		if (empty($error) && isModEnabled('mailing') && !empty($contact->email) && isset($no_email)) {
1124
			$result = $contact->setNoEmail($no_email);
1125
			if ($result < 0) {
1126
				$this->error = $contact->error;
1127
				$this->errors = array_merge($this->errors, $contact->errors);
1128
				dol_syslog(get_class($this)."::create_individual set mailing status ERROR:".$this->error, LOG_ERR);
1129
				$contactId = $result;
1130
			}
1131
		}
1132
1133
		if (empty($error)) {
1134
			dol_syslog(get_class($this)."::create_individual success");
1135
			$this->db->commit();
1136
		} else {
1137
			$this->db->rollback();
1138
		}
1139
1140
		return $contactId;
1141
	}
1142
1143
	/**
1144
	 *    Check properties of third party are ok (like name, third party codes, ...)
1145
	 *    Used before an add or update.
1146
	 *
1147
	 *    @return     int		0 if OK, <0 if KO
1148
	 */
1149
	public function verify()
1150
	{
1151
		global $conf, $langs, $mysoc;
1152
1153
		$error = 0;
1154
		$this->errors = array();
1155
1156
		$result = 0;
1157
		$this->name = trim($this->name);
1158
		$this->nom = $this->name; // For backward compatibility
1159
1160
		if (!$this->name) {
1161
			$this->errors[] = 'ErrorBadThirdPartyName';
1162
			$result = -2;
1163
		}
1164
1165
		if ($this->client) {
1166
			$rescode = $this->check_codeclient();
1167
			if ($rescode != 0 && $rescode != -5) {
1168
				if ($rescode == -1) {
1169
					$this->errors[] = 'ErrorBadCustomerCodeSyntax';
1170
				} elseif ($rescode == -2) {
1171
					$this->errors[] = 'ErrorCustomerCodeRequired';
1172
				} elseif ($rescode == -3) {
1173
					$this->errors[] = 'ErrorCustomerCodeAlreadyUsed';
1174
				} elseif ($rescode == -4) {
1175
					$this->errors[] = 'ErrorPrefixRequired';
1176
				} else {
1177
					$this->errors[] = 'ErrorUnknownOnCustomerCodeCheck';
1178
				}
1179
1180
				$result = -3;
1181
			}
1182
		}
1183
1184
		if ($this->fournisseur) {
1185
			$rescode = $this->check_codefournisseur();
1186
			if ($rescode != 0 && $rescode != -5) {
1187
				if ($rescode == -1) {
1188
					$this->errors[] = 'ErrorBadSupplierCodeSyntax';
1189
				} elseif ($rescode == -2) {
1190
					$this->errors[] = 'ErrorSupplierCodeRequired';
1191
				} elseif ($rescode == -3) {
1192
					$this->errors[] = 'ErrorSupplierCodeAlreadyUsed';
1193
				} elseif ($rescode == -4) {
1194
					$this->errors[] = 'ErrorPrefixRequired';
1195
				} else {
1196
					$this->errors[] = 'ErrorUnknownOnSupplierCodeCheck';
1197
				}
1198
				$result = -3;
1199
			}
1200
		}
1201
1202
		// Check for duplicate or mandatory fields defined into setup
1203
		$array_to_check = array('IDPROF1', 'IDPROF2', 'IDPROF3', 'IDPROF4', 'IDPROF5', 'IDPROF6', 'EMAIL', 'TVA_INTRA');
1204
		foreach ($array_to_check as $key) {
1205
			$keymin = strtolower($key);
1206
			$i = (int) preg_replace('/[^0-9]/', '', $key);
1207
			$vallabel = $this->$keymin;
1208
1209
			if ($i > 0) {
1210
				if ($this->isACompany()) {
1211
					// Check for mandatory prof id (but only if country is same than ours)
1212
					if ($mysoc->country_id > 0 && $this->country_id == $mysoc->country_id) {
1213
						$idprof_mandatory = 'SOCIETE_'.$key.'_MANDATORY';
1214
						if (!$vallabel && !empty($conf->global->$idprof_mandatory)) {
1215
							$langs->load("errors");
1216
							$error++;
1217
							$this->errors[] = $langs->trans("ErrorProdIdIsMandatory", $langs->transcountry('ProfId'.$i, $this->country_code)).' ('.$langs->trans("ForbiddenBySetupRules").')';
1218
						}
1219
					}
1220
				}
1221
1222
				// Check for unicity on profid
1223
				if (!$error && $vallabel && $this->id_prof_verifiable($i)) {
1224
					if ($this->id_prof_exists($keymin, $vallabel, ($this->id > 0 ? $this->id : 0))) {
1225
						$langs->load("errors");
1226
						$error++;
1227
						$this->errors[] = $langs->transcountry('ProfId'.$i, $this->country_code)." ".$langs->trans("ErrorProdIdAlreadyExist", $vallabel).' ('.$langs->trans("ForbiddenBySetupRules").')';
1228
					}
1229
				}
1230
			} else {
1231
				//var_dump($conf->global->SOCIETE_EMAIL_UNIQUE);
1232
				//var_dump($conf->global->SOCIETE_EMAIL_MANDATORY);
1233
				if ($key == 'EMAIL') {
1234
					// Check for mandatory
1235
					if (!empty($conf->global->SOCIETE_EMAIL_MANDATORY) && !isValidEMail($this->email)) {
1236
						$langs->load("errors");
1237
						$error++;
1238
						$this->errors[] = $langs->trans("ErrorBadEMail", $this->email).' ('.$langs->trans("ForbiddenBySetupRules").')';
1239
					}
1240
1241
					// Check for unicity
1242
					if (!$error && $vallabel && !empty($conf->global->SOCIETE_EMAIL_UNIQUE)) {
1243
						if ($this->id_prof_exists($keymin, $vallabel, ($this->id > 0 ? $this->id : 0))) {
1244
							$langs->load("errors");
1245
							$error++; $this->errors[] = $langs->trans('Email')." ".$langs->trans("ErrorProdIdAlreadyExist", $vallabel).' ('.$langs->trans("ForbiddenBySetupRules").')';
1246
						}
1247
					}
1248
				} elseif ($key == 'TVA_INTRA') {
1249
					// Check for unicity
1250
					if ($vallabel && !empty($conf->global->SOCIETE_VAT_INTRA_UNIQUE)) {
1251
						if ($this->id_prof_exists($keymin, $vallabel, ($this->id > 0 ? $this->id : 0))) {
1252
							$langs->load("errors");
1253
							$error++; $this->errors[] = $langs->trans('VATIntra')." ".$langs->trans("ErrorProdIdAlreadyExist", $vallabel).' ('.$langs->trans("ForbiddenBySetupRules").')';
1254
						}
1255
					}
1256
				}
1257
			}
1258
		}
1259
1260
		if ($error) {
1261
			$result = -4;
1262
		}
1263
1264
		return $result;
1265
	}
1266
1267
	/**
1268
	 *      Update parameters of third party
1269
	 *
1270
	 *      @param	int		$id              			Id of company (deprecated, use 0 here and call update on an object loaded by a fetch)
1271
	 *      @param  User	$user            			User who requests the update
1272
	 *      @param  int		$call_trigger    			0=no, 1=yes
1273
	 *		@param	int		$allowmodcodeclient			Inclut modif code client et code compta
1274
	 *		@param	int		$allowmodcodefournisseur	Inclut modif code fournisseur et code compta fournisseur
1275
	 *		@param	string	$action						'add' or 'update' or 'merge'
1276
	 *		@param	int		$nosyncmember				Do not synchronize info of linked member
1277
	 *      @return int  			           			<0 if KO, >=0 if OK
1278
	 */
1279
	public function update($id, $user = '', $call_trigger = 1, $allowmodcodeclient = 0, $allowmodcodefournisseur = 0, $action = 'update', $nosyncmember = 1)
1280
	{
1281
		global $langs, $conf, $hookmanager;
1282
1283
		require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
1284
1285
		if (empty($id)) {
1286
			$id = $this->id;
1287
		}
1288
1289
		$error = 0;
1290
1291
		dol_syslog(get_class($this)."::Update id=".$id." call_trigger=".$call_trigger." allowmodcodeclient=".$allowmodcodeclient." allowmodcodefournisseur=".$allowmodcodefournisseur);
1292
1293
		$now = dol_now();
1294
1295
		// Clean parameters
1296
		$this->id = $id;
1297
		$this->entity = ((isset($this->entity) && is_numeric($this->entity)) ? $this->entity : $conf->entity);
1298
		$this->name = $this->name ? trim($this->name) : trim($this->nom);
1299
		$this->nom = $this->name; // For backward compatibility
1300
		$this->name_alias = trim($this->name_alias);
1301
		$this->ref_ext		= trim($this->ref_ext);
1302
		$this->address		= $this->address ?trim($this->address) : trim($this->address);
1303
		$this->zip = $this->zip ?trim($this->zip) : trim($this->zip);
1304
		$this->town = $this->town ?trim($this->town) : trim($this->town);
1305
		$this->state_id = trim($this->state_id);
1306
		$this->country_id = ($this->country_id > 0) ? $this->country_id : 0;
1307
		$this->phone		= trim($this->phone);
1308
		$this->phone		= preg_replace("/\s/", "", $this->phone);
1309
		$this->phone		= preg_replace("/\./", "", $this->phone);
1310
		$this->fax			= trim($this->fax);
1311
		$this->fax			= preg_replace("/\s/", "", $this->fax);
1312
		$this->fax			= preg_replace("/\./", "", $this->fax);
1313
		$this->email		= trim($this->email);
1314
		$this->url			= $this->url ?clean_url($this->url, 0) : '';
1315
		$this->note_private = trim($this->note_private);
1316
		$this->note_public  = trim($this->note_public);
1317
		$this->idprof1		= trim($this->idprof1);
1318
		$this->idprof2		= trim($this->idprof2);
1319
		$this->idprof3		= trim($this->idprof3);
1320
		$this->idprof4		= trim($this->idprof4);
1321
		$this->idprof5		= (!empty($this->idprof5) ?trim($this->idprof5) : '');
1322
		$this->idprof6		= (!empty($this->idprof6) ?trim($this->idprof6) : '');
1323
		$this->prefix_comm = trim($this->prefix_comm);
1324
		$this->outstanding_limit = price2num($this->outstanding_limit);
1325
		$this->order_min_amount = price2num($this->order_min_amount);
1326
		$this->supplier_order_min_amount = price2num($this->supplier_order_min_amount);
1327
1328
		$this->tva_assuj	= trim($this->tva_assuj);
1329
		$this->tva_intra	= dol_sanitizeFileName($this->tva_intra, '');
1330
		if (empty($this->status)) {
1331
			$this->status = 0;
1332
		}
1333
1334
		if (!empty($this->multicurrency_code)) {
1335
			$this->fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $this->multicurrency_code);
1336
		}
1337
		if (empty($this->fk_multicurrency)) {
1338
			$this->multicurrency_code = '';
1339
			$this->fk_multicurrency = 0;
1340
		}
1341
1342
		// Local taxes
1343
		$this->localtax1_assuj = trim($this->localtax1_assuj);
1344
		$this->localtax2_assuj = trim($this->localtax2_assuj);
1345
1346
		$this->localtax1_value = trim($this->localtax1_value);
1347
		$this->localtax2_value = trim($this->localtax2_value);
1348
1349
		if ($this->capital != '') {
1350
			$this->capital = price2num(trim($this->capital));
1351
		}
1352
		if (!is_numeric($this->capital)) {
1353
			$this->capital = ''; // '' = undef
1354
		}
1355
1356
		$this->effectif_id = trim($this->effectif_id);
1357
		$this->forme_juridique_code = trim($this->forme_juridique_code);
1358
1359
		//Gencod
1360
		$this->barcode = trim($this->barcode);
1361
1362
		// For automatic creation
1363
		if ($this->code_client == -1 || $this->code_client === 'auto') {
1364
			$this->get_codeclient($this, 0);
1365
		}
1366
		if ($this->code_fournisseur == -1 || $this->code_fournisseur === 'auto') {
1367
			$this->get_codefournisseur($this, 1);
1368
		}
1369
1370
		$this->code_compta_client = trim(empty($this->code_compta) ? $this->code_compta_client : $this->code_compta);
1371
		$this->code_compta = $this->code_compta_client; // for backward compatibility
1372
		$this->code_compta_fournisseur = trim($this->code_compta_fournisseur);
1373
1374
		// Check parameters. More tests are done later in the ->verify()
1375
		if (!is_numeric($this->client) && !is_numeric($this->fournisseur)) {
1376
			$langs->load("errors");
1377
			$this->error = $langs->trans("BadValueForParameterClientOrSupplier");
1378
			return -1;
1379
		}
1380
1381
		$customer = false;
1382
		if (!empty($allowmodcodeclient) && !empty($this->client)) {
1383
			// If $allowmodcodeclient is set and value is not set, we generate it
1384
			if (empty($this->code_compta_client)) {
1385
				$ret = $this->get_codecompta('customer');
1386
				if ($ret < 0) {
1387
					return -1;
1388
				}
1389
			}
1390
1391
			$customer = true;
1392
		}
1393
1394
		$supplier = false;
1395
		if (!empty($allowmodcodefournisseur) && !empty($this->fournisseur)) {
1396
			// If $allowmodcodefournisseur is set and value is not set, we generate it
1397
			if (empty($this->code_compta_fournisseur)) {
1398
				$ret = $this->get_codecompta('supplier');
1399
				if ($ret < 0) {
1400
					return -1;
1401
				}
1402
			}
1403
1404
			$supplier = true;
1405
		}
1406
1407
		//Web services
1408
		$this->webservices_url = $this->webservices_url ?clean_url($this->webservices_url, 0) : '';
1409
		$this->webservices_key = trim($this->webservices_key);
1410
1411
		$this->accountancy_code_buy = trim($this->accountancy_code_buy);
1412
		$this->accountancy_code_sell = trim($this->accountancy_code_sell);
1413
1414
		//Incoterms
1415
		$this->fk_incoterms = (int) $this->fk_incoterms;
1416
		$this->location_incoterms = trim($this->location_incoterms);
1417
1418
		$this->db->begin();
1419
1420
		// Check name is required and codes are ok or unique.
1421
		// If error, this->errors[] is filled
1422
		$result = 0;
1423
		if ($action != 'add' && $action != 'merge') {
1424
			// We don't check when update called during a create because verify was already done.
1425
			// For a merge, we suppose source data is clean and a customer code of a deleted thirdparty must be accepted into a target thirdparty with empty code without duplicate error
1426
			$result = $this->verify();
1427
1428
			// If there is only one error and error is ErrorBadCustomerCodeSyntax and we don't change customer code, we allow the update
1429
			// So we can update record that were using and old numbering rule.
1430
			if (is_array($this->errors)) {
1431
				if (in_array('ErrorBadCustomerCodeSyntax', $this->errors) && is_object($this->oldcopy) && $this->oldcopy->code_client == $this->code_client) {
1432
					if (($key = array_search('ErrorBadCustomerCodeSyntax', $this->errors)) !== false) {
1433
						unset($this->errors[$key]); // Remove error message
1434
					}
1435
				}
1436
				if (in_array('ErrorBadSupplierCodeSyntax', $this->errors) && is_object($this->oldcopy) && $this->oldcopy->code_fournisseur == $this->code_fournisseur) {
1437
					if (($key = array_search('ErrorBadSupplierCodeSyntax', $this->errors)) !== false) {
1438
						unset($this->errors[$key]); // Remove error message
1439
					}
1440
				}
1441
				if (empty($this->errors)) {	// If there is no more error, we can make like if there is no error at all
1442
					$result = 0;
1443
				}
1444
			}
1445
		}
1446
		$this->setUpperOrLowerCase();
1447
		if ($result >= 0) {
1448
			dol_syslog(get_class($this)."::update verify ok or not done");
1449
1450
			$sql  = "UPDATE ".MAIN_DB_PREFIX."societe SET ";
1451
			$sql .= "entity = ".$this->db->escape($this->entity);
1452
			$sql .= ",nom = '".$this->db->escape($this->name)."'"; // Required
1453
			$sql .= ",name_alias = '".$this->db->escape($this->name_alias)."'";
1454
			$sql .= ",ref_ext = ".(!empty($this->ref_ext) ? "'".$this->db->escape($this->ref_ext)."'" : "null");
1455
			$sql .= ",address = '".$this->db->escape($this->address)."'";
1456
1457
			$sql .= ",zip = ".(!empty($this->zip) ? "'".$this->db->escape($this->zip)."'" : "null");
1458
			$sql .= ",town = ".(!empty($this->town) ? "'".$this->db->escape($this->town)."'" : "null");
1459
1460
			$sql .= ",fk_departement = ".((!empty($this->state_id) && $this->state_id > 0) ? ((int) $this->state_id) : 'null');
1461
			$sql .= ",fk_pays = ".((!empty($this->country_id) && $this->country_id > 0) ? ((int) $this->country_id) : 'null');
1462
1463
			$sql .= ",phone = ".(!empty($this->phone) ? "'".$this->db->escape($this->phone)."'" : "null");
1464
			$sql .= ",fax = ".(!empty($this->fax) ? "'".$this->db->escape($this->fax)."'" : "null");
1465
			$sql .= ",email = ".(!empty($this->email) ? "'".$this->db->escape($this->email)."'" : "null");
1466
			$sql .= ",socialnetworks = '".$this->db->escape(json_encode($this->socialnetworks))."'";
1467
			$sql .= ",url = ".(!empty($this->url) ? "'".$this->db->escape($this->url)."'" : "null");
1468
1469
			$sql .= ",parent = ".($this->parent > 0 ? $this->parent : "null");
1470
1471
			$sql .= ",note_private = ".(!empty($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null");
1472
			$sql .= ",note_public = ".(!empty($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : "null");
1473
1474
			$sql .= ",siren   = '".$this->db->escape($this->idprof1)."'";
1475
			$sql .= ",siret   = '".$this->db->escape($this->idprof2)."'";
1476
			$sql .= ",ape     = '".$this->db->escape($this->idprof3)."'";
1477
			$sql .= ",idprof4 = '".$this->db->escape($this->idprof4)."'";
1478
			$sql .= ",idprof5 = '".$this->db->escape($this->idprof5)."'";
1479
			$sql .= ",idprof6 = '".$this->db->escape($this->idprof6)."'";
1480
1481
			$sql .= ",tva_assuj = ".($this->tva_assuj != '' ? "'".$this->db->escape($this->tva_assuj)."'" : "null");
1482
			$sql .= ",tva_intra = '".$this->db->escape($this->tva_intra)."'";
1483
			$sql .= ",status = ".((int) $this->status);
1484
1485
			// Local taxes
1486
			$sql .= ",localtax1_assuj = ".($this->localtax1_assuj != '' ? "'".$this->db->escape($this->localtax1_assuj)."'" : "null");
1487
			$sql .= ",localtax2_assuj = ".($this->localtax2_assuj != '' ? "'".$this->db->escape($this->localtax2_assuj)."'" : "null");
1488
			if ($this->localtax1_assuj == 1) {
1489
				if ($this->localtax1_value != '') {
1490
					$sql .= ",localtax1_value =".$this->localtax1_value;
1491
				} else {
1492
					$sql .= ",localtax1_value =0.000";
1493
				}
1494
			} else {
1495
				$sql .= ",localtax1_value =0.000";
1496
			}
1497
1498
			if ($this->localtax2_assuj == 1) {
1499
				if ($this->localtax2_value != '') {
1500
					$sql .= ",localtax2_value =".$this->localtax2_value;
1501
				} else {
1502
					$sql .= ",localtax2_value =0.000";
1503
				}
1504
			} else {
1505
				$sql .= ",localtax2_value =0.000";
1506
			}
1507
1508
			$sql .= ",capital = ".($this->capital == '' ? "null" : $this->capital);
1509
1510
			$sql .= ",prefix_comm = ".(!empty($this->prefix_comm) ? "'".$this->db->escape($this->prefix_comm)."'" : "null");
1511
1512
			$sql .= ",fk_effectif = ".($this->effectif_id > 0 ? ((int) $this->effectif_id) : "null");
1513
			if (isset($this->stcomm_id)) {
1514
				$sql .= ",fk_stcomm=".(int) $this->stcomm_id;
1515
			}
1516
			if (isset($this->typent_id)) {
1517
				$sql .= ",fk_typent = ".($this->typent_id > 0 ? ((int) $this->typent_id) : "0");
1518
			}
1519
1520
			$sql .= ",fk_forme_juridique = ".(!empty($this->forme_juridique_code) ? "'".$this->db->escape($this->forme_juridique_code)."'" : "null");
1521
1522
			$sql .= ",mode_reglement = ".(!empty($this->mode_reglement_id) ? "'".$this->db->escape($this->mode_reglement_id)."'" : "null");
1523
			$sql .= ",cond_reglement = ".(!empty($this->cond_reglement_id) ? "'".$this->db->escape($this->cond_reglement_id)."'" : "null");
1524
			$sql .= ",deposit_percent = ".(!empty($this->deposit_percent) ? "'".$this->db->escape($this->deposit_percent)."'" : "null");
1525
			$sql .= ",transport_mode = ".(!empty($this->transport_mode_id) ? "'".$this->db->escape($this->transport_mode_id)."'" : "null");
1526
			$sql .= ",mode_reglement_supplier = ".(!empty($this->mode_reglement_supplier_id) ? "'".$this->db->escape($this->mode_reglement_supplier_id)."'" : "null");
1527
			$sql .= ",cond_reglement_supplier = ".(!empty($this->cond_reglement_supplier_id) ? "'".$this->db->escape($this->cond_reglement_supplier_id)."'" : "null");
1528
			$sql .= ",transport_mode_supplier = ".(!empty($this->transport_mode_supplier_id) ? "'".$this->db->escape($this->transport_mode_supplier_id)."'" : "null");
1529
			$sql .= ",fk_shipping_method = ".(!empty($this->shipping_method_id) ? "'".$this->db->escape($this->shipping_method_id)."'" : "null");
1530
1531
			$sql .= ",client = ".(!empty($this->client) ? $this->client : 0);
1532
			$sql .= ",fournisseur = ".(!empty($this->fournisseur) ? $this->fournisseur : 0);
1533
			$sql .= ",barcode = ".(!empty($this->barcode) ? "'".$this->db->escape($this->barcode)."'" : "null");
1534
			$sql .= ",default_lang = ".(!empty($this->default_lang) ? "'".$this->db->escape($this->default_lang)."'" : "null");
1535
			$sql .= ",logo = ".(!empty($this->logo) ? "'".$this->db->escape($this->logo)."'" : "null");
1536
			$sql .= ",logo_squarred = ".(!empty($this->logo_squarred) ? "'".$this->db->escape($this->logo_squarred)."'" : "null");
1537
			$sql .= ",outstanding_limit= ".($this->outstanding_limit != '' ? $this->outstanding_limit : 'null');
1538
			$sql .= ",order_min_amount= ".($this->order_min_amount != '' ? $this->order_min_amount : 'null');
1539
			$sql .= ",supplier_order_min_amount= ".($this->supplier_order_min_amount != '' ? $this->supplier_order_min_amount : 'null');
1540
			$sql .= ",fk_prospectlevel='".$this->db->escape($this->fk_prospectlevel)."'";
1541
			if (empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) {
1542
				$sql .= ", accountancy_code_buy = '".$this->db->escape($this->accountancy_code_buy)."'";
1543
				$sql .= ", accountancy_code_sell= '".$this->db->escape($this->accountancy_code_sell)."'";
1544
1545
				if ($customer) {
1546
					$sql .= ", code_compta = ".(!empty($this->code_compta_client) ? "'".$this->db->escape($this->code_compta_client)."'" : "null");
1547
				}
1548
1549
				if ($supplier) {
1550
					$sql .= ", code_compta_fournisseur = ".(($this->code_compta_fournisseur != "") ? "'".$this->db->escape($this->code_compta_fournisseur)."'" : "null");
1551
				}
1552
			}
1553
			$sql .= ",webservices_url = ".(!empty($this->webservices_url) ? "'".$this->db->escape($this->webservices_url)."'" : "null");
1554
			$sql .= ",webservices_key = ".(!empty($this->webservices_key) ? "'".$this->db->escape($this->webservices_key)."'" : "null");
1555
1556
			//Incoterms
1557
			$sql .= ", fk_incoterms = ".((int) $this->fk_incoterms);
1558
			$sql .= ", location_incoterms = ".(!empty($this->location_incoterms) ? "'".$this->db->escape($this->location_incoterms)."'" : "null");
1559
1560
			if ($customer) {
1561
				$sql .= ", code_client = ".(!empty($this->code_client) ? "'".$this->db->escape($this->code_client)."'" : "null");
1562
			}
1563
1564
			if ($supplier) {
1565
				$sql .= ", code_fournisseur = ".(!empty($this->code_fournisseur) ? "'".$this->db->escape($this->code_fournisseur)."'" : "null");
1566
			}
1567
			$sql .= ", fk_user_modif = ".($user->id > 0 ? $user->id : "null");
1568
			$sql .= ", fk_multicurrency = ".(int) $this->fk_multicurrency;
1569
			$sql .= ", multicurrency_code = '".$this->db->escape($this->multicurrency_code)."'";
1570
			$sql .= ", model_pdf = '".$this->db->escape($this->model_pdf)."'";
1571
			$sql .= " WHERE rowid = ".(int) $id;
1572
1573
			$resql = $this->db->query($sql);
1574
			if ($resql) {
1575
				if (is_object($this->oldcopy)) {	// If we have information on old values
1576
					if ($this->oldcopy->country_id != $this->country_id) {
1577
						unset($this->country_code);
1578
						unset($this->country);
1579
					}
1580
					if ($this->oldcopy->state_id != $this->state_id) {
1581
						unset($this->state_code);
1582
						unset($this->state);
1583
					}
1584
				} else {
1585
					unset($this->country_code); // We clean this, in the doubt, because it may have been changed after an update of country_id
1586
					unset($this->country);
1587
					unset($this->state_code);
1588
					unset($this->state);
1589
				}
1590
1591
				$nbrowsaffected = $this->db->affected_rows($resql);
1592
1593
				if (!$error && $nbrowsaffected) {
1594
					// Update information on linked member if it is an update
1595
					if (!$nosyncmember && isModEnabled('adherent')) {
1596
						require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1597
1598
						dol_syslog(get_class($this)."::update update linked member");
1599
1600
						$lmember = new Adherent($this->db);
1601
						$result = $lmember->fetch(0, 0, $this->id);
1602
1603
						if ($result > 0) {
1604
							$lmember->company = $this->name;
1605
							//$lmember->firstname=$this->firstname?$this->firstname:$lmember->firstname;	// We keep firstname and lastname of member unchanged
1606
							//$lmember->lastname=$this->lastname?$this->lastname:$lmember->lastname;		// We keep firstname and lastname of member unchanged
1607
							$lmember->address = $this->address;
1608
							$lmember->zip = $this->zip;
1609
							$lmember->town = $this->town;
1610
							$lmember->email = $this->email;
1611
							$lmember->socialnetworks = $this->socialnetworks;
1612
							$lmember->phone = $this->phone;
1613
							$lmember->state_id = $this->state_id;
1614
							$lmember->country_id = $this->country_id;
1615
							$lmember->default_lang = $this->default_lang;
1616
1617
							$result = $lmember->update($user, 0, 1, 1, 1); // Use nosync to 1 to avoid cyclic updates
1618
							if ($result < 0) {
1619
								$this->error = $lmember->error;
1620
								$this->errors = array_merge($this->errors, $lmember->errors);
1621
								dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
1622
								$error++;
1623
							}
1624
						} elseif ($result < 0) {
1625
							$this->error = $lmember->error;
1626
							$error++;
1627
						}
1628
					}
1629
				}
1630
1631
				$action = 'update';
1632
1633
				// update accountancy for this entity
1634
				if (!$error && !empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) {
1635
					$this->db->query("DELETE FROM ".MAIN_DB_PREFIX."societe_perentity WHERE fk_soc = ".((int) $this->id)." AND entity = ".((int) $conf->entity));
1636
1637
					$sql = "INSERT INTO ".MAIN_DB_PREFIX."societe_perentity (";
1638
					$sql .= " fk_soc";
1639
					$sql .= ", entity";
1640
					$sql .= ", accountancy_code_customer";
1641
					$sql .= ", accountancy_code_supplier";
1642
					$sql .= ", accountancy_code_buy";
1643
					$sql .= ", accountancy_code_sell";
1644
					$sql .= ") VALUES (";
1645
					$sql .= $this->id;
1646
					$sql .= ", ".$conf->entity;
1647
					$sql .= ", '".$this->db->escape($this->code_compta_client)."'";
1648
					$sql .= ", '".$this->db->escape($this->code_compta_fournisseur)."'";
1649
					$sql .= ", '".$this->db->escape($this->accountancy_code_buy)."'";
1650
					$sql .= ", '".$this->db->escape($this->accountancy_code_sell)."'";
1651
					$sql .= ")";
1652
					$result = $this->db->query($sql);
1653
					if (!$result) {
1654
						$error++;
1655
						$this->error = 'ErrorFailedToUpdateAccountancyForEntity';
1656
					}
1657
				}
1658
1659
				// Actions on extra fields
1660
				if (!$error) {
1661
					$result = $this->insertExtraFields();
1662
					if ($result < 0) {
1663
						$error++;
1664
					}
1665
				}
1666
				// Actions on extra languages
1667
				if (!$error && empty($conf->global->MAIN_EXTRALANGUAGES_DISABLED)) { // For avoid conflicts if trigger used
1668
					$result = $this->insertExtraLanguages();
1669
					if ($result < 0) {
1670
						$error++;
1671
					}
1672
				}
1673
1674
				if (!$error && $call_trigger) {
1675
					// Call trigger
1676
					$result = $this->call_trigger('COMPANY_MODIFY', $user);
1677
					if ($result < 0) {
1678
						$error++;
1679
					}
1680
					// End call triggers
1681
				}
1682
1683
				if (!$error) {
1684
					dol_syslog(get_class($this)."::Update success");
1685
					$this->db->commit();
1686
					return 1;
1687
				} else {
1688
					$this->db->rollback();
1689
					return -1;
1690
				}
1691
			} else {
1692
				if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
1693
					// Doublon
1694
					$this->error = $langs->trans("ErrorDuplicateField");
1695
					$result = -1;
1696
				} else {
1697
					$this->error = $this->db->lasterror();
1698
					$result = -2;
1699
				}
1700
				$this->db->rollback();
1701
				return $result;
1702
			}
1703
		} else {
1704
			$this->db->rollback();
1705
			dol_syslog(get_class($this)."::Update fails verify ".join(',', $this->errors), LOG_WARNING);
1706
			return -3;
1707
		}
1708
	}
1709
1710
	/**
1711
	 *    Load a third party from database into memory
1712
	 *
1713
	 *    @param	int		$rowid			Id of third party to load
1714
	 *    @param    string	$ref			Reference of third party, name (Warning, this can return several records)
1715
	 *    @param    string	$ref_ext       	External reference of third party (Warning, this information is a free field not provided by Dolibarr)
1716
	 *    @param    string	$barcode       	Barcode of third party to load
1717
	 *    @param    string	$idprof1		Prof id 1 of third party (Warning, this can return several records)
1718
	 *    @param    string	$idprof2		Prof id 2 of third party (Warning, this can return several records)
1719
	 *    @param    string	$idprof3		Prof id 3 of third party (Warning, this can return several records)
1720
	 *    @param    string	$idprof4		Prof id 4 of third party (Warning, this can return several records)
1721
	 *    @param    string	$idprof5		Prof id 5 of third party (Warning, this can return several records)
1722
	 *    @param    string	$idprof6		Prof id 6 of third party (Warning, this can return several records)
1723
	 *    @param    string	$email   		Email of third party (Warning, this can return several records)
1724
	 *    @param    string	$ref_alias 		Name_alias of third party (Warning, this can return several records)
1725
	 *    @return   int						>0 if OK, <0 if KO or if two records found for same ref or idprof, 0 if not found.
1726
	 */
1727
	public function fetch($rowid, $ref = '', $ref_ext = '', $barcode = '', $idprof1 = '', $idprof2 = '', $idprof3 = '', $idprof4 = '', $idprof5 = '', $idprof6 = '', $email = '', $ref_alias = '')
1728
	{
1729
		global $langs;
1730
		global $conf;
1731
1732
		if (empty($rowid) && empty($ref) && empty($ref_ext) && empty($barcode) && empty($idprof1) && empty($idprof2) && empty($idprof3) && empty($idprof4) && empty($idprof5) && empty($idprof6) && empty($email)) {
1733
			return -1;
1734
		}
1735
1736
		$sql = 'SELECT s.rowid, s.nom as name, s.name_alias, s.entity, s.ref_ext, s.address, s.datec as date_creation, s.prefix_comm';
1737
		$sql .= ', s.status, s.fk_warehouse';
1738
		$sql .= ', s.price_level';
1739
		$sql .= ', s.tms as date_modification, s.fk_user_creat, s.fk_user_modif';
1740
		$sql .= ', s.phone, s.fax, s.email';
1741
		$sql .= ', s.socialnetworks';
1742
		$sql .= ', s.url, s.zip, s.town, s.note_private, s.note_public, s.client, s.fournisseur';
1743
		$sql .= ', s.siren as idprof1, s.siret as idprof2, s.ape as idprof3, s.idprof4, s.idprof5, s.idprof6';
1744
		$sql .= ', s.capital, s.tva_intra';
1745
		$sql .= ', s.fk_typent as typent_id';
1746
		$sql .= ', s.fk_effectif as effectif_id';
1747
		$sql .= ', s.fk_forme_juridique as forme_juridique_code';
1748
		$sql .= ', s.webservices_url, s.webservices_key, s.model_pdf, s.last_main_doc';
1749
		if (empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) {
1750
			$sql .= ', s.code_compta, s.code_compta_fournisseur, s.accountancy_code_buy, s.accountancy_code_sell';
1751
		} else {
1752
			$sql .= ', spe.accountancy_code_customer as code_compta, spe.accountancy_code_supplier as code_compta_fournisseur, spe.accountancy_code_buy, spe.accountancy_code_sell';
1753
		}
1754
		$sql .= ', s.code_client, s.code_fournisseur, s.parent, s.barcode';
1755
		$sql .= ', s.fk_departement as state_id, s.fk_pays as country_id, s.fk_stcomm, s.mode_reglement, s.cond_reglement, s.deposit_percent, s.transport_mode';
1756
		$sql .= ', s.fk_account, s.tva_assuj';
1757
		$sql .= ', s.mode_reglement_supplier, s.cond_reglement_supplier, s.transport_mode_supplier';
1758
		$sql .= ', s.localtax1_assuj, s.localtax1_value, s.localtax2_assuj, s.localtax2_value, s.fk_prospectlevel, s.default_lang, s.logo, s.logo_squarred';
1759
		$sql .= ', s.fk_shipping_method';
1760
		$sql .= ', s.outstanding_limit, s.import_key, s.canvas, s.fk_incoterms, s.location_incoterms';
1761
		$sql .= ', s.order_min_amount, s.supplier_order_min_amount';
1762
		$sql .= ', s.fk_multicurrency, s.multicurrency_code';
1763
		$sql .= ', fj.libelle as forme_juridique';
1764
		$sql .= ', e.libelle as effectif';
1765
		$sql .= ', c.code as country_code, c.label as country';
1766
		$sql .= ', d.code_departement as state_code, d.nom as state';
1767
		$sql .= ', r.rowid as region_id, r.code_region as region_code';
1768
		$sql .= ', st.libelle as stcomm, st.picto as stcomm_picto';
1769
		$sql .= ', te.code as typent_code';
1770
		$sql .= ', i.libelle as label_incoterms';
1771
		if (!isModEnabled('multicompany')) {
1772
			$sql .= ', s.remise_client, s.remise_supplier';
1773
		} else {
1774
			$sql .= ', sr.remise_client, sr2.remise_supplier';
1775
		}
1776
		$sql .= ' FROM '.MAIN_DB_PREFIX.'societe as s';
1777
		if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) {
1778
			$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe_perentity as spe ON spe.fk_soc = s.rowid AND spe.entity = ".((int) $conf->entity);
1779
		}
1780
		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_effectif as e ON s.fk_effectif = e.id';
1781
		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_country as c ON s.fk_pays = c.rowid';
1782
		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_stcomm as st ON s.fk_stcomm = st.id';
1783
		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_forme_juridique as fj ON s.fk_forme_juridique = fj.code';
1784
		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_departements as d ON s.fk_departement = d.rowid';
1785
		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_regions as r ON d.fk_region = r.code_region ';
1786
		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_typent as te ON s.fk_typent = te.id';
1787
		$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_incoterms as i ON s.fk_incoterms = i.rowid';
1788
		// With default setup, llx_societe_remise is a history table in default setup and current value is in llx_societe.
1789
		// We use it for real value when multicompany is on. A better place would be into llx_societe_perentity.
1790
		if (isModEnabled('multicompany')) {
1791
			$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'societe_remise as sr ON sr.rowid = (SELECT MAX(rowid) FROM '.MAIN_DB_PREFIX.'societe_remise WHERE fk_soc = s.rowid AND entity IN ('.getEntity('discount').'))';
1792
			$sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'societe_remise_supplier as sr2 ON sr2.rowid = (SELECT MAX(rowid) FROM '.MAIN_DB_PREFIX.'societe_remise_supplier WHERE fk_soc = s.rowid AND entity IN ('.getEntity('discount').'))';
1793
		}
1794
		$sql .= ' WHERE s.entity IN ('.getEntity($this->element).')';
1795
		if ($rowid) {
1796
			$sql .= ' AND s.rowid = '.((int) $rowid);
1797
		}
1798
		if ($ref) {
1799
			$sql .= " AND s.nom = '".$this->db->escape($ref)."'";
1800
		}
1801
		if ($ref_alias) {
1802
			$sql .= " AND s.name_alias = '".$this->db->escape($ref_alias)."'";
1803
		}
1804
		if ($ref_ext) {
1805
			$sql .= " AND s.ref_ext = '".$this->db->escape($ref_ext)."'";
1806
		}
1807
		if ($barcode) {
1808
			$sql .= " AND s.barcode = '".$this->db->escape($barcode)."'";
1809
		}
1810
		if ($idprof1) {
1811
			$sql .= " AND s.siren = '".$this->db->escape($idprof1)."'";
1812
		}
1813
		if ($idprof2) {
1814
			$sql .= " AND s.siret = '".$this->db->escape($idprof2)."'";
1815
		}
1816
		if ($idprof3) {
1817
			$sql .= " AND s.ape = '".$this->db->escape($idprof3)."'";
1818
		}
1819
		if ($idprof4) {
1820
			$sql .= " AND s.idprof4 = '".$this->db->escape($idprof4)."'";
1821
		}
1822
		if ($idprof5) {
1823
			$sql .= " AND s.idprof5 = '".$this->db->escape($idprof5)."'";
1824
		}
1825
		if ($idprof6) {
1826
			$sql .= " AND s.idprof6 = '".$this->db->escape($idprof6)."'";
1827
		}
1828
		if ($email) {
1829
			$sql .= " AND s.email = '".$this->db->escape($email)."'";
1830
		}
1831
1832
		$resql = $this->db->query($sql);
1833
		if ($resql) {
1834
			$num = $this->db->num_rows($resql);
1835
			if ($num > 1) {
1836
				$this->error = 'Fetch found several records. Rename one of thirdparties to avoid duplicate.';
1837
				dol_syslog($this->error, LOG_ERR);
1838
				$result = -2;
1839
			} elseif ($num) {   // $num = 1
1840
				$obj = $this->db->fetch_object($resql);
1841
1842
				$this->id           = $obj->rowid;
1843
				$this->entity       = $obj->entity;
1844
				$this->canvas = $obj->canvas;
1845
1846
				$this->ref          = $obj->rowid;
1847
				$this->name = $obj->name;
1848
				$this->nom          = $obj->name; // deprecated
1849
				$this->name_alias = $obj->name_alias;
1850
				$this->ref_ext      = $obj->ref_ext;
1851
1852
				$this->date_creation     = $this->db->jdate($obj->date_creation);
1853
				$this->date_modification = $this->db->jdate($obj->date_modification);
1854
				$this->user_creation     = $obj->fk_user_creat;
1855
				$this->user_modification = $obj->fk_user_modif;
1856
1857
				$this->address = $obj->address;
1858
				$this->zip 			= $obj->zip;
1859
				$this->town 		= $obj->town;
1860
1861
				$this->country_id   = $obj->country_id;
1862
				$this->country_code = $obj->country_id ? $obj->country_code : '';
1863
				$this->country = $obj->country_id ? (($langs->transnoentities('Country'.$obj->country_code) != 'Country'.$obj->country_code) ? $langs->transnoentities('Country'.$obj->country_code) : $obj->country) : '';
1864
1865
				$this->state_id     = $obj->state_id;
1866
				$this->state_code   = $obj->state_code;
1867
				$this->region_id    = $obj->region_id;
1868
				$this->region_code = $obj->region_code;
1869
				$this->state        = ($obj->state != '-' ? $obj->state : '');
1870
1871
				$transcode = $langs->trans('StatusProspect'.$obj->fk_stcomm);
1872
				$label = ($transcode != 'StatusProspect'.$obj->fk_stcomm ? $transcode : $obj->stcomm);
1873
				$this->stcomm_id = $obj->fk_stcomm; // id status prospect
1874
				$this->status_prospect_label = $label; // label status prospect
1875
				$this->stcomm_picto = $obj->stcomm_picto; // picto statut commercial
1876
1877
				$this->email = $obj->email;
1878
				$this->socialnetworks = ($obj->socialnetworks ? (array) json_decode($obj->socialnetworks, true) : array());
1879
1880
				$this->url = $obj->url;
1881
				$this->phone = $obj->phone;
1882
				$this->fax = $obj->fax;
1883
1884
				$this->parent = $obj->parent;
1885
1886
				$this->idprof1		= $obj->idprof1;
1887
				$this->idprof2		= $obj->idprof2;
1888
				$this->idprof3		= $obj->idprof3;
1889
				$this->idprof4		= $obj->idprof4;
1890
				$this->idprof5		= $obj->idprof5;
1891
				$this->idprof6		= $obj->idprof6;
1892
1893
				$this->capital = $obj->capital;
1894
1895
				$this->code_client = $obj->code_client;
1896
				$this->code_fournisseur = $obj->code_fournisseur;
1897
1898
				$this->code_compta = $obj->code_compta;			// For backward compatibility
1899
				$this->code_compta_client = $obj->code_compta;
1900
				$this->code_compta_fournisseur = $obj->code_compta_fournisseur;
1901
1902
				$this->barcode = $obj->barcode;
1903
1904
				$this->tva_assuj      = $obj->tva_assuj;
1905
				$this->tva_intra      = $obj->tva_intra;
1906
				$this->status = $obj->status;
1907
1908
				// Local Taxes
1909
				$this->localtax1_assuj      = $obj->localtax1_assuj;
1910
				$this->localtax2_assuj      = $obj->localtax2_assuj;
1911
1912
				$this->localtax1_value		= $obj->localtax1_value;
1913
				$this->localtax2_value		= $obj->localtax2_value;
1914
1915
				$this->typent_id      = $obj->typent_id;
1916
				$this->typent_code    = $obj->typent_code;
1917
1918
				$this->effectif_id    = $obj->effectif_id;
1919
				$this->effectif       = $obj->effectif_id ? $obj->effectif : '';
1920
1921
				$this->forme_juridique_code = $obj->forme_juridique_code;
1922
				$this->forme_juridique = $obj->forme_juridique_code ? $obj->forme_juridique : '';
1923
1924
				$this->fk_prospectlevel = $obj->fk_prospectlevel;
1925
1926
				$this->prefix_comm = $obj->prefix_comm;
1927
1928
				$this->remise_percent = $obj->remise_client ? price2num($obj->remise_client) : 0; // 0.000000 must be 0
1929
				$this->remise_supplier_percent = $obj->remise_supplier;
1930
1931
				$this->mode_reglement_id 	= $obj->mode_reglement;
1932
				$this->cond_reglement_id 	= $obj->cond_reglement;
1933
				$this->deposit_percent		= $obj->deposit_percent;
1934
				$this->transport_mode_id 	= $obj->transport_mode;
1935
				$this->mode_reglement_supplier_id 	= $obj->mode_reglement_supplier;
1936
				$this->cond_reglement_supplier_id 	= $obj->cond_reglement_supplier;
1937
				$this->transport_mode_supplier_id = $obj->transport_mode_supplier;
1938
				$this->shipping_method_id = ($obj->fk_shipping_method > 0) ? $obj->fk_shipping_method : null;
1939
				$this->fk_account = $obj->fk_account;
1940
1941
				$this->client = $obj->client;
1942
				$this->fournisseur = $obj->fournisseur;
1943
1944
				$this->note = $obj->note_private; // TODO Deprecated for backward comtability
1945
				$this->note_private = $obj->note_private;
1946
				$this->note_public = $obj->note_public;
1947
				$this->model_pdf = $obj->model_pdf;
1948
				$this->modelpdf = $obj->model_pdf; // deprecated
1949
				$this->default_lang = $obj->default_lang;
1950
				$this->logo = $obj->logo;
1951
				$this->logo_squarred = $obj->logo_squarred;
1952
1953
				$this->webservices_url = $obj->webservices_url;
1954
				$this->webservices_key = $obj->webservices_key;
1955
1956
				$this->accountancy_code_buy     = $obj->accountancy_code_buy;
1957
				$this->accountancy_code_sell    = $obj->accountancy_code_sell;
1958
1959
				$this->outstanding_limit		= $obj->outstanding_limit;
1960
				$this->order_min_amount			= $obj->order_min_amount;
1961
				$this->supplier_order_min_amount = $obj->supplier_order_min_amount;
1962
1963
				// multiprix
1964
				$this->price_level = $obj->price_level;
1965
1966
				// warehouse
1967
				$this->fk_warehouse = $obj->fk_warehouse;
1968
1969
				$this->import_key = $obj->import_key;
1970
1971
				//Incoterms
1972
				$this->fk_incoterms = $obj->fk_incoterms;
1973
				$this->location_incoterms = $obj->location_incoterms;
1974
				$this->label_incoterms = $obj->label_incoterms;
1975
1976
				// multicurrency
1977
				$this->fk_multicurrency = $obj->fk_multicurrency;
1978
				$this->multicurrency_code = $obj->multicurrency_code;
1979
1980
				// pdf
1981
				$this->model_pdf = $obj->model_pdf;
1982
				$this->last_main_doc = $obj->last_main_doc;
1983
1984
				$result = 1;
1985
1986
				// fetch optionals attributes and labels
1987
				$this->fetch_optionals();
1988
			} else {
1989
				$result = 0;
1990
			}
1991
1992
			$this->db->free($resql);
1993
		} else {
1994
			$this->error = $this->db->lasterror();
1995
			$this->errors[] = $this->db->lasterror();
1996
			$result = -3;
1997
		}
1998
1999
		// Use first price level if level not defined for third party
2000
		if ((!empty($conf->global->PRODUIT_MULTIPRICES) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) && empty($this->price_level)) {
2001
			$this->price_level = 1;
2002
		}
2003
2004
		return $result;
2005
	}
2006
2007
	/**
2008
	 *    Delete a third party from database and all its dependencies (contacts, rib...)
2009
	 *
2010
	 *    @param	int		$id             Id of third party to delete
2011
	 *    @param    User    $fuser          User who ask to delete thirdparty
2012
	 *    @param    int		$call_trigger   0=No, 1=yes
2013
	 *    @return	int						<0 if KO, 0 if nothing done, >0 if OK
2014
	 */
2015
	public function delete($id, User $fuser = null, $call_trigger = 1)
2016
	{
2017
		global $langs, $conf, $user;
2018
2019
		if (empty($fuser)) {
2020
			$fuser = $user;
2021
		}
2022
2023
		require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
2024
2025
		$entity = isset($this->entity) ? $this->entity : $conf->entity;
2026
2027
		dol_syslog(get_class($this)."::delete", LOG_DEBUG);
2028
		$error = 0;
2029
2030
		// Test if child exists
2031
		$objectisused = $this->isObjectUsed($id);
2032
		if (empty($objectisused)) {
2033
			$this->db->begin();
2034
2035
			// User is mandatory for trigger call
2036
			if (!$error && $call_trigger) {
2037
				// Call trigger
2038
				$result = $this->call_trigger('COMPANY_DELETE', $fuser);
2039
				if ($result < 0) {
2040
					$error++;
2041
				}
2042
				// End call triggers
2043
			}
2044
2045
			if (!$error) {
2046
				require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
2047
				$static_cat = new Categorie($this->db);
2048
				$toute_categs = array();
2049
2050
				// Fill $toute_categs array with an array of (type => array of ("Categorie" instance))
2051
				if ($this->client || $this->prospect) {
2052
					$toute_categs['customer'] = $static_cat->containing($this->id, Categorie::TYPE_CUSTOMER);
2053
				}
2054
				if ($this->fournisseur) {
2055
					$toute_categs['supplier'] = $static_cat->containing($this->id, Categorie::TYPE_SUPPLIER);
2056
				}
2057
2058
				// Remove each "Categorie"
2059
				foreach ($toute_categs as $type => $categs_type) {
2060
					foreach ($categs_type as $cat) {
2061
						$cat->del_type($this, $type);
2062
					}
2063
				}
2064
			}
2065
2066
			if (!$error) {
2067
				foreach ($this->childtablesoncascade as $tabletodelete) {
2068
					$deleteFromObject = explode(':', $tabletodelete);
2069
					if (count($deleteFromObject) >= 2) {
2070
						$className = str_replace('@', '', $deleteFromObject[0]);
2071
						$filepath = $deleteFromObject[1];
2072
						$columnName = $deleteFromObject[2];
2073
						if (dol_include_once($filepath)) {
2074
							$child_object = new $className($this->db);
2075
							$result = $child_object->deleteByParentField($id, $columnName);
2076
							if ($result < 0) {
2077
								$error++;
2078
								$this->errors[] = $child_object->error;
2079
								break;
2080
							}
2081
						} else {
2082
							$error++;
2083
							$this->errors[] = 'Cannot include child class file '.$filepath;
2084
							break;
2085
						}
2086
					} else {
2087
						$sql = "DELETE FROM ".MAIN_DB_PREFIX.$tabletodelete;
2088
						$sql .= " WHERE fk_soc = ".((int) $id);
2089
						if (!$this->db->query($sql)) {
2090
							$error++;
2091
							$this->errors[] = $this->db->lasterror();
2092
							break;
2093
						}
2094
					}
2095
				}
2096
			}
2097
2098
			// Removed extrafields
2099
			if (!$error) {
2100
				$result = $this->deleteExtraFields();
2101
				if ($result < 0) {
2102
					$error++;
2103
					dol_syslog(get_class($this)."::delete error -3 ".$this->error, LOG_ERR);
2104
				}
2105
			}
2106
2107
			// Remove links to subsidiaries companies
2108
			if (!$error) {
2109
				$sql = "UPDATE ".MAIN_DB_PREFIX."societe";
2110
				$sql .= " SET parent = NULL";
2111
				$sql .= " WHERE parent = ".((int) $id);
2112
				if (!$this->db->query($sql)) {
2113
					$error++;
2114
					$this->errors[] = $this->db->lasterror();
2115
				}
2116
			}
2117
2118
			// Remove third party
2119
			if (!$error) {
2120
				if (!empty($conf->global->MAIN_COMPANY_PERENTITY_SHARED)) {
2121
					$sql = "DELETE FROM ".MAIN_DB_PREFIX."societe_perentity";
2122
					$sql .= " WHERE fk_soc = ".((int) $id);
2123
					if (!$this->db->query($sql)) {
2124
						$error++;
2125
						$this->errors[] = $this->db->lasterror();
2126
					}
2127
				}
2128
2129
				$sql = "DELETE FROM ".MAIN_DB_PREFIX."societe";
2130
				$sql .= " WHERE rowid = ".((int) $id);
2131
				if (!$this->db->query($sql)) {
2132
					$error++;
2133
					$this->errors[] = $this->db->lasterror();
2134
				}
2135
			}
2136
2137
			if (!$error) {
2138
				$this->db->commit();
2139
2140
				// Delete directory
2141
				if (!empty($conf->societe->multidir_output[$entity])) {
2142
					$docdir = $conf->societe->multidir_output[$entity]."/".$id;
2143
					if (dol_is_dir($docdir)) {
2144
						dol_delete_dir_recursive($docdir);
2145
					}
2146
				}
2147
2148
				return 1;
2149
			} else {
2150
				dol_syslog($this->error, LOG_ERR);
2151
				$this->db->rollback();
2152
				return -1;
2153
			}
2154
		} else {
2155
			dol_syslog("Can't remove thirdparty with id ".$id.". There is ".$objectisused." childs", LOG_WARNING);
2156
		}
2157
		return 0;
2158
	}
2159
2160
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2161
	/**
2162
	 *  Define third party as a customer
2163
	 *
2164
	 *	@return		int		<0 if KO, >0 if OK
2165
	 */
2166
	public function set_as_client()
2167
	{
2168
		// phpcs:enable
2169
		if ($this->id) {
2170
			$newclient = 1;
2171
			if ($this->client == 2 || $this->client == 3) {
2172
				$newclient = 3; //If prospect, we keep prospect tag
2173
			}
2174
			$sql = "UPDATE ".MAIN_DB_PREFIX."societe";
2175
			$sql .= " SET client = ".((int) $newclient);
2176
			$sql .= " WHERE rowid = ".((int) $this->id);
2177
2178
			$resql = $this->db->query($sql);
2179
			if ($resql) {
2180
				$this->client = $newclient;
2181
				return 1;
2182
			} else {
2183
				return -1;
2184
			}
2185
		}
2186
		return 0;
2187
	}
2188
2189
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2190
	/**
2191
	 *  Defines the company as a customer
2192
	 *
2193
	 *  @param	float	$remise		Value in % of the discount
2194
	 *  @param  string	$note		Note/Reason for changing the discount
2195
	 *  @param  User	$user		User who sets the discount
2196
	 *	@return	int					<0 if KO, >0 if OK
2197
	 */
2198
	public function set_remise_client($remise, $note, User $user)
2199
	{
2200
		// phpcs:enable
2201
		global $conf, $langs;
2202
2203
		// Parameter cleaning
2204
		$note = trim($note);
2205
		if (!$note) {
2206
			$this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("NoteReason"));
2207
			return -2;
2208
		}
2209
2210
		dol_syslog(get_class($this)."::set_remise_client ".$remise.", ".$note.", ".$user->id);
2211
2212
		if ($this->id) {
2213
			$this->db->begin();
2214
2215
			$now = dol_now();
2216
2217
			// Position current discount
2218
			$sql = "UPDATE ".MAIN_DB_PREFIX."societe ";
2219
			$sql .= " SET remise_client = '".$this->db->escape($remise)."'";
2220
			$sql .= " WHERE rowid = ".((int) $this->id);
2221
			$resql = $this->db->query($sql);
2222
			if (!$resql) {
2223
				$this->db->rollback();
2224
				$this->error = $this->db->error();
2225
				return -1;
2226
			}
2227
2228
			// Writes trace in discount history
2229
			$sql = "INSERT INTO ".MAIN_DB_PREFIX."societe_remise";
2230
			$sql .= " (entity, datec, fk_soc, remise_client, note, fk_user_author)";
2231
			$sql .= " VALUES (".$conf->entity.", '".$this->db->idate($now)."', ".((int) $this->id).", '".$this->db->escape($remise)."',";
2232
			$sql .= " '".$this->db->escape($note)."',";
2233
			$sql .= " ".((int) $user->id);
2234
			$sql .= ")";
2235
2236
			$resql = $this->db->query($sql);
2237
			if (!$resql) {
2238
				$this->db->rollback();
2239
				$this->error = $this->db->lasterror();
2240
				return -1;
2241
			}
2242
2243
			$this->db->commit();
2244
2245
			return 1;
2246
		}
2247
	}
2248
2249
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2250
	/**
2251
	 *  Defines the company as a customer
2252
	 *
2253
	 *  @param	float	$remise		Value in % of the discount
2254
	 *  @param  string	$note		Note/Reason for changing the discount
2255
	 *  @param  User	$user		User who sets the discount
2256
	 *	@return	int					<0 if KO, >0 if OK
2257
	 */
2258
	public function set_remise_supplier($remise, $note, User $user)
2259
	{
2260
		// phpcs:enable
2261
		global $conf, $langs;
2262
2263
		// Parameter cleaning
2264
		$note = trim($note);
2265
		if (!$note) {
2266
			$this->error = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("NoteReason"));
2267
			return -2;
2268
		}
2269
2270
		dol_syslog(get_class($this)."::set_remise_supplier ".$remise.", ".$note.", ".$user->id);
2271
2272
		if ($this->id) {
2273
			$this->db->begin();
2274
2275
			$now = dol_now();
2276
2277
			// Position current discount
2278
			$sql = "UPDATE ".MAIN_DB_PREFIX."societe ";
2279
			$sql .= " SET remise_supplier = '".$this->db->escape($remise)."'";
2280
			$sql .= " WHERE rowid = ".((int) $this->id);
2281
			$resql = $this->db->query($sql);
2282
			if (!$resql) {
2283
				$this->db->rollback();
2284
				$this->error = $this->db->error();
2285
				return -1;
2286
			}
2287
2288
			// Writes trace in discount history
2289
			$sql = "INSERT INTO ".MAIN_DB_PREFIX."societe_remise_supplier";
2290
			$sql .= " (entity, datec, fk_soc, remise_supplier, note, fk_user_author)";
2291
			$sql .= " VALUES (".$conf->entity.", '".$this->db->idate($now)."', ".((int) $this->id).", '".$this->db->escape($remise)."',";
2292
			$sql .= " '".$this->db->escape($note)."',";
2293
			$sql .= " ".((int) $user->id);
2294
			$sql .= ")";
2295
2296
			$resql = $this->db->query($sql);
2297
			if (!$resql) {
2298
				$this->db->rollback();
2299
				$this->error = $this->db->lasterror();
2300
				return -1;
2301
			}
2302
2303
			$this->db->commit();
2304
			return 1;
2305
		}
2306
2307
		return -1;
2308
	}
2309
2310
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2311
	/**
2312
	 *    	Add a discount for third party
2313
	 *
2314
	 *    	@param	float	$remise     		Amount of discount
2315
	 *    	@param  User	$user       		User adding discount
2316
	 *    	@param  string	$desc				Reason of discount
2317
	 *      @param  string	$vatrate     		VAT rate (may contain the vat code too). Exemple: '1.23', '1.23 (ABC)', ...
2318
	 *      @param	int		$discount_type		0 => customer discount, 1 => supplier discount
2319
	 *      @param	string	$price_base_type	Price base type 'HT' or 'TTC'
2320
	 *		@return	int							<0 if KO, id of discount record if OK
2321
	 */
2322
	public function set_remise_except($remise, User $user, $desc, $vatrate = '', $discount_type = 0, $price_base_type = 'HT')
2323
	{
2324
		// phpcs:enable
2325
		global $langs;
2326
2327
		// Clean parameters
2328
		$remise = price2num($remise);
2329
		$desc = trim($desc);
2330
2331
		// Check parameters
2332
		if (!($remise > 0)) {
2333
			$this->error = $langs->trans("ErrorWrongValueForParameter", "1");
2334
			return -1;
2335
		}
2336
		if (!$desc) {
2337
			$this->error = $langs->trans("ErrorWrongValueForParameter", "3");
2338
			return -2;
2339
		}
2340
2341
		if ($this->id > 0) {
2342
			// Clean vat code
2343
			$reg = array();
2344
			$vat_src_code = '';
2345
			if (preg_match('/\((.*)\)/', $vatrate, $reg)) {
2346
				$vat_src_code = $reg[1];
2347
				$vatrate = preg_replace('/\s*\(.*\)/', '', $vatrate); // Remove code into vatrate.
2348
			}
2349
2350
			require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
2351
2352
			$discount = new DiscountAbsolute($this->db);
2353
			$discount->fk_soc = $this->id;
2354
2355
			$discount->discount_type = $discount_type;
2356
2357
			if ($price_base_type == 'TTC') {
2358
				$discount->amount_ttc = $discount->multicurrency_amount_ttc = price2num($remise, 'MT');
2359
				$discount->amount_ht = $discount->multicurrency_amount_ht = price2num($remise / (1 + $vatrate / 100), 'MT');
2360
				$discount->amount_tva = $discount->multicurrency_amount_tva = price2num($discount->amount_ttc - $discount->amount_ht, 'MT');
2361
			} else {
2362
				$discount->amount_ht = $discount->multicurrency_amount_ht = price2num($remise, 'MT');
2363
				$discount->amount_tva = $discount->multicurrency_amount_tva = price2num($remise * $vatrate / 100, 'MT');
2364
				$discount->amount_ttc = $discount->multicurrency_amount_ttc = price2num($discount->amount_ht + $discount->amount_tva, 'MT');
2365
			}
2366
2367
			$discount->tva_tx = price2num($vatrate);
2368
			$discount->vat_src_code = $vat_src_code;
2369
2370
			$discount->description = $desc;
2371
2372
			$result = $discount->create($user);
2373
			if ($result > 0) {
2374
				return $result;
2375
			} else {
2376
				$this->error = $discount->error;
2377
				return -3;
2378
			}
2379
		} else {
2380
			return 0;
2381
		}
2382
	}
2383
2384
	/**
2385
	 * 	Returns amount of included taxes of the current discounts/credits available from the company
2386
	 *
2387
	 *	@param	User	$user			Filter on a user author of discounts
2388
	 * 	@param	string	$filter			Other filter
2389
	 * 	@param	integer	$maxvalue		Filter on max value for discount
2390
	 * 	@param	int		$discount_type	0 => customer discount, 1 => supplier discount
2391
	 *	@return	int					<0 if KO, Credit note amount otherwise
2392
	 */
2393
	public function getAvailableDiscounts($user = '', $filter = '', $maxvalue = 0, $discount_type = 0)
2394
	{
2395
		require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
2396
2397
		$discountstatic = new DiscountAbsolute($this->db);
2398
		$result = $discountstatic->getAvailableDiscounts($this, $user, $filter, $maxvalue, $discount_type);
2399
		if ($result >= 0) {
2400
			return $result;
2401
		} else {
2402
			$this->error = $discountstatic->error;
2403
			return -1;
2404
		}
2405
	}
2406
2407
	/**
2408
	 *  Return array of sales representatives
2409
	 *
2410
	 *  @param	User		$user			Object user (not used)
2411
	 *  @param	int			$mode			0=Array with properties, 1=Array of id.
2412
	 *  @param	string		$sortfield		List of sort fields, separated by comma. Example: 't1.fielda,t2.fieldb'
2413
	 *  @param	string		$sortorder		Sort order, separated by comma. Example: 'ASC,DESC';
2414
	 *  @return array       				Array of sales representatives of third party
2415
	 */
2416
	public function getSalesRepresentatives(User $user, $mode = 0, $sortfield = null, $sortorder = null)
2417
	{
2418
		global $conf;
2419
2420
		$reparray = array();
2421
2422
		$sql = "SELECT DISTINCT u.rowid, u.login, u.lastname, u.firstname, u.office_phone, u.job, u.email, u.statut as status, u.entity, u.photo, u.gender";
2423
		$sql .= ", u.office_fax, u.user_mobile, u.personal_mobile";
2424
		$sql .= " FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc, ".MAIN_DB_PREFIX."user as u";
2425
		if (isModEnabled('multicompany') && !empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) {
2426
			$sql .= ", ".MAIN_DB_PREFIX."usergroup_user as ug";
2427
			$sql .= " WHERE ((ug.fk_user = sc.fk_user";
2428
			$sql .= " AND ug.entity = ".$conf->entity.")";
2429
			$sql .= " OR u.admin = 1)";
2430
		} else {
2431
			$sql .= " WHERE entity in (0, ".$conf->entity.")";
2432
		}
2433
2434
		$sql .= " AND u.rowid = sc.fk_user AND sc.fk_soc = ".((int) $this->id);
2435
		if (empty($sortfield) && empty($sortorder)) {
2436
			$sortfield = 'u.lastname,u.firstname';
2437
			$sortorder = 'ASC,ASC';
2438
		}
2439
		$sql .= $this->db->order($sortfield, $sortorder);
2440
2441
		$resql = $this->db->query($sql);
2442
		if ($resql) {
2443
			$num = $this->db->num_rows($resql);
2444
			$i = 0;
2445
			while ($i < $num) {
2446
				$obj = $this->db->fetch_object($resql);
2447
2448
				if (empty($mode)) {
2449
					$reparray[$i]['id'] = $obj->rowid;
2450
					$reparray[$i]['lastname'] = $obj->lastname;
2451
					$reparray[$i]['firstname'] = $obj->firstname;
2452
					$reparray[$i]['email'] = $obj->email;
2453
					$reparray[$i]['phone'] = $obj->office_phone;
2454
					$reparray[$i]['office_phone'] = $obj->office_phone;
2455
					$reparray[$i]['office_fax'] = $obj->office_fax;
2456
					$reparray[$i]['user_mobile'] = $obj->user_mobile;
2457
					$reparray[$i]['personal_mobile'] = $obj->personal_mobile;
2458
					$reparray[$i]['job'] = $obj->job;
2459
					$reparray[$i]['statut'] = $obj->status; // deprecated
2460
					$reparray[$i]['status'] = $obj->status;
2461
					$reparray[$i]['entity'] = $obj->entity;
2462
					$reparray[$i]['login'] = $obj->login;
2463
					$reparray[$i]['photo'] = $obj->photo;
2464
					$reparray[$i]['gender'] = $obj->gender;
2465
				} else {
2466
					$reparray[] = $obj->rowid;
2467
				}
2468
				$i++;
2469
			}
2470
			return $reparray;
2471
		} else {
2472
			dol_print_error($this->db);
2473
			return -1;
2474
		}
2475
	}
2476
2477
	/**
2478
	 * Set the price level
2479
	 *
2480
	 * @param 	int		$price_level	Level of price
2481
	 * @param 	User	$user			Use making change
2482
	 * @return	int						<0 if KO, >0 if OK
2483
	 */
2484
	public function setPriceLevel($price_level, User $user)
2485
	{
2486
		if ($this->id) {
2487
			$now = dol_now();
2488
2489
			$sql  = "UPDATE ".MAIN_DB_PREFIX."societe";
2490
			$sql .= " SET price_level = ".((int) $price_level);
2491
			$sql .= " WHERE rowid = ".((int) $this->id);
2492
2493
			if (!$this->db->query($sql)) {
2494
				dol_print_error($this->db);
2495
				return -1;
2496
			}
2497
2498
			$sql  = "INSERT INTO ".MAIN_DB_PREFIX."societe_prices";
2499
			$sql .= " (datec, fk_soc, price_level, fk_user_author)";
2500
			$sql .= " VALUES ('".$this->db->idate($now)."', ".((int) $this->id).", ".((int) $price_level).", ".((int) $user->id).")";
2501
2502
			if (!$this->db->query($sql)) {
2503
				dol_print_error($this->db);
2504
				return -1;
2505
			}
2506
			return 1;
2507
		}
2508
		return -1;
2509
	}
2510
2511
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2512
	/**
2513
	 *	Add link to sales representative
2514
	 *
2515
	 *	@param	User	$user		Object user
2516
	 *	@param	int		$commid		Id of user
2517
	 *	@return	int					<=0 if KO, >0 if OK
2518
	 */
2519
	public function add_commercial(User $user, $commid)
2520
	{
2521
		// phpcs:enable
2522
		$error = 0;
2523
2524
		if ($this->id > 0 && $commid > 0) {
2525
			$this->db->begin();
2526
2527
			if (!$error) {
2528
				$sql = "DELETE FROM  ".MAIN_DB_PREFIX."societe_commerciaux";
2529
				$sql .= " WHERE fk_soc = ".((int) $this->id)." AND fk_user = ".((int) $commid);
2530
2531
				$resql = $this->db->query($sql);
2532
				if (!$resql) {
2533
					dol_syslog(get_class($this)."::add_commercial Error ".$this->db->lasterror());
2534
					$error++;
2535
				}
2536
			}
2537
2538
			if (!$error) {
2539
				$sql = "INSERT INTO ".MAIN_DB_PREFIX."societe_commerciaux";
2540
				$sql .= " (fk_soc, fk_user)";
2541
				$sql .= " VALUES (".((int) $this->id).", ".((int) $commid).")";
2542
2543
				$resql = $this->db->query($sql);
2544
				if (!$resql) {
2545
					dol_syslog(get_class($this)."::add_commercial Error ".$this->db->lasterror());
2546
					$error++;
2547
				}
2548
			}
2549
2550
			if (!$error) {
2551
				$this->context = array('commercial_modified' => $commid);
2552
2553
				$result = $this->call_trigger('COMPANY_LINK_SALE_REPRESENTATIVE', $user);
2554
				if ($result < 0) {
2555
					$error++;
2556
				}
2557
			}
2558
2559
			if (!$error) {
2560
				$this->db->commit();
2561
				return 1;
2562
			} else {
2563
				$this->db->rollback();
2564
				return -1;
2565
			}
2566
		}
2567
2568
		return 0;
2569
	}
2570
2571
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2572
	/**
2573
	 *	Add link to sales representative
2574
	 *
2575
	 *	@param	User	$user		Object user
2576
	 *	@param	int		$commid		Id of user
2577
	 *	@return	void
2578
	 */
2579
	public function del_commercial(User $user, $commid)
2580
	{
2581
		// phpcs:enable
2582
		$error = 0;
2583
		$this->context = array('commercial_modified'=>$commid);
2584
2585
		$result = $this->call_trigger('COMPANY_UNLINK_SALE_REPRESENTATIVE', $user);
2586
		if ($result < 0) {
2587
			$error++;
2588
		}
2589
2590
		if ($this->id > 0 && $commid > 0) {
2591
			$sql  = "DELETE FROM  ".MAIN_DB_PREFIX."societe_commerciaux ";
2592
			$sql .= " WHERE fk_soc = ".((int) $this->id)." AND fk_user = ".((int) $commid);
2593
2594
			if (!$this->db->query($sql)) {
2595
				dol_syslog(get_class($this)."::del_commercial Erreur");
2596
			}
2597
		}
2598
	}
2599
2600
	/**
2601
	 * getTooltipContentArray
2602
	 * @param array $params params to construct tooltip data
2603
	 * @since v18
2604
	 * @return array
2605
	 */
2606
	public function getTooltipContentArray($params)
2607
	{
2608
		global $conf, $langs, $user;
2609
2610
		$langs->loadLangs(['companies', 'commercial']);
2611
2612
		$datas = [];
2613
2614
		$option = $params['option'] ?? '';
2615
		$name = $this->name;
2616
2617
		if (!empty($this->name_alias) && empty($noaliasinname)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $noaliasinname seems to never exist and therefore empty should always be true.
Loading history...
2618
			$name .= ' ('.$this->name_alias.')';
2619
		}
2620
		if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2621
			return ['optimize' => $langs->trans("ShowCompany")];
2622
		}
2623
2624
		if (!empty($this->logo) && class_exists('Form')) {
2625
			$photo = '<div class="photointooltip floatright">';
2626
			$photo .= Form::showphoto('societe', $this, 0, 40, 0, 'photoref', 'mini', 0); // Important, we must force height so image will have height tags and if image is inside a tooltip, the tooltip manager can calculate height and position correctly the tooltip.
2627
			$photo .= '</div>';
2628
			$datas['photo'] = $photo;
2629
		} elseif (!empty($this->logo_squarred) && class_exists('Form')) {
2630
			/*$label.= '<div class="photointooltip">';
2631
			$label.= Form::showphoto('societe', $this, 0, 40, 0, 'photowithmargin', 'mini', 0);	// Important, we must force height so image will have height tags and if image is inside a tooltip, the tooltip manager can calculate height and position correctly the tooltip.
2632
			$label.= '</div><div style="clear: both;"></div>';*/
2633
		}
2634
2635
		$datas['divopen'] = '<div class="centpercent">';
2636
2637
		if ($option == 'customer' || $option == 'compta' || $option == 'category') {
2638
			$datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Customer").'</u>';
2639
		} elseif ($option == 'prospect' && empty($conf->global->SOCIETE_DISABLE_PROSPECTS)) {
2640
			$datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Prospect").'</u>';
2641
		} elseif ($option == 'supplier' || $option == 'category_supplier') {
2642
			$datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Supplier").'</u>';
2643
		} elseif ($option == 'agenda') {
2644
			$datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("ThirdParty").'</u>';
2645
		} elseif ($option == 'project') {
2646
			$datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("ThirdParty").'</u>';
2647
		} elseif ($option == 'margin') {
2648
			$datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("ThirdParty").'</u>';
2649
		} elseif ($option == 'contact') {
2650
			$datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("ThirdParty").'</u>';
2651
		} elseif ($option == 'ban') {
2652
			$datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("ThirdParty").'</u>';
2653
		}
2654
2655
		// By default
2656
		if (empty($datas['picto'])) {
2657
			$datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("ThirdParty").'</u>';
2658
		}
2659
		if (isset($this->status)) {
2660
			$datas['status'] = ' '.$this->getLibStatut(5);
2661
		}
2662
		if (isset($this->client) && isset($this->fournisseur)) {
2663
			$datas['type'] = ' &nbsp; ' . $this->getTypeUrl(1);
2664
		}
2665
		$datas['name'] = '<br><b>'.$langs->trans('Name').':</b> '.dol_escape_htmltag($this->name);
2666
		if (!empty($this->name_alias)) {
2667
			$datas['namealias'] = ' ('.dol_escape_htmltag($this->name_alias).')';
2668
		}
2669
		if (!empty($this->email)) {
2670
			$datas['email'] = '<br>'.img_picto('', 'email', 'class="pictofixedwidth"').$this->email;
2671
		}
2672
		if (!empty($this->url)) {
2673
			$datas['url'] = '<br>'.img_picto('', 'globe', 'class="pictofixedwidth"').$this->url;
2674
		}
2675
		if (!empty($this->phone) || !empty($this->fax)) {
2676
			$phonelist = array();
2677
			if ($this->phone) {
2678
				$phonelist[] = dol_print_phone($this->phone, $this->country_code, $this->id, 0, '', '&nbsp', 'phone');
2679
			}
2680
			if ($this->fax) {
2681
				$phonelist[] = dol_print_phone($this->fax, $this->country_code, $this->id, 0, '', '&nbsp', 'fax');
2682
			}
2683
			$datas['phonelist'] = '<br>'.implode('&nbsp;', $phonelist);
2684
		}
2685
2686
		if (!empty($this->address)) {
2687
			$datas['address'] = '<br><b>'.$langs->trans("Address").':</b> '.dol_format_address($this, 1, ' ', $langs); // Address + country
2688
		} elseif (!empty($this->country_code)) {
2689
			$datas['address'] = '<br><b>'.$langs->trans('Country').':</b> '.$this->country_code;
2690
		}
2691
		if (!empty($this->tva_intra) || (!empty($conf->global->SOCIETE_SHOW_FIELD_IN_TOOLTIP) && strpos($conf->global->SOCIETE_SHOW_FIELD_IN_TOOLTIP, 'vatnumber') !== false)) {
2692
			$datas['vatintra'] = '<br><b>'.$langs->trans('VATIntra').':</b> '.dol_escape_htmltag($this->tva_intra);
2693
		}
2694
2695
		if (!empty($conf->global->SOCIETE_SHOW_FIELD_IN_TOOLTIP)) {
2696
			if (strpos($conf->global->SOCIETE_SHOW_FIELD_IN_TOOLTIP, 'profid1') !== false && $langs->trans('ProfId1'.$this->country_code) != '-') {
2697
				$datas['profid1'] = '<br><b>'.$langs->trans('ProfId1'.$this->country_code).':</b> '.$this->idprof1;
2698
			}
2699
			if (strpos($conf->global->SOCIETE_SHOW_FIELD_IN_TOOLTIP, 'profid2') !== false && $langs->trans('ProfId2'.$this->country_code) != '-') {
2700
				$datas['profid2'] = '<br><b>'.$langs->trans('ProfId2'.$this->country_code).':</b> '.$this->idprof2;
2701
			}
2702
			if (strpos($conf->global->SOCIETE_SHOW_FIELD_IN_TOOLTIP, 'profid3') !== false && $langs->trans('ProfId3'.$this->country_code) != '-') {
2703
				$datas['profid3'] = '<br><b>'.$langs->trans('ProfId3'.$this->country_code).':</b> '.$this->idprof3;
2704
			}
2705
			if (strpos($conf->global->SOCIETE_SHOW_FIELD_IN_TOOLTIP, 'profid4') !== false && $langs->trans('ProfId4'.$this->country_code) != '-') {
2706
				$datas['profid4'] = '<br><b>'.$langs->trans('ProfId4'.$this->country_code).':</b> '.$this->idprof4;
2707
			}
2708
			if (strpos($conf->global->SOCIETE_SHOW_FIELD_IN_TOOLTIP, 'profid5') !== false && $langs->trans('ProfId5'.$this->country_code) != '-') {
2709
				$datas['profid5'] = '<br><b>'.$langs->trans('ProfId5'.$this->country_code).':</b> '.$this->idprof5;
2710
			}
2711
			if (strpos($conf->global->SOCIETE_SHOW_FIELD_IN_TOOLTIP, 'profid6') !== false && $langs->trans('ProfId6'.$this->country_code) != '-') {
2712
				$datas['profid6'] = '<br><b>'.$langs->trans('ProfId6'.$this->country_code).':</b> '.$this->idprof6;
2713
			}
2714
		}
2715
		if (!empty($this->code_client) && ($this->client == 1 || $this->client == 3)) {
2716
			$datas['customercode'] = '<br><b>'.$langs->trans('CustomerCode').':</b> '.$this->code_client;
2717
		}
2718
		if (!empty($this->code_fournisseur) && $this->fournisseur) {
2719
			$datas['suppliercode'] = '<br><b>'.$langs->trans('SupplierCode').':</b> '.$this->code_fournisseur;
2720
		}
2721
		if (isModEnabled('accounting') && ($this->client == 1 || $this->client == 3)) {
2722
			$datas['accountancycustomercode'] = '<br><b>'.$langs->trans('CustomerAccountancyCode').':</b> '.($this->code_compta ? $this->code_compta : $this->code_compta_client);
2723
		}
2724
		if (isModEnabled('accounting') && $this->fournisseur) {
2725
			$datas['accountancysuppliercode'] = '<br><b>'.$langs->trans('SupplierAccountancyCode').':</b> '.$this->code_compta_fournisseur;
2726
		}
2727
2728
		$datas['divclose'] = '</div>';
2729
2730
		return $datas;
2731
	}
2732
2733
	/**
2734
	 *    	Return a link on thirdparty (with picto)
2735
	 *
2736
	 *		@param	int		$withpicto		          Add picto into link (0=No picto, 1=Include picto with link, 2=Picto only)
2737
	 *		@param	string	$option			          Target of link ('', 'customer', 'prospect', 'supplier', 'project')
2738
	 *		@param	int		$maxlen			          Max length of name
2739
	 *      @param	int  	$notooltip		          1=Disable tooltip
2740
	 *      @param  int     $save_lastsearch_value    -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
2741
	 *      @param	int		$noaliasinname			  1=Do not add alias into the link ref
2742
	 *      @param	string	$target			  		  add attribute target
2743
	 *		@return	string					          String with URL
2744
	 */
2745
	public function getNomUrl($withpicto = 0, $option = '', $maxlen = 0, $notooltip = 0, $save_lastsearch_value = -1, $noaliasinname = 0, $target = '')
2746
	{
2747
		global $conf, $langs, $hookmanager;
2748
2749
		if (!empty($conf->dol_no_mouse_hover)) {
2750
			$notooltip = 1; // Force disable tooltips
2751
		}
2752
2753
		$name = $this->name ? $this->name : $this->nom;
2754
2755
		if (!empty($conf->global->SOCIETE_ON_SEARCH_AND_LIST_GO_ON_CUSTOMER_OR_SUPPLIER_CARD)) {
2756
			if (empty($option) && $this->client > 0) {
2757
				$option = 'customer';
2758
			}
2759
			if (empty($option) && $this->fournisseur > 0) {
2760
				$option = 'supplier';
2761
			}
2762
		}
2763
2764
		if (!empty($conf->global->SOCIETE_ADD_REF_IN_LIST) && (!empty($withpicto))) {
2765
			$code = '';
2766
			if (($this->client) && (!empty($this->code_client)) && ($conf->global->SOCIETE_ADD_REF_IN_LIST == 1 || $conf->global->SOCIETE_ADD_REF_IN_LIST == 2)) {
2767
				$code = $this->code_client.' - ';
2768
			}
2769
2770
			if (($this->fournisseur) && (!empty($this->code_fournisseur)) && ($conf->global->SOCIETE_ADD_REF_IN_LIST == 1 || $conf->global->SOCIETE_ADD_REF_IN_LIST == 3)) {
2771
				$code .= $this->code_fournisseur.' - ';
2772
			}
2773
2774
			if ($code) {
2775
				if ($conf->global->SOCIETE_ADD_REF_IN_LIST == 1) {
2776
					$name = $code.' '.$name;
2777
				} else {
2778
					$name = $code;
2779
				}
2780
			}
2781
		}
2782
2783
		if (!empty($this->name_alias) && empty($noaliasinname)) {
2784
			$name .= ' ('.$this->name_alias.')';
2785
		}
2786
2787
		$result = '';
2788
		$params = [
2789
			'id' => $this->id,
2790
			'objecttype' => $this->element,
2791
			'option' => $option,
2792
		];
2793
		$classfortooltip = 'classfortooltip';
2794
		$dataparams = '';
2795
		if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
2796
			$classfortooltip = 'classforajaxtooltip';
2797
			$dataparams = ' data-params='.json_encode($params);
2798
			// $label = $langs->trans('Loading');
2799
		}
2800
		$label = implode($this->getTooltipContentArray($params));
2801
		$linkstart = '';
2802
		$linkend = '';
2803
2804
		if ($option == 'customer' || $option == 'compta' || $option == 'category') {
2805
			$linkstart = '<a href="'.DOL_URL_ROOT.'/comm/card.php?socid='.$this->id;
2806
		} elseif ($option == 'prospect' && empty($conf->global->SOCIETE_DISABLE_PROSPECTS)) {
2807
			$linkstart = '<a href="'.DOL_URL_ROOT.'/comm/card.php?socid='.$this->id;
2808
		} elseif ($option == 'supplier' || $option == 'category_supplier') {
2809
			$linkstart = '<a href="'.DOL_URL_ROOT.'/fourn/card.php?socid='.$this->id;
2810
		} elseif ($option == 'agenda') {
2811
			$linkstart = '<a href="'.DOL_URL_ROOT.'/societe/agenda.php?socid='.$this->id;
2812
		} elseif ($option == 'project') {
2813
			$linkstart = '<a href="'.DOL_URL_ROOT.'/societe/project.php?socid='.$this->id;
2814
		} elseif ($option == 'margin') {
2815
			$linkstart = '<a href="'.DOL_URL_ROOT.'/margin/tabs/thirdpartyMargins.php?socid='.$this->id.'&type=1';
2816
		} elseif ($option == 'contact') {
2817
			$linkstart = '<a href="'.DOL_URL_ROOT.'/societe/contact.php?socid='.$this->id;
2818
		} elseif ($option == 'ban') {
2819
			$linkstart = '<a href="'.DOL_URL_ROOT.'/societe/paymentmodes.php?socid='.$this->id;
2820
		}
2821
2822
		// By default
2823
		if (empty($linkstart)) {
2824
			$linkstart = '<a href="'.DOL_URL_ROOT.'/societe/card.php?socid='.$this->id;
2825
		}
2826
2827
		// Add type of canvas
2828
		$linkstart .= (!empty($this->canvas) ? '&canvas='.$this->canvas : '');
2829
		// Add param to save lastsearch_values or not
2830
		$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2831
		if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
2832
			$add_save_lastsearch_values = 1;
2833
		}
2834
		if ($add_save_lastsearch_values) {
2835
			$linkstart .= '&save_lastsearch_values=1';
2836
		}
2837
		$linkstart .= '"';
2838
2839
		$linkclose = '';
2840
		if (empty($notooltip)) {
2841
			if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2842
				$label = $langs->trans("ShowCompany");
2843
				$linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
2844
			}
2845
			$linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
2846
			$linkclose .= $dataparams.' class="'.$classfortooltip.' refurl valignmiddle"';
2847
			$target_value = array('_self', '_blank', '_parent', '_top');
2848
			if (in_array($target, $target_value)) {
2849
				$linkclose .= ' target="'.dol_escape_htmltag($target).'"';
2850
			}
2851
		} else {
2852
			$linkclose .= ' class="valignmiddle"';
2853
		}
2854
		$linkstart .= $linkclose.'>';
2855
		$linkend = '</a>';
2856
2857
		global $user;
2858
		if (empty($user->rights->societe->client->voir) && $user->socid > 0 && $this->id != $user->socid) {
2859
			$linkstart = '';
2860
			$linkend = '';
2861
		}
2862
2863
		$result .= $linkstart;
2864
		if ($withpicto) {
2865
			$result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : $dataparams.' class="'.(($withpicto != 2) ? 'paddingright ' : '').$classfortooltip.'"'), 0, 0, $notooltip ? 0 : 1);
2866
		}
2867
		if ($withpicto != 2) {
2868
			$result .= dol_escape_htmltag($maxlen ? dol_trunc($name, $maxlen) : $name);
2869
		}
2870
		$result .= $linkend;
2871
2872
		global $action;
2873
		$hookmanager->initHooks(array('thirdpartydao'));
2874
		$parameters = array(
2875
			'id'=>$this->id,
2876
			'getnomurl' => &$result,
2877
			'withpicto '=> $withpicto,
2878
			'option'=> $option,
2879
			'maxlen'=> $maxlen,
2880
			'notooltip'=> $notooltip,
2881
			'save_lastsearch_value'=> $save_lastsearch_value
2882
		);
2883
		$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
2884
		if ($reshook > 0) {
2885
			$result = $hookmanager->resPrint;
2886
		} else {
2887
			$result .= $hookmanager->resPrint;
2888
		}
2889
2890
		return $result;
2891
	}
2892
2893
	/**
2894
	 *    	Return link(s) on type of thirdparty (with picto)
2895
	 *
2896
	 *		@param	int		$withpicto		        Add picto into link (0=No picto, 1=Include picto with link, 2=Picto only)
2897
	 *		@param	string	$option					''=All
2898
	 *      @param	int  	$notooltip		        1=Disable tooltip
2899
	 *      @param	string	$tag					Tag 'a' or 'span'
2900
	 *		@return	string					        String with URL
2901
	 */
2902
	public function getTypeUrl($withpicto = 0, $option = '', $notooltip = 0, $tag = 'a')
2903
	{
2904
		global $conf, $langs;
2905
2906
		$s = '';
2907
		if (empty($option) || preg_match('/prospect/', $option)) {
2908
			if (($this->client == 2 || $this->client == 3) && empty($conf->global->SOCIETE_DISABLE_PROSPECTS)) {
2909
				$s .= '<'.$tag.' class="customer-back opacitymedium" title="'.$langs->trans("Prospect").'" href="'.DOL_URL_ROOT.'/comm/card.php?socid='.$this->id.'">'.dol_substr($langs->trans("Prospect"), 0, 1).'</'.$tag.'>';
2910
			}
2911
		}
2912
		if (empty($option) || preg_match('/customer/', $option)) {
2913
			if (($this->client == 1 || $this->client == 3) && empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) {
2914
				$s .= '<'.$tag.' class="customer-back" title="'.$langs->trans("Customer").'" href="'.DOL_URL_ROOT.'/comm/card.php?socid='.$this->id.'">'.dol_substr($langs->trans("Customer"), 0, 1).'</'.$tag.'>';
2915
			}
2916
		}
2917
		if (empty($option) || preg_match('/supplier/', $option)) {
2918
			if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && $this->fournisseur) {
2919
				$s .= '<'.$tag.' class="vendor-back" title="'.$langs->trans("Supplier").'" href="'.DOL_URL_ROOT.'/fourn/card.php?socid='.$this->id.'">'.dol_substr($langs->trans("Supplier"), 0, 1).'</'.$tag.'>';
2920
			}
2921
		}
2922
		return $s;
2923
	}
2924
2925
2926
	/**
2927
	 *    Return label of status (activity, closed)
2928
	 *
2929
	 *    @param  	int		$mode       0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
2930
	 *    @return   string     	   		Label of status
2931
	 */
2932
	public function getLibStatut($mode = 0)
2933
	{
2934
		return $this->LibStatut($this->status, $mode);
2935
	}
2936
2937
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2938
	/**
2939
	 *  Return the label of a given status
2940
	 *
2941
	 *  @param	int		$status         Status id
2942
	 *  @param	int		$mode           0=Long label, 1=Short label, 2=Picto + Short label, 3=Picto, 4=Picto + Long label, 5=Short label + Picto, 6=Long label + Picto
2943
	 *  @return	string          		Status label
2944
	 */
2945
	public function LibStatut($status, $mode = 0)
2946
	{
2947
		// phpcs:enable
2948
		global $langs;
2949
		$langs->load('companies');
2950
2951
		$statusType = 'status4';
2952
		if ($status == 0) {
2953
			$statusType = 'status6';
2954
		}
2955
2956
		if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
2957
			$this->labelStatus[0] = $langs->transnoentitiesnoconv("ActivityCeased");
2958
			$this->labelStatus[1] = $langs->transnoentitiesnoconv("InActivity");
2959
			$this->labelStatusShort[0] = $langs->transnoentitiesnoconv("ActivityCeased");
2960
			$this->labelStatusShort[1] = $langs->transnoentitiesnoconv("InActivity");
2961
		}
2962
2963
		return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
2964
	}
2965
2966
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2967
	/**
2968
	 *    Return list of contacts emails existing for third party
2969
	 *
2970
	 *	  @param	  int		$addthirdparty		1=Add also a record for thirdparty email
2971
	 *    @return     array       					Array of contacts emails
2972
	 */
2973
	public function thirdparty_and_contact_email_array($addthirdparty = 0)
2974
	{
2975
		// phpcs:enable
2976
		global $langs;
2977
2978
		$contact_emails = $this->contact_property_array('email', 1);
2979
		if ($this->email && $addthirdparty) {
2980
			if (empty($this->name)) {
2981
				$this->name = $this->nom;
2982
			}
2983
			$contact_emails['thirdparty'] = $langs->transnoentitiesnoconv("ThirdParty").': '.dol_trunc($this->name, 16)." <".$this->email.">";
2984
		}
2985
		//var_dump($contact_emails)
2986
		return $contact_emails;
2987
	}
2988
2989
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2990
	/**
2991
	 *    Return list of contacts mobile phone existing for third party
2992
	 *
2993
	 *    @return     array       Array of contacts emails
2994
	 */
2995
	public function thirdparty_and_contact_phone_array()
2996
	{
2997
		// phpcs:enable
2998
		global $langs;
2999
3000
		$contact_phone = $this->contact_property_array('mobile');
3001
3002
		if (!empty($this->phone)) {	// If a phone of thirdparty is defined, we add it ot mobile of contacts
3003
			if (empty($this->name)) {
3004
				$this->name = $this->nom;
3005
			}
3006
			// TODO: Tester si tel non deja present dans tableau contact
3007
			$contact_phone['thirdparty'] = $langs->transnoentitiesnoconv("ThirdParty").': '.dol_trunc($this->name, 16)." <".$this->phone.">";
3008
		}
3009
		return $contact_phone;
3010
	}
3011
3012
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3013
	/**
3014
	 *  Return list of contacts emails or mobile existing for third party
3015
	 *
3016
	 *  @param	string	$mode       		'email' or 'mobile'
3017
	 * 	@param	int		$hidedisabled		1=Hide contact if disabled
3018
	 *  @return array       				Array of contacts emails or mobile. Example: array(id=>'Name <email>')
3019
	 */
3020
	public function contact_property_array($mode = 'email', $hidedisabled = 0)
3021
	{
3022
		// phpcs:enable
3023
		global $langs;
3024
3025
		$contact_property = array();
3026
3027
3028
		$sql = "SELECT rowid, email, statut as status, phone_mobile, lastname, poste, firstname";
3029
		$sql .= " FROM ".MAIN_DB_PREFIX."socpeople";
3030
		$sql .= " WHERE fk_soc = ".((int) $this->id);
3031
		$sql .= " ORDER BY lastname, firstname";
3032
3033
		$resql = $this->db->query($sql);
3034
		if ($resql) {
3035
			$nump = $this->db->num_rows($resql);
3036
			if ($nump) {
3037
				$sepa = "("; $sepb = ")";
3038
				if ($mode == 'email') {
3039
					//$sepa="&lt;"; $sepb="&gt;";
3040
					$sepa = "<"; $sepb = ">";
3041
				}
3042
				$i = 0;
3043
				while ($i < $nump) {
3044
					$obj = $this->db->fetch_object($resql);
3045
					if ($mode == 'email') {
3046
						$property = $obj->email;
3047
					} elseif ($mode == 'mobile') {
3048
						$property = $obj->phone_mobile;
3049
					} else {
3050
						$property = $obj->$mode;
3051
					}
3052
3053
					// Show all contact. If hidedisabled is 1, showonly contacts with status = 1
3054
					if ($obj->status == 1 || empty($hidedisabled)) {
3055
						if (empty($property)) {
3056
							if ($mode == 'email') {
3057
								$property = $langs->transnoentitiesnoconv("NoEMail");
3058
							} elseif ($mode == 'mobile') {
3059
								$property = $langs->transnoentitiesnoconv("NoMobilePhone");
3060
							}
3061
						}
3062
3063
						if (!empty($obj->poste)) {
3064
							$contact_property[$obj->rowid] = trim(dolGetFirstLastname($obj->firstname, $obj->lastname)).($obj->poste ? " - ".$obj->poste : "").(($mode != 'poste' && $property) ? " ".$sepa.$property.$sepb : '');
3065
						} else {
3066
							$contact_property[$obj->rowid] = trim(dolGetFirstLastname($obj->firstname, $obj->lastname)).(($mode != 'poste' && $property) ? " ".$sepa.$property.$sepb : '');
3067
						}
3068
					}
3069
					$i++;
3070
				}
3071
			}
3072
		} else {
3073
			dol_print_error($this->db);
3074
		}
3075
		return $contact_property;
3076
	}
3077
3078
3079
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3080
	/**
3081
	 *    Returns the contact list of this company
3082
	 *
3083
	 *    @return     array      array of contacts
3084
	 */
3085
	public function contact_array()
3086
	{
3087
		// phpcs:enable
3088
		$contacts = array();
3089
3090
		$sql = "SELECT rowid, lastname, firstname FROM ".MAIN_DB_PREFIX."socpeople WHERE fk_soc = ".((int) $this->id);
3091
		$resql = $this->db->query($sql);
3092
		if ($resql) {
3093
			$nump = $this->db->num_rows($resql);
3094
			if ($nump) {
3095
				$i = 0;
3096
				while ($i < $nump) {
3097
					$obj = $this->db->fetch_object($resql);
3098
					$contacts[$obj->rowid] = dolGetFirstLastname($obj->firstname, $obj->lastname);
3099
					$i++;
3100
				}
3101
			}
3102
		} else {
3103
			dol_print_error($this->db);
3104
		}
3105
		return $contacts;
3106
	}
3107
3108
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3109
	/**
3110
	 *    Returns the contact list of this company
3111
	 *
3112
	 *    @return    array    $contacts    array of contacts
3113
	 */
3114
	public function contact_array_objects()
3115
	{
3116
		// phpcs:enable
3117
		require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
3118
		$contacts = array();
3119
3120
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."socpeople WHERE fk_soc = ".((int) $this->id);
3121
		$resql = $this->db->query($sql);
3122
		if ($resql) {
3123
			$nump = $this->db->num_rows($resql);
3124
			if ($nump) {
3125
				$i = 0;
3126
				while ($i < $nump) {
3127
					$obj = $this->db->fetch_object($resql);
3128
					$contact = new Contact($this->db);
3129
					$contact->fetch($obj->rowid);
3130
					$contacts[] = $contact;
3131
					$i++;
3132
				}
3133
			}
3134
		} else {
3135
			dol_print_error($this->db);
3136
		}
3137
		return $contacts;
3138
	}
3139
3140
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3141
	/**
3142
	 *  Return property of contact from its id
3143
	 *
3144
	 *  @param	int		$rowid      id of contact
3145
	 *  @param  string	$mode       'email' or 'mobile'
3146
	 *  @return string  			Email of contact with format: "Full name <email>"
3147
	 */
3148
	public function contact_get_property($rowid, $mode)
3149
	{
3150
		// phpcs:enable
3151
		$contact_property = '';
3152
3153
		if (empty($rowid)) {
3154
			return '';
3155
		}
3156
3157
		$sql = "SELECT rowid, email, phone_mobile, lastname, firstname";
3158
		$sql .= " FROM ".MAIN_DB_PREFIX."socpeople";
3159
		$sql .= " WHERE rowid = ".((int) $rowid);
3160
3161
		$resql = $this->db->query($sql);
3162
		if ($resql) {
3163
			$nump = $this->db->num_rows($resql);
3164
3165
			if ($nump) {
3166
				$obj = $this->db->fetch_object($resql);
3167
3168
				if ($mode == 'email') {
3169
					$contact_property = dol_string_nospecial(dolGetFirstLastname($obj->firstname, $obj->lastname), ' ', array(","))." <".$obj->email.">";
3170
				} elseif ($mode == 'mobile') {
3171
					$contact_property = $obj->phone_mobile;
3172
				}
3173
			}
3174
			return $contact_property;
3175
		} else {
3176
			dol_print_error($this->db);
3177
		}
3178
3179
		return '';
3180
	}
3181
3182
3183
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3184
	/**
3185
	 *  Return bank number property of thirdparty (label or rum)
3186
	 *
3187
	 *	@param	string	$mode	'label' or 'rum' or 'format'
3188
	 *  @return	string			Bank label or RUM or '' if no bank account found
3189
	 */
3190
	public function display_rib($mode = 'label')
3191
	{
3192
		// phpcs:enable
3193
		require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
3194
3195
		$bac = new CompanyBankAccount($this->db);
3196
		$bac->fetch(0, $this->id);
3197
3198
		if ($bac->id > 0) {		// If a bank account has been found for company $this->id
3199
			if ($mode == 'label') {
3200
				return $bac->getRibLabel(true);
3201
			} elseif ($mode == 'rum') {
3202
				if (empty($bac->rum)) {
3203
					require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php';
3204
					$prelevement = new BonPrelevement($this->db);
3205
					$bac->fetch_thirdparty();
3206
					$bac->rum = $prelevement->buildRumNumber($bac->thirdparty->code_client, $bac->datec, $bac->id);
3207
				}
3208
				return $bac->rum;
3209
			} elseif ($mode == 'format') {
3210
				return $bac->frstrecur;
3211
			} else {
3212
				return 'BadParameterToFunctionDisplayRib';
3213
			}
3214
		} else {
3215
			return '';
3216
		}
3217
	}
3218
3219
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3220
	/**
3221
	 * Return Array of RIB
3222
	 *
3223
	 * @return     array|int        0 if KO, Array of CompanyBanckAccount if OK
3224
	 */
3225
	public function get_all_rib()
3226
	{
3227
		// phpcs:enable
3228
		require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
3229
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."societe_rib WHERE type='ban' AND fk_soc = ".((int) $this->id);
3230
		$result = $this->db->query($sql);
3231
		if (!$result) {
3232
			$this->error++;
3233
			$this->errors[] = $this->db->lasterror;
3234
			return 0;
3235
		} else {
3236
			$num_rows = $this->db->num_rows($result);
3237
			$rib_array = array();
3238
			if ($num_rows) {
3239
				while ($obj = $this->db->fetch_object($result)) {
3240
					$rib = new CompanyBankAccount($this->db);
3241
					$rib->fetch($obj->rowid);
3242
					$rib_array[] = $rib;
3243
				}
3244
			}
3245
			return $rib_array;
3246
		}
3247
	}
3248
3249
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3250
	/**
3251
	 *  Assigns a customer code from the code control module.
3252
	 *  Return value is stored into this->code_client
3253
	 *
3254
	 *	@param	Societe		$objsoc		Object thirdparty
3255
	 *	@param	int			$type		Should be 0 to say customer
3256
	 *  @return void
3257
	 */
3258
	public function get_codeclient($objsoc = 0, $type = 0)
3259
	{
3260
		// phpcs:enable
3261
		global $conf;
3262
		if (!empty($conf->global->SOCIETE_CODECLIENT_ADDON)) {
3263
			$module = $conf->global->SOCIETE_CODECLIENT_ADDON;
3264
3265
			$dirsociete = array_merge(array('/core/modules/societe/'), $conf->modules_parts['societe']);
3266
			foreach ($dirsociete as $dirroot) {
3267
				$res = dol_include_once($dirroot.$module.'.php');
3268
				if ($res) {
3269
					break;
3270
				}
3271
			}
3272
			$mod = new $module();
3273
3274
			$this->code_client = $mod->getNextValue($objsoc, $type);
3275
			$this->prefixCustomerIsRequired = $mod->prefixIsRequired;
3276
3277
			dol_syslog(get_class($this)."::get_codeclient code_client=".$this->code_client." module=".$module);
3278
		}
3279
	}
3280
3281
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3282
	/**
3283
	 *  Assigns a vendor code from the code control module.
3284
	 *  Return value is stored into this->code_fournisseur
3285
	 *
3286
	 *	@param	Societe		$objsoc		Object thirdparty
3287
	 *	@param	int			$type		Should be 1 to say supplier
3288
	 *  @return void
3289
	 */
3290
	public function get_codefournisseur($objsoc = 0, $type = 1)
3291
	{
3292
		// phpcs:enable
3293
		global $conf;
3294
		if (!empty($conf->global->SOCIETE_CODECLIENT_ADDON)) {
3295
			$module = $conf->global->SOCIETE_CODECLIENT_ADDON;
3296
3297
			$dirsociete = array_merge(array('/core/modules/societe/'), $conf->modules_parts['societe']);
3298
			foreach ($dirsociete as $dirroot) {
3299
				$res = dol_include_once($dirroot.$module.'.php');
3300
				if ($res) {
3301
					break;
3302
				}
3303
			}
3304
			$mod = new $module();
3305
3306
			$this->code_fournisseur = $mod->getNextValue($objsoc, $type);
3307
3308
			dol_syslog(get_class($this)."::get_codefournisseur code_fournisseur=".$this->code_fournisseur." module=".$module);
3309
		}
3310
	}
3311
3312
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3313
	/**
3314
	 *    Check if a client code is editable based on the parameters of the
3315
	 *    code control module.
3316
	 *
3317
	 *    @return     int		0=No, 1=Yes
3318
	 */
3319
	public function codeclient_modifiable()
3320
	{
3321
		// phpcs:enable
3322
		global $conf;
3323
		if (!empty($conf->global->SOCIETE_CODECLIENT_ADDON)) {
3324
			$module = $conf->global->SOCIETE_CODECLIENT_ADDON;
3325
3326
			$dirsociete = array_merge(array('/core/modules/societe/'), $conf->modules_parts['societe']);
3327
			foreach ($dirsociete as $dirroot) {
3328
				$res = dol_include_once($dirroot.$module.'.php');
3329
				if ($res) {
3330
					break;
3331
				}
3332
			}
3333
3334
			$mod = new $module();
3335
3336
			dol_syslog(get_class($this)."::codeclient_modifiable code_client=".$this->code_client." module=".$module);
3337
			if ($mod->code_modifiable_null && !$this->code_client) {
3338
				return 1;
3339
			}
3340
			if ($mod->code_modifiable_invalide && $this->check_codeclient() < 0) {
3341
				return 1;
3342
			}
3343
			if ($mod->code_modifiable) {
3344
				return 1; // A mettre en dernier
3345
			}
3346
			return 0;
3347
		} else {
3348
			return 0;
3349
		}
3350
	}
3351
3352
3353
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3354
	/**
3355
	 *    Check if a vendor code is editable in the code control module configuration
3356
	 *
3357
	 *    @return     int		0=No, 1=Yes
3358
	 */
3359
	public function codefournisseur_modifiable()
3360
	{
3361
		// phpcs:enable
3362
		global $conf;
3363
		if (!empty($conf->global->SOCIETE_CODECLIENT_ADDON)) {
3364
			$module = $conf->global->SOCIETE_CODECLIENT_ADDON;
3365
3366
			$dirsociete = array_merge(array('/core/modules/societe/'), $conf->modules_parts['societe']);
3367
			foreach ($dirsociete as $dirroot) {
3368
				$res = dol_include_once($dirroot.$module.'.php');
3369
				if ($res) {
3370
					break;
3371
				}
3372
			}
3373
3374
			$mod = new $module();
3375
3376
			dol_syslog(get_class($this)."::codefournisseur_modifiable code_founisseur=".$this->code_fournisseur." module=".$module);
3377
			if ($mod->code_modifiable_null && !$this->code_fournisseur) {
3378
				return 1;
3379
			}
3380
			if ($mod->code_modifiable_invalide && $this->check_codefournisseur() < 0) {
3381
				return 1;
3382
			}
3383
			if ($mod->code_modifiable) {
3384
				return 1; // A mettre en dernier
3385
			}
3386
			return 0;
3387
		} else {
3388
			return 0;
3389
		}
3390
	}
3391
3392
3393
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3394
	/**
3395
	 *  Check customer code
3396
	 *
3397
	 *  @return     int				0 if OK
3398
	 * 								-1 ErrorBadCustomerCodeSyntax
3399
	 * 								-2 ErrorCustomerCodeRequired
3400
	 * 								-3 ErrorCustomerCodeAlreadyUsed
3401
	 * 								-4 ErrorPrefixRequired
3402
	 * 								-5 NotConfigured - Setup empty so any value may be ok or not
3403
	 * 								-6 Other (see this->error)
3404
	 */
3405
	public function check_codeclient()
3406
	{
3407
		// phpcs:enable
3408
		global $conf;
3409
		if (!empty($conf->global->SOCIETE_CODECLIENT_ADDON)) {
3410
			$module = $conf->global->SOCIETE_CODECLIENT_ADDON;
3411
3412
			$dirsociete = array_merge(array('/core/modules/societe/'), $conf->modules_parts['societe']);
3413
			foreach ($dirsociete as $dirroot) {
3414
				$res = dol_include_once($dirroot.$module.'.php');
3415
				if ($res) {
3416
					break;
3417
				}
3418
			}
3419
3420
			$mod = new $module();
3421
3422
			dol_syslog(get_class($this)."::check_codeclient code_client=".$this->code_client." module=".$module);
3423
			$result = $mod->verif($this->db, $this->code_client, $this, 0);
3424
			if ($result) {	// If error
3425
				$this->error = $mod->error;
3426
				$this->errors = $mod->errors;
3427
			}
3428
			return $result;
3429
		} else {
3430
			return 0;
3431
		}
3432
	}
3433
3434
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3435
	/**
3436
	 *    Check supplier code
3437
	 *
3438
	 *    @return     int		0 if OK
3439
	 * 							-1 ErrorBadCustomerCodeSyntax
3440
	 * 							-2 ErrorCustomerCodeRequired
3441
	 * 							-3 ErrorCustomerCodeAlreadyUsed
3442
	 * 							-4 ErrorPrefixRequired
3443
	 * 							-5 NotConfigured - Setup empty so any value may be ok or not
3444
	 * 							-6 Other (see this->error)
3445
	 */
3446
	public function check_codefournisseur()
3447
	{
3448
		// phpcs:enable
3449
		global $conf;
3450
		if (!empty($conf->global->SOCIETE_CODECLIENT_ADDON)) {
3451
			$module = $conf->global->SOCIETE_CODECLIENT_ADDON;
3452
3453
			$dirsociete = array_merge(array('/core/modules/societe/'), $conf->modules_parts['societe']);
3454
			foreach ($dirsociete as $dirroot) {
3455
				$res = dol_include_once($dirroot.$module.'.php');
3456
				if ($res) {
3457
					break;
3458
				}
3459
			}
3460
3461
			$mod = new $module();
3462
3463
			dol_syslog(get_class($this)."::check_codefournisseur code_fournisseur=".$this->code_fournisseur." module=".$module);
3464
			$result = $mod->verif($this->db, $this->code_fournisseur, $this, 1);
3465
			if ($result) {	// If error
3466
				$this->error = $mod->error;
3467
				$this->errors = $mod->errors;
3468
			}
3469
			return $result;
3470
		} else {
3471
			return 0;
3472
		}
3473
	}
3474
3475
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3476
	/**
3477
	 *    	Assigns a accounting code from the accounting code module.
3478
	 *      Computed value is stored into this->code_compta or this->code_compta_fournisseur according to $type.
3479
	 *      May be identical to the one entered or generated automatically. Currently, only the automatic generation is implemented.
3480
	 *
3481
	 *    	@param	string	$type		Type of thirdparty ('customer' or 'supplier')
3482
	 *		@return	int					0 if OK, <0 if $type is not valid
3483
	 */
3484
	public function get_codecompta($type)
3485
	{
3486
		// phpcs:enable
3487
		global $conf;
3488
3489
		if (!empty($conf->global->SOCIETE_CODECOMPTA_ADDON)) {
3490
			$res = false;
3491
			$dirsociete = array_merge(array('/core/modules/societe/'), $conf->modules_parts['societe']);
3492
			foreach ($dirsociete as $dirroot) {
3493
				$res = dol_include_once($dirroot.$conf->global->SOCIETE_CODECOMPTA_ADDON.'.php');
3494
				if ($res) {
3495
					break;
3496
				}
3497
			}
3498
3499
			if ($res) {
3500
				$classname = $conf->global->SOCIETE_CODECOMPTA_ADDON;
3501
				$mod = new $classname;
3502
3503
				// Set code count in $mod->code
3504
				$result = $mod->get_code($this->db, $this, $type);
3505
3506
				if ($type == 'customer') {
3507
					$this->code_compta_client = $mod->code;
3508
					$this->code_compta = $this->code_compta_client; // For backward compatibility
3509
				} elseif ($type == 'supplier') {
3510
					$this->code_compta_fournisseur = $mod->code;
3511
				}
3512
3513
				return $result;
3514
			} else {
3515
				$this->error = 'ErrorAccountancyCodeNotDefined';
3516
				return -1;
3517
			}
3518
		} else {
3519
			if ($type == 'customer') {
3520
				$this->code_compta_client = '';
3521
				$this->code_compta = '';
3522
			} elseif ($type == 'supplier') {
3523
				$this->code_compta_fournisseur = '';
3524
			}
3525
3526
			return 0;
3527
		}
3528
	}
3529
3530
	/**
3531
	 *    Define parent company of current company
3532
	 *
3533
	 *    @param	int		$id     Id of thirdparty to set or '' to remove
3534
	 *    @return	int     		<0 if KO, >0 if OK
3535
	 */
3536
	public function setParent($id)
3537
	{
3538
		dol_syslog(get_class($this).'::setParent', LOG_DEBUG);
3539
3540
		if ($this->id) {
3541
			// Check if the id we want to add as parent has not already one parent that is the current id we try to update
3542
			if ($id > 0) {
3543
				$sameparent = $this->validateFamilyTree($id, $this->id, 0);
3544
				if ($sameparent < 0) {
3545
					return -1;
3546
				}
3547
				if ($sameparent == 1) {
3548
					setEventMessages('ParentCompanyToAddIsAlreadyAChildOfModifiedCompany', null, 'warnings');
3549
					return -1;
3550
				}
3551
			}
3552
3553
			$sql = 'UPDATE '.MAIN_DB_PREFIX.'societe SET parent = '.($id > 0 ? $id : 'null').' WHERE rowid = '.((int) $this->id);
3554
3555
			$resql = $this->db->query($sql);
3556
			if ($resql) {
3557
				$this->parent = $id;
3558
				return 1;
3559
			} else {
3560
				return -1;
3561
			}
3562
		}
3563
3564
		return -1;
3565
	}
3566
3567
	/**
3568
	 *    Check if a thirdparty $idchild is or not inside the parents (or grand parents) of another thirdparty id $idparent.
3569
	 *
3570
	 *    @param	int		$idparent	Id of thirdparty to check
3571
	 *    @param	int		$idchild	Id of thirdparty to compare to
3572
	 *    @param    int     $counter    Counter to protect against infinite loops
3573
	 *    @return	int     			<0 if KO, 0 if OK or 1 if at some level a parent company was the child to compare to
3574
	 */
3575
	public function validateFamilyTree($idparent, $idchild, $counter = 0)
3576
	{
3577
		if ($counter > 100) {
3578
			dol_syslog("Too high level of parent - child for company. May be an infinite loop ?", LOG_WARNING);
3579
		}
3580
3581
		$sql = 'SELECT s.parent';
3582
		$sql .= ' FROM '.MAIN_DB_PREFIX.'societe as s';
3583
		$sql .= ' WHERE rowid = '.((int) $idparent);
3584
		$resql = $this->db->query($sql);
3585
		if ($resql) {
3586
			$obj	= $this->db->fetch_object($resql);
3587
3588
			if ($obj->parent == '') {
3589
				return 0;
3590
			} elseif ($obj->parent == $idchild) {
3591
				return 1;
3592
			} else {
3593
				$sameparent = $this->validateFamilyTree($obj->parent, $idchild, ($counter + 1));
3594
			}
3595
			return $sameparent;
3596
		} else {
3597
			return -1;
3598
		}
3599
	}
3600
3601
	/**
3602
	 *	Get parents for company
3603
	 *
3604
	 * @param   int         $company_id     ID of company to search parent
3605
	 * @param   array       $parents        List of companies ID found
3606
	 * @return	array
3607
	 */
3608
	public function getParentsForCompany($company_id, $parents = [])
3609
	{
3610
		global $langs;
3611
3612
		if ($company_id > 0) {
3613
			$sql = "SELECT parent FROM " . MAIN_DB_PREFIX . "societe WHERE rowid = $company_id";
3614
			$resql = $this->db->query($sql);
3615
			if ($resql) {
3616
				if ($obj = $this->db->fetch_object($resql)) {
3617
					$parent = $obj->parent;
3618
					if ($parent > 0 && !in_array($parent, $parents)) {
3619
						$parents[] = $parent;
3620
						return $this->getParentsForCompany($parent, $parents);
3621
					} else {
3622
						return $parents;
3623
					}
3624
				}
3625
				$this->db->free($resql);
3626
			} else {
3627
				setEventMessage($langs->trans('GetCompanyParentsError', $this->db->lasterror()), 'errors');
3628
			}
3629
		}
3630
	}
3631
3632
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3633
	/**
3634
	 *  Returns if a profid sould be verified to be unique
3635
	 *
3636
	 *  @param	int		$idprof		1,2,3,4,5,6 (Example: 1=siren, 2=siret, 3=naf, 4=rcs/rm, 5=eori, 6=idprof6)
3637
	 *  @return boolean         	true if the ID must be unique
3638
	 */
3639
	public function id_prof_verifiable($idprof)
3640
	{
3641
		// phpcs:enable
3642
		global $conf;
3643
3644
		switch ($idprof) {
3645
			case 1:
3646
				$ret = (empty($conf->global->SOCIETE_IDPROF1_UNIQUE) ? false : true);
3647
				break;
3648
			case 2:
3649
				$ret = (empty($conf->global->SOCIETE_IDPROF2_UNIQUE) ? false : true);
3650
				break;
3651
			case 3:
3652
				$ret = (empty($conf->global->SOCIETE_IDPROF3_UNIQUE) ? false : true);
3653
				break;
3654
			case 4:
3655
				$ret = (empty($conf->global->SOCIETE_IDPROF4_UNIQUE) ? false : true);
3656
				break;
3657
			case 5:
3658
				$ret = (empty($conf->global->SOCIETE_IDPROF5_UNIQUE) ? false : true);
3659
				break;
3660
			case 6:
3661
				$ret = (empty($conf->global->SOCIETE_IDPROF6_UNIQUE) ? false : true);
3662
				break;
3663
			default:
3664
				$ret = false;
3665
		}
3666
3667
		return $ret;
3668
	}
3669
3670
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3671
	/**
3672
	 *    Verify if a profid exists into database for others thirds
3673
	 *
3674
	 *    @param	string	$idprof		'idprof1','idprof2','idprof3','idprof4','idprof5','idprof6','email' (Example: idprof1=siren, idprof2=siret, idprof3=naf, idprof4=rcs/rm)
3675
	 *    @param	string	$value		Value of profid
3676
	 *    @param	int		$socid		Id of thirdparty to exclude (if update)
3677
	 *    @return   boolean				True if exists, False if not
3678
	 */
3679
	public function id_prof_exists($idprof, $value, $socid = 0)
3680
	{
3681
		// phpcs:enable
3682
		$field = $idprof;
3683
3684
		switch ($idprof) {	// For backward compatibility
3685
			case '1':
3686
			case 'idprof1':
3687
				$field = "siren";
3688
				break;
3689
			case '2':
3690
			case 'idprof2':
3691
				$field = "siret";
3692
				break;
3693
			case '3':
3694
			case 'idprof3':
3695
				$field = "ape";
3696
				break;
3697
			case '4':
3698
			case 'idprof4':
3699
				$field = "idprof4";
3700
				break;
3701
			case '5':
3702
				$field = "idprof5";
3703
				break;
3704
			case '6':
3705
				$field = "idprof6";
3706
				break;
3707
		}
3708
3709
		 //Verify duplicate entries
3710
		$sql = "SELECT COUNT(*) as nb FROM ".MAIN_DB_PREFIX."societe WHERE ".$field." = '".$this->db->escape($value)."' AND entity IN (".getEntity('societe').")";
3711
		if ($socid) {
3712
			$sql .= " AND rowid <> ".$socid;
3713
		}
3714
		$resql = $this->db->query($sql);
3715
		if ($resql) {
3716
			$obj = $this->db->fetch_object($resql);
3717
			$count = $obj->nb;
3718
		} else {
3719
			$count = 0;
3720
			print $this->db->error();
3721
		}
3722
		$this->db->free($resql);
3723
3724
		if ($count > 0) {
3725
			return true;
3726
		} else {
3727
			return false;
3728
		}
3729
	}
3730
3731
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3732
	/**
3733
	 *  Check the validity of a professional identifier according to the country of the company (siren, siret, ...)
3734
	 *
3735
	 *  @param	int			$idprof         1,2,3,4 (Exemple: 1=siren,2=siret,3=naf,4=rcs/rm)
3736
	 *  @param  Societe		$soc            Objet societe
3737
	 *  @return int             			<=0 if KO, >0 if OK
3738
	 *  TODO better to have this in a lib than into a business class
3739
	 */
3740
	public function id_prof_check($idprof, $soc)
3741
	{
3742
		// phpcs:enable
3743
		global $conf;
3744
3745
		$ok = 1;
3746
3747
		if (!empty($conf->global->MAIN_DISABLEPROFIDRULES)) {
3748
			return 1;
3749
		}
3750
3751
		// Check SIREN if country FR
3752
		if ($idprof == 1 && $soc->country_code == 'FR') {
3753
			$chaine = trim($this->idprof1);
3754
			$chaine = preg_replace('/(\s)/', '', $chaine);
3755
3756
			if (!is_numeric($chaine)) {
3757
				return -1;
3758
			}
3759
			if (dol_strlen($chaine) != 9) {
3760
				return -1;
3761
			}
3762
3763
			// on prend chaque chiffre un par un
3764
			// si son index (position dans la chaîne en commence à 0 au premier caractère) est impair
3765
			// on double sa valeur et si cette dernière est supérieure à 9, on lui retranche 9
3766
			// on ajoute cette valeur à la somme totale
3767
			$sum = 0;
3768
			for ($index = 0; $index < 9; $index++) {
3769
				$number = (int) $chaine[$index];
3770
				if (($index % 2) != 0) {
3771
					if (($number *= 2) > 9) {
3772
						$number -= 9;
3773
					}
3774
				}
3775
				$sum += $number;
3776
			}
3777
3778
			// le numéro est valide si la somme des chiffres est multiple de 10
3779
			if (($sum % 10) != 0) {
3780
				return -1;
3781
			}
3782
		}
3783
3784
		// Verifie SIRET si pays FR
3785
		if ($idprof == 2 && $soc->country_code == 'FR') {
3786
			$chaine = trim($this->idprof2);
3787
			$chaine = preg_replace('/(\s)/', '', $chaine);
3788
3789
			if (!is_numeric($chaine)) {
3790
				return -1;
3791
			}
3792
			if (dol_strlen($chaine) != 14) {
3793
				return -1;
3794
			}
3795
3796
			// on prend chaque chiffre un par un
3797
			// si son index (position dans la chaîne en commence à 0 au premier caractère) est pair
3798
			// on double sa valeur et si cette dernière est supérieure à 9, on lui retranche 9
3799
			// on ajoute cette valeur à la somme totale
3800
			$sum = 0;
3801
			for ($index = 0; $index < 14; $index++) {
3802
				$number = (int) $chaine[$index];
3803
				if (($index % 2) == 0) {
3804
					if (($number *= 2) > 9) {
3805
						$number -= 9;
3806
					}
3807
				}
3808
				$sum += $number;
3809
			}
3810
3811
			// le numéro est valide si la somme des chiffres est multiple de 10
3812
			if (($sum % 10) != 0) {
3813
				return -1;
3814
			}
3815
		}
3816
3817
		//Verify CIF/NIF/NIE if pays ES
3818
		//Returns: 1 if NIF ok, 2 if CIF ok, 3 if NIE ok, -1 if NIF bad, -2 if CIF bad, -3 if NIE bad, 0 if unexpected bad
3819
		if ($idprof == 1 && $soc->country_code == 'ES') {
3820
			$string = trim($this->idprof1);
3821
			$string = preg_replace('/(\s)/', '', $string);
3822
			$string = strtoupper($string);
3823
3824
			//Check format
3825
			if (!preg_match('/((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)/', $string)) {
3826
				return 0;
3827
			}
3828
3829
			$num = array();
3830
			for ($i = 0; $i < 9; $i++) {
3831
				$num[$i] = substr($string, $i, 1);
3832
			}
3833
3834
			//Check NIF
3835
			if (preg_match('/(^[0-9]{8}[A-Z]{1}$)/', $string)) {
3836
				if ($num[8] == substr('TRWAGMYFPDXBNJZSQVHLCKE', substr($string, 0, 8) % 23, 1)) {
3837
					return 1;
3838
				} else {
3839
					return -1;
3840
				}
3841
			}
3842
3843
			//algorithm checking type code CIF
3844
			$sum = $num[2] + $num[4] + $num[6];
3845
			for ($i = 1; $i < 8; $i += 2) {
3846
				$sum += intval(substr((2 * $num[$i]), 0, 1)) + intval(substr((2 * $num[$i]), 1, 1));
3847
			}
3848
			$n = 10 - substr($sum, strlen($sum) - 1, 1);
3849
3850
			//Chek special NIF
3851
			if (preg_match('/^[KLM]{1}/', $string)) {
3852
				if ($num[8] == chr(64 + $n) || $num[8] == substr('TRWAGMYFPDXBNJZSQVHLCKE', substr($string, 1, 8) % 23, 1)) {
3853
					return 1;
3854
				} else {
3855
					return -1;
3856
				}
3857
			}
3858
3859
			//Check CIF
3860
			if (preg_match('/^[ABCDEFGHJNPQRSUVW]{1}/', $string)) {
3861
				if ($num[8] == chr(64 + $n) || $num[8] == substr($n, strlen($n) - 1, 1)) {
3862
					return 2;
3863
				} else {
3864
					return -2;
3865
				}
3866
			}
3867
3868
			//Check NIE T
3869
			if (preg_match('/^[T]{1}/', $string)) {
3870
				if ($num[8] == preg_match('/^[T]{1}[A-Z0-9]{8}$/', $string)) {
3871
					return 3;
3872
				} else {
3873
					return -3;
3874
				}
3875
			}
3876
3877
			//Check NIE XYZ
3878
			if (preg_match('/^[XYZ]{1}/', $string)) {
3879
				if ($num[8] == substr('TRWAGMYFPDXBNJZSQVHLCKE', substr(str_replace(array('X', 'Y', 'Z'), array('0', '1', '2'), $string), 0, 8) % 23, 1)) {
3880
					return 3;
3881
				} else {
3882
					return -3;
3883
				}
3884
			}
3885
3886
			//Can not be verified
3887
			return -4;
3888
		}
3889
3890
		//Verify NIF if country is PT
3891
		//Returns: 1 if NIF ok, -1 if NIF bad, 0 if unexpected bad
3892
		if ($idprof == 1 && $soc->country_code == 'PT') {
3893
			$string = trim($this->idprof1);
3894
			$string = preg_replace('/(\s)/', '', $string);
3895
3896
			//Check NIF
3897
			if (preg_match('/(^[0-9]{9}$)/', $string)) {
3898
				return 1;
3899
			} else {
3900
				return -1;
3901
			}
3902
		}
3903
3904
		//Verify NIF if country is DZ
3905
		//Returns: 1 if NIF ok, -1 if NIF bad, 0 if unexpected bad
3906
		if ($idprof == 1 && $soc->country_code == 'DZ') {
3907
			$string = trim($this->idprof1);
3908
			$string = preg_replace('/(\s)/', '', $string);
3909
3910
			//Check NIF
3911
			if (preg_match('/(^[0-9]{15}$)/', $string)) {
3912
				return 1;
3913
			} else {
3914
				return -1;
3915
			}
3916
		}
3917
3918
		return $ok;
3919
	}
3920
3921
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3922
	/**
3923
	 *   Return an url to check online a professional id or empty string
3924
	 *
3925
	 *   @param		int		$idprof         1,2,3,4 (Example: 1=siren,2=siret,3=naf,4=rcs/rm)
3926
	 *   @param 	Societe	$thirdparty     Object thirdparty
3927
	 *   @return	string          		Url or empty string if no URL known
3928
	 *   TODO better in a lib than into business class
3929
	 */
3930
	public function id_prof_url($idprof, $thirdparty)
3931
	{
3932
		// phpcs:enable
3933
		global $conf, $langs, $hookmanager;
3934
3935
		$url = '';
3936
		$action = '';
3937
3938
		$hookmanager->initHooks(array('idprofurl'));
3939
		$parameters = array('idprof'=>$idprof, 'company'=>$thirdparty);
3940
		$reshook = $hookmanager->executeHooks('getIdProfUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
3941
		if (empty($reshook)) {
3942
			if (!empty($conf->global->MAIN_DISABLEPROFIDRULES)) {
3943
				return '';
3944
			}
3945
3946
			// TODO Move links to validate professional ID into a dictionary table "country" + "link"
3947
			$strippedIdProf1 = str_replace(' ', '', $thirdparty->idprof1);
3948
			if ($idprof == 1 && $thirdparty->country_code == 'FR') {
3949
				$url = 'https://annuaire-entreprises.data.gouv.fr/entreprise/'.$strippedIdProf1; // See also http://avis-situation-sirene.insee.fr/
3950
			}
3951
			if ($idprof == 1 && ($thirdparty->country_code == 'GB' || $thirdparty->country_code == 'UK')) {
3952
				$url = 'https://beta.companieshouse.gov.uk/company/'.$strippedIdProf1;
3953
			}
3954
			if ($idprof == 1 && $thirdparty->country_code == 'ES') {
3955
				$url = 'http://www.e-informa.es/servlet/app/portal/ENTP/screen/SProducto/prod/ETIQUETA_EMPRESA/nif/'.$strippedIdProf1;
3956
			}
3957
			if ($idprof == 1 && $thirdparty->country_code == 'IN') {
3958
				$url = 'http://www.tinxsys.com/TinxsysInternetWeb/dealerControllerServlet?tinNumber='.$strippedIdProf1.';&searchBy=TIN&backPage=searchByTin_Inter.jsp';
3959
			}
3960
			if ($idprof == 1 && $thirdparty->country_code == 'DZ') {
3961
				$url = 'http://nif.mfdgi.gov.dz/nif.asp?Nif='.$strippedIdProf1;
3962
			}
3963
			if ($idprof == 1 && $thirdparty->country_code == 'PT') {
3964
				$url = 'http://www.nif.pt/'.$strippedIdProf1;
3965
			}
3966
3967
			if ($url) {
3968
				return '<a target="_blank" rel="noopener noreferrer" href="'.$url.'">'.$langs->trans("Check").'</a>';
3969
			}
3970
		} else {
3971
			return $hookmanager->resPrint;
3972
		}
3973
3974
		return '';
3975
	}
3976
3977
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
3978
	/**
3979
	 *   Indicates if the company has projects
3980
	 *
3981
	 *   @return     bool	   true if the company has projects, false otherwise
3982
	 */
3983
	public function has_projects()
3984
	{
3985
		// phpcs:enable
3986
		$sql = "SELECT COUNT(*) as numproj FROM ".MAIN_DB_PREFIX."projet WHERE fk_soc = ".((int) $this->id);
3987
		$resql = $this->db->query($sql);
3988
		if ($resql) {
3989
			$obj = $this->db->fetch_object($resql);
3990
			$count = $obj->numproj;
3991
		} else {
3992
			$count = 0;
3993
			print $this->db->error();
3994
		}
3995
		$this->db->free($resql);
3996
		return ($count > 0);
3997
	}
3998
3999
4000
	/**
4001
	 *  Load information for tab info
4002
	 *
4003
	 *  @param  int		$id     Id of thirdparty to load
4004
	 *  @return	void
4005
	 */
4006
	public function info($id)
4007
	{
4008
		$sql = "SELECT s.rowid, s.nom as name, s.datec, tms as datem,";
4009
		$sql .= " fk_user_creat, fk_user_modif";
4010
		$sql .= " FROM ".MAIN_DB_PREFIX."societe as s";
4011
		$sql .= " WHERE s.rowid = ".((int) $id);
4012
4013
		$result = $this->db->query($sql);
4014
		if ($result) {
4015
			if ($this->db->num_rows($result)) {
4016
				$obj = $this->db->fetch_object($result);
4017
4018
				$this->id = $obj->rowid;
4019
4020
				$this->user_creation_id = $obj->fk_user_creat;
4021
				$this->user_modification_id = $obj->fk_user_modif;
4022
				$this->date_creation     = $this->db->jdate($obj->datec);
4023
				$this->date_modification = empty($obj->datem) ? '' : $this->db->jdate($obj->datem);
4024
4025
				$this->ref = $obj->name;
4026
			}
4027
4028
			$this->db->free($result);
4029
		} else {
4030
			dol_print_error($this->db);
4031
		}
4032
	}
4033
4034
	/**
4035
	 *  Return if third party is a company (Business) or an end user (Consumer)
4036
	 *
4037
	 *  @return    boolean     true=is a company, false=a and user
4038
	 */
4039
	public function isACompany()
4040
	{
4041
		global $conf;
4042
4043
		// Define if third party is treated as company (or not) when nature is unknown
4044
		$isacompany = empty($conf->global->MAIN_UNKNOWN_CUSTOMERS_ARE_COMPANIES) ? 0 : 1; // 0 by default
4045
		if (!empty($this->tva_intra)) {
4046
			$isacompany = 1;
4047
		} elseif (!empty($this->idprof1) || !empty($this->idprof2) || !empty($this->idprof3) || !empty($this->idprof4) || !empty($this->idprof5) || !empty($this->idprof6)) {
4048
			$isacompany = 1;
4049
		} elseif (!empty($this->typent_code) && $this->typent_code != 'TE_UNKNOWN') {
4050
			// TODO Add a field is_a_company into dictionary
4051
			if (preg_match('/^TE_PRIVATE/', $this->typent_code)) {
4052
				$isacompany = 0;
4053
			} else {
4054
				$isacompany = 1;
4055
			}
4056
		}
4057
4058
		return $isacompany;
4059
	}
4060
4061
	/**
4062
	 *  Return if a company is inside the EEC (European Economic Community)
4063
	 *
4064
	 *  @return     boolean		true = country inside EEC, false = country outside EEC
4065
	 */
4066
	public function isInEEC()
4067
	{
4068
		require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
4069
		return isInEEC($this);
4070
	}
4071
4072
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4073
	/**
4074
	 *  Load the list of provider categories
4075
	 *
4076
	 *  @return    int      0 if success, <> 0 if error
4077
	 */
4078
	public function LoadSupplierCateg()
4079
	{
4080
		// phpcs:enable
4081
		$this->SupplierCategories = array();
4082
		$sql = "SELECT rowid, label";
4083
		$sql .= " FROM ".MAIN_DB_PREFIX."categorie";
4084
		$sql .= " WHERE type = ".Categorie::TYPE_SUPPLIER;
4085
4086
		$resql = $this->db->query($sql);
4087
		if ($resql) {
4088
			while ($obj = $this->db->fetch_object($resql)) {
4089
				$this->SupplierCategories[$obj->rowid] = $obj->label;
4090
			}
4091
			return 0;
4092
		} else {
4093
			return -1;
4094
		}
4095
	}
4096
4097
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4098
	/**
4099
	 *  Insert link supplier - category
4100
	 *
4101
	 *	@param	int		$categorie_id		Id of category
4102
	 *  @return int      					0 if success, <> 0 if error
4103
	 */
4104
	public function AddFournisseurInCategory($categorie_id)
4105
	{
4106
		// phpcs:enable
4107
		if ($categorie_id > 0 && $this->id > 0) {
4108
			$sql = "INSERT INTO ".MAIN_DB_PREFIX."categorie_fournisseur (fk_categorie, fk_soc) ";
4109
			$sql .= " VALUES (".((int) $categorie_id).", ".((int) $this->id).")";
4110
4111
			if ($resql = $this->db->query($sql)) {
4112
				return 0;
4113
			}
4114
		} else {
4115
			return 0;
4116
		}
4117
		return -1;
4118
	}
4119
4120
	/**
4121
	 *  Return number of mass Emailing received by this contacts with its email
4122
	 *
4123
	 *  @return       int     Number of EMailings
4124
	 */
4125
	public function getNbOfEMailings()
4126
	{
4127
		$sql = "SELECT count(mc.email) as nb";
4128
		$sql .= " FROM ".MAIN_DB_PREFIX."mailing_cibles as mc, ".MAIN_DB_PREFIX."mailing as m";
4129
		$sql .= " WHERE mc.fk_mailing=m.rowid AND mc.email = '".$this->db->escape($this->email)."' ";
4130
		$sql .= " AND m.entity IN (".getEntity($this->element).") AND mc.statut NOT IN (-1,0)"; // -1 error, 0 not sent, 1 sent with success
4131
4132
		$resql = $this->db->query($sql);
4133
		if ($resql) {
4134
			$obj = $this->db->fetch_object($resql);
4135
			$nb = $obj->nb;
4136
4137
			$this->db->free($resql);
4138
			return $nb;
4139
		} else {
4140
			$this->error = $this->db->error();
4141
			return -1;
4142
		}
4143
	}
4144
4145
	/**
4146
	 *  Set "blacklist" mailing status
4147
	 *
4148
	 *  @param	int		$no_email	1=Do not send mailing, 0=Ok to recieve mailling
4149
	 *  @return int					<0 if KO, >0 if OK
4150
	 */
4151
	public function setNoEmail($no_email)
4152
	{
4153
		$error = 0;
4154
4155
		// Update mass emailing flag into table mailing_unsubscribe
4156
		if ($this->email) {
4157
			$this->db->begin();
4158
4159
			if ($no_email) {
4160
				$sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE entity IN (".getEntity('mailing', 0).") AND email = '".$this->db->escape($this->email)."'";
4161
				$resql = $this->db->query($sql);
4162
				if ($resql) {
4163
					$obj = $this->db->fetch_object($resql);
4164
					$noemail = $obj->nb;
4165
					if (empty($noemail)) {
4166
						$sql = "INSERT INTO ".MAIN_DB_PREFIX."mailing_unsubscribe(email, entity, date_creat) VALUES ('".$this->db->escape($this->email)."', ".getEntity('mailing', 0).", '".$this->db->idate(dol_now())."')";
4167
						$resql = $this->db->query($sql);
4168
						if (!$resql) {
4169
							$error++;
4170
							$this->error = $this->db->lasterror();
4171
							$this->errors[] = $this->error;
4172
						}
4173
					}
4174
				} else {
4175
					$error++;
4176
					$this->error = $this->db->lasterror();
4177
					$this->errors[] = $this->error;
4178
				}
4179
			} else {
4180
				$sql = "DELETE FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE email = '".$this->db->escape($this->email)."' AND entity IN (".getEntity('mailing', 0).")";
4181
				$resql = $this->db->query($sql);
4182
				if (!$resql) {
4183
					$error++;
4184
					$this->error = $this->db->lasterror();
4185
					$this->errors[] = $this->error;
4186
				}
4187
			}
4188
4189
			if (empty($error)) {
4190
				$this->no_email = $no_email;
4191
				$this->db->commit();
4192
				return 1;
4193
			} else {
4194
				$this->db->rollback();
4195
				return $error * -1;
4196
			}
4197
		}
4198
4199
		return 0;
4200
	}
4201
4202
	/**
4203
	 *  get "blacklist" mailing status
4204
	 * 	set no_email attribut to 1 or 0
4205
	 *
4206
	 *  @return int					<0 if KO, >0 if OK
4207
	 */
4208
	public function getNoEmail()
4209
	{
4210
		if ($this->email) {
4211
			$sql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."mailing_unsubscribe WHERE entity IN (".getEntity('mailing').") AND email = '".$this->db->escape($this->email)."'";
4212
			$resql = $this->db->query($sql);
4213
			if ($resql) {
4214
				$obj = $this->db->fetch_object($resql);
4215
				$this->no_email = $obj->nb;
4216
				return 1;
4217
			} else {
4218
				$this->error = $this->db->lasterror();
4219
				$this->errors[] = $this->error;
4220
				return -1;
4221
			}
4222
		}
4223
		return 0;
4224
	}
4225
4226
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4227
	/**
4228
	 *  Create a third party into database from a member object
4229
	 *
4230
	 *  @param	Adherent	$member			Object member
4231
	 * 	@param	string		$socname		Name of third party to force
4232
	 *	@param	string		$socalias		Alias name of third party to force
4233
	 *  @param	string		$customercode	Customer code
4234
	 *  @return int							<0 if KO, id of created account if OK
4235
	 */
4236
	public function create_from_member(Adherent $member, $socname = '', $socalias = '', $customercode = '')
4237
	{
4238
		// phpcs:enable
4239
		global $conf, $user, $langs;
4240
4241
		dol_syslog(get_class($this)."::create_from_member", LOG_DEBUG);
4242
		$fullname = $member->getFullName($langs);
4243
4244
		if ($member->morphy == 'mor') {
4245
			if (empty($socname)) {
4246
				$socname = $member->company? $member->company : $member->societe;
4247
			}
4248
			if (!empty($fullname) && empty($socalias)) {
4249
				$socalias = $fullname;
4250
			}
4251
		} elseif (empty($socname) && $member->morphy == 'phy') {
4252
			if (empty($socname)) {
4253
				$socname = $fullname;
4254
			}
4255
			if (!empty($member->company) && empty($socalias)) {
4256
				$socalias = $member->company;
4257
			}
4258
		}
4259
4260
		$name = $socname;
4261
		$alias = $socalias ? $socalias : '';
4262
4263
		// Positionne parametres
4264
		$this->nom = $name; // TODO deprecated
4265
		$this->name = $name;
4266
		$this->name_alias = $alias;
4267
		$this->address = $member->address;
4268
		$this->zip = $member->zip;
4269
		$this->town = $member->town;
4270
		$this->country_code = $member->country_code;
4271
		$this->country_id = $member->country_id;
4272
		$this->phone = $member->phone; // Prof phone
4273
		$this->email = $member->email;
4274
		$this->socialnetworks = $member->socialnetworks;
4275
		$this->entity = $member->entity;
4276
4277
		$this->client = 1; // A member is a customer by default
4278
		$this->code_client = ($customercode ? $customercode : -1);
4279
		$this->code_fournisseur = -1;
4280
		$this->typent_code = ($member->morphy == 'phy' ? 'TE_PRIVATE' : 0);
4281
		$this->typent_id = $this->typent_code ? dol_getIdFromCode($this->db, $this->typent_code, 'c_typent', 'id', 'code') : 0;
4282
4283
		$this->db->begin();
4284
4285
		// Cree et positionne $this->id
4286
		$result = $this->create($user);
4287
4288
		if ($result >= 0) {
4289
			// Auto-create contact on thirdparty creation
4290
			if (!empty($conf->global->THIRDPARTY_DEFAULT_CREATE_CONTACT)) {
4291
				// Fill fields needed by contact
4292
				$this->name_bis = $member->lastname;
4293
				$this->firstname = $member->firstname;
4294
				$this->civility_id = $member->civility_id;
4295
4296
				dol_syslog("We ask to create a contact/address too", LOG_DEBUG);
4297
				$result = $this->create_individual($user);
4298
4299
				if ($result < 0) {
4300
					setEventMessages($this->error, $this->errors, 'errors');
4301
					$this->db->rollback();
4302
					return -1;
4303
				}
4304
			}
4305
4306
			$sql = "UPDATE ".MAIN_DB_PREFIX."adherent";
4307
			$sql .= " SET fk_soc = ".((int) $this->id);
4308
			$sql .= " WHERE rowid = ".((int) $member->id);
4309
4310
			$resql = $this->db->query($sql);
4311
			if ($resql) {
4312
				$this->db->commit();
4313
				return $this->id;
4314
			} else {
4315
				$this->error = $this->db->error();
4316
4317
				$this->db->rollback();
4318
				return -1;
4319
			}
4320
		} else {
4321
			// $this->error deja positionne
4322
			dol_syslog(get_class($this)."::create_from_member - 2 - ".$this->error." - ".join(',', $this->errors), LOG_ERR);
4323
4324
			$this->db->rollback();
4325
			return $result;
4326
		}
4327
	}
4328
4329
	/**
4330
	 * 	Set properties with value into $conf
4331
	 *
4332
	 * 	@param	Conf	$conf		Conf object (possibility to use another entity)
4333
	 * 	@return	void
4334
	 */
4335
	public function setMysoc(Conf $conf)
4336
	{
4337
		global $langs;
4338
4339
		$this->id = 0;
4340
		$this->name = getDolGlobalString('MAIN_INFO_SOCIETE_NOM');
4341
		$this->address = getDolGlobalString('MAIN_INFO_SOCIETE_ADDRESS');
4342
		$this->zip = getDolGlobalString('MAIN_INFO_SOCIETE_ZIP');
4343
		$this->town = getDolGlobalString('MAIN_INFO_SOCIETE_TOWN');
4344
		$this->region_code = getDolGlobalString('MAIN_INFO_SOCIETE_REGION');
4345
4346
		$this->socialobject = getDolGlobalString('MAIN_INFO_SOCIETE_OBJECT');
4347
4348
		$this->note_private = getDolGlobalString('MAIN_INFO_SOCIETE_NOTE');
4349
4350
		$this->nom = $this->name; // deprecated
4351
4352
		// We define country_id, country_code and country
4353
		$country_id = $country_code = $country_label = '';
4354
		if (!empty($conf->global->MAIN_INFO_SOCIETE_COUNTRY)) {
4355
			$tmp = explode(':', $conf->global->MAIN_INFO_SOCIETE_COUNTRY);
4356
			$country_id = $tmp[0];
4357
			if (!empty($tmp[1])) {   // If $conf->global->MAIN_INFO_SOCIETE_COUNTRY is "id:code:label"
4358
				$country_code = $tmp[1];
4359
				$country_label = $tmp[2];
4360
			} else {
4361
				// For backward compatibility
4362
				dol_syslog("Your country setup use an old syntax. Reedit it using setup area.", LOG_WARNING);
4363
				include_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
4364
				$country_code = getCountry($country_id, 2, $this->db); // This need a SQL request, but it's the old feature that should not be used anymore
4365
				$country_label = getCountry($country_id, 0, $this->db); // This need a SQL request, but it's the old feature that should not be used anymore
4366
			}
4367
		}
4368
		$this->country_id = $country_id;
4369
		$this->country_code = $country_code;
4370
		$this->country = $country_label;
4371
		if (is_object($langs)) {
4372
			$this->country = ($langs->trans('Country'.$country_code) != 'Country'.$country_code) ? $langs->trans('Country'.$country_code) : $country_label;
4373
		}
4374
4375
		//TODO This could be replicated for region but function `getRegion` didn't exist, so I didn't added it.
4376
		// We define state_id, state_code and state
4377
		$state_id = 0; $state_code = $state_label = '';
4378
		if (!empty($conf->global->MAIN_INFO_SOCIETE_STATE)) {
4379
			$tmp = explode(':', $conf->global->MAIN_INFO_SOCIETE_STATE);
4380
			$state_id = $tmp[0];
4381
			if (!empty($tmp[1])) {   // If $conf->global->MAIN_INFO_SOCIETE_STATE is "id:code:label"
4382
				$state_code = $tmp[1];
4383
				$state_label = $tmp[2];
4384
			} else { // For backward compatibility
4385
				dol_syslog("Your setup of State has an old syntax (entity=".$conf->entity."). Go in Home - Setup - Organization then Save should remove this error.", LOG_ERR);
4386
				include_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
4387
				$state_code = getState($state_id, 2, $this->db); // This need a SQL request, but it's the old feature that should not be used anymore
4388
				$state_label = getState($state_id, 0, $this->db); // This need a SQL request, but it's the old feature that should not be used anymore
4389
			}
4390
		}
4391
		$this->state_id = $state_id;
4392
		$this->state_code = $state_code;
4393
		$this->state = $state_label;
4394
		if (is_object($langs)) {
4395
			$this->state = ($langs->trans('State'.$state_code) != 'State'.$state_code) ? $langs->trans('State'.$state_code) : $state_label;
4396
		}
4397
4398
		$this->phone = getDolGlobalString('MAIN_INFO_SOCIETE_TEL');
4399
		$this->fax = getDolGlobalString('MAIN_INFO_SOCIETE_FAX');
4400
		$this->url = getDolGlobalString('MAIN_INFO_SOCIETE_WEB');
4401
4402
		// Social networks
4403
		$facebook_url = getDolGlobalString('MAIN_INFO_SOCIETE_FACEBOOK_URL');
4404
		$twitter_url = getDolGlobalString('MAIN_INFO_SOCIETE_TWITTER_URL');
4405
		$linkedin_url = getDolGlobalString('MAIN_INFO_SOCIETE_LINKEDIN_URL');
4406
		$instagram_url = getDolGlobalString('MAIN_INFO_SOCIETE_INSTAGRAM_URL');
4407
		$youtube_url = getDolGlobalString('MAIN_INFO_SOCIETE_YOUTUBE_URL');
4408
		$github_url = getDolGlobalString('MAIN_INFO_SOCIETE_GITHUB_URL');
4409
		$this->socialnetworks = array();
4410
		if (!empty($facebook_url)) {
4411
			$this->socialnetworks['facebook'] = $facebook_url;
4412
		}
4413
		if (!empty($twitter_url)) {
4414
			$this->socialnetworks['twitter'] = $twitter_url;
4415
		}
4416
		if (!empty($linkedin_url)) {
4417
			$this->socialnetworks['linkedin'] = $linkedin_url;
4418
		}
4419
		if (!empty($instagram_url)) {
4420
			$this->socialnetworks['instagram'] = $instagram_url;
4421
		}
4422
		if (!empty($youtube_url)) {
4423
			$this->socialnetworks['youtube'] = $youtube_url;
4424
		}
4425
		if (!empty($github_url)) {
4426
			$this->socialnetworks['github'] = $github_url;
4427
		}
4428
4429
		// Id prof generiques
4430
		$this->idprof1 = getDolGlobalString('MAIN_INFO_SIREN');
4431
		$this->idprof2 = getDolGlobalString('MAIN_INFO_SIRET');
4432
		$this->idprof3 = getDolGlobalString('MAIN_INFO_APE');
4433
		$this->idprof4 = getDolGlobalString('MAIN_INFO_RCS');
4434
		$this->idprof5 = getDolGlobalString('MAIN_INFO_PROFID5');
4435
		$this->idprof6 = getDolGlobalString('MAIN_INFO_PROFID6');
4436
		$this->tva_intra = getDolGlobalString('MAIN_INFO_TVAINTRA'); // VAT number, not necessarly INTRA.
4437
		$this->managers = getDolGlobalString('MAIN_INFO_SOCIETE_MANAGERS');
4438
		$this->capital = getDolGlobalString('MAIN_INFO_CAPITAL');
4439
		$this->forme_juridique_code = getDolGlobalString('MAIN_INFO_SOCIETE_FORME_JURIDIQUE');
4440
		$this->email = getDolGlobalString('MAIN_INFO_SOCIETE_MAIL');
4441
		$this->default_lang = getDolGlobalString('MAIN_LANG_DEFAULT', 'auto');
4442
		$this->logo =getDolGlobalString('MAIN_INFO_SOCIETE_LOGO');
4443
		$this->logo_small = getDolGlobalString('MAIN_INFO_SOCIETE_LOGO_SMALL');
4444
		$this->logo_mini = getDolGlobalString('MAIN_INFO_SOCIETE_LOGO_MINI');
4445
		$this->logo_squarred = getDolGlobalString('MAIN_INFO_SOCIETE_LOGO_SQUARRED');
4446
		$this->logo_squarred_small = getDolGlobalString('MAIN_INFO_SOCIETE_LOGO_SQUARRED_SMALL');
4447
		$this->logo_squarred_mini = getDolGlobalString('MAIN_INFO_SOCIETE_LOGO_SQUARRED_MINI');
4448
4449
		// Define if company use vat or not
4450
		$this->tva_assuj = $conf->global->FACTURE_TVAOPTION;
4451
4452
		// Define if company use local taxes
4453
		$this->localtax1_assuj = ((isset($conf->global->FACTURE_LOCAL_TAX1_OPTION) && ($conf->global->FACTURE_LOCAL_TAX1_OPTION == '1' || $conf->global->FACTURE_LOCAL_TAX1_OPTION == 'localtax1on')) ? 1 : 0);
4454
		$this->localtax2_assuj = ((isset($conf->global->FACTURE_LOCAL_TAX2_OPTION) && ($conf->global->FACTURE_LOCAL_TAX2_OPTION == '1' || $conf->global->FACTURE_LOCAL_TAX2_OPTION == 'localtax2on')) ? 1 : 0);
4455
	}
4456
4457
	/**
4458
	 *  Initialise an instance with random values.
4459
	 *  Used to build previews or test instances.
4460
	 *	id must be 0 if object instance is a specimen.
4461
	 *
4462
	 *  @return	int >0 if ok
4463
	 */
4464
	public function initAsSpecimen()
4465
	{
4466
		$now = dol_now();
4467
4468
		// Initialize parameters
4469
		$this->id = 0;
4470
		$this->entity = 1;
4471
		$this->name = 'THIRDPARTY SPECIMEN '.dol_print_date($now, 'dayhourlog');
4472
		$this->nom = $this->name; // For backward compatibility
4473
		$this->ref_ext = 'Ref ext';
4474
		$this->specimen = 1;
4475
		$this->address = '21 jump street';
4476
		$this->zip = '99999';
4477
		$this->town = 'MyTown';
4478
		$this->state_id = 1;
4479
		$this->state_code = 'AA';
4480
		$this->state = 'MyState';
4481
		$this->country_id = 1;
4482
		$this->country_code = 'FR';
4483
		$this->email = '[email protected]';
4484
		$this->socialnetworks = array(
4485
			'skype' => 'tom.hanson',
4486
			'twitter' => 'tomhanson',
4487
			'facebook' => 'tomhanson',
4488
			'linkedin' => 'tomhanson',
4489
		);
4490
		$this->url = 'http://www.specimen.com';
4491
4492
		$this->phone = '0909090901';
4493
		$this->fax = '0909090909';
4494
4495
		$this->code_client = 'CC-'.dol_print_date($now, 'dayhourlog');
4496
		$this->code_fournisseur = 'SC-'.dol_print_date($now, 'dayhourlog');
4497
		$this->capital = 10000;
4498
		$this->client = 1;
4499
		$this->prospect = 1;
4500
		$this->fournisseur = 1;
4501
		$this->tva_assuj = 1;
4502
		$this->tva_intra = 'EU1234567';
4503
		$this->note_public = 'This is a comment (public)';
4504
		$this->note_private = 'This is a comment (private)';
4505
4506
		$this->idprof1 = 'idprof1';
4507
		$this->idprof2 = 'idprof2';
4508
		$this->idprof3 = 'idprof3';
4509
		$this->idprof4 = 'idprof4';
4510
		$this->idprof5 = 'idprof5';
4511
		$this->idprof6 = 'idprof6';
4512
		return 1;
4513
	}
4514
4515
	/**
4516
	 *  Check if we must use localtax feature or not according to country (country of $mysoc in most cases).
4517
	 *
4518
	 *	@param		int		$localTaxNum	To get info for only localtax1 or localtax2
4519
	 *  @return		boolean					true or false
4520
	 */
4521
	public function useLocalTax($localTaxNum = 0)
4522
	{
4523
		$sql  = "SELECT t.localtax1, t.localtax2";
4524
		$sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
4525
		$sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$this->db->escape($this->country_code)."'";
4526
		$sql .= " AND t.active = 1";
4527
		if (empty($localTaxNum)) {
4528
			$sql .= " AND (t.localtax1_type <> '0' OR t.localtax2_type <> '0')";
4529
		} elseif ($localTaxNum == 1) {
4530
			$sql .= " AND t.localtax1_type <> '0'";
4531
		} elseif ($localTaxNum == 2) {
4532
			$sql .= " AND t.localtax2_type <> '0'";
4533
		}
4534
4535
		$resql = $this->db->query($sql);
4536
		if ($resql) {
4537
			return ($this->db->num_rows($resql) > 0);
4538
		} else {
4539
			return false;
4540
		}
4541
	}
4542
4543
	/**
4544
	 *  Check if we must use NPR Vat (french stupid rule) or not according to country (country of $mysoc in most cases).
4545
	 *
4546
	 *  @return		boolean					true or false
4547
	 */
4548
	public function useNPR()
4549
	{
4550
		$sql  = "SELECT t.rowid";
4551
		$sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
4552
		$sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$this->db->escape($this->country_code)."'";
4553
		$sql .= " AND t.active = 1 AND t.recuperableonly = 1";
4554
4555
		dol_syslog("useNPR", LOG_DEBUG);
4556
		$resql = $this->db->query($sql);
4557
		if ($resql) {
4558
			return ($this->db->num_rows($resql) > 0);
4559
		} else {
4560
			return false;
4561
		}
4562
	}
4563
4564
	/**
4565
	 *  Check if we must use revenue stamps feature or not according to country (country of $mysocin most cases).
4566
	 *  Table c_revenuestamp contains the country and value of stamp per invoice.
4567
	 *
4568
	 *  @return		boolean			true or false
4569
	 */
4570
	public function useRevenueStamp()
4571
	{
4572
		$sql  = "SELECT COUNT(*) as nb";
4573
		$sql .= " FROM ".MAIN_DB_PREFIX."c_revenuestamp as r, ".MAIN_DB_PREFIX."c_country as c";
4574
		$sql .= " WHERE r.fk_pays = c.rowid AND c.code = '".$this->db->escape($this->country_code)."'";
4575
		$sql .= " AND r.active = 1";
4576
4577
		dol_syslog("useRevenueStamp", LOG_DEBUG);
4578
		$resql = $this->db->query($sql);
4579
		if ($resql) {
4580
			$obj = $this->db->fetch_object($resql);
4581
			return (($obj->nb > 0) ?true:false);
4582
		} else {
4583
			$this->error = $this->db->lasterror();
4584
			return false;
4585
		}
4586
	}
4587
4588
	/**
4589
	 *	Return prostect level
4590
	 *
4591
	 *  @return     string        Libelle
4592
	 */
4593
	public function getLibProspLevel()
4594
	{
4595
		return $this->LibProspLevel($this->fk_prospectlevel);
4596
	}
4597
4598
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4599
	/**
4600
	 *  Return label of prospect level
4601
	 *
4602
	 *  @param	int		$fk_prospectlevel   	Prospect level
4603
	 *  @return string        					label of level
4604
	 */
4605
	public function LibProspLevel($fk_prospectlevel)
4606
	{
4607
		// phpcs:enable
4608
		global $langs;
4609
4610
		$lib = $langs->trans("ProspectLevel".$fk_prospectlevel);
4611
		// If lib not found in language file, we get label from cache/databse
4612
		if ($lib == $langs->trans("ProspectLevel".$fk_prospectlevel)) {
4613
			$lib = $langs->getLabelFromKey($this->db, $fk_prospectlevel, 'c_prospectlevel', 'code', 'label');
4614
		}
4615
		return $lib;
4616
	}
4617
4618
	/**
4619
	 *  Return status of prospect
4620
	 *
4621
	 *  @param	int		$mode       0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long
4622
	 *  @param	string	$label		Label to use for status for added status
4623
	 *  @return string        		Libelle
4624
	 */
4625
	public function getLibProspCommStatut($mode = 0, $label = '')
4626
	{
4627
		return $this->LibProspCommStatut($this->stcomm_id, $mode, $label, $this->stcomm_picto);
4628
	}
4629
4630
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4631
	/**
4632
	 *  Return label of a given status
4633
	 *
4634
	 *  @param	int|string	$status        	Id or code for prospection status
4635
	 *  @param  int			$mode          	0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto
4636
	 *  @param	string		$label			Label to use for status for added status
4637
	 *	@param 	string		$picto      	Name of image file to show ('filenew', ...)
4638
	 *                                      If no extension provided, we use '.png'. Image must be stored into theme/xxx/img directory.
4639
	 *                                      Example: picto.png                  if picto.png is stored into htdocs/theme/mytheme/img
4640
	 *                                      Example: picto.png@mymodule         if picto.png is stored into htdocs/mymodule/img
4641
	 *                                      Example: /mydir/mysubdir/picto.png  if picto.png is stored into htdocs/mydir/mysubdir (pictoisfullpath must be set to 1)
4642
	 *  @return string       	 			Label of prospection status
4643
	 */
4644
	public function LibProspCommStatut($status, $mode = 0, $label = '', $picto = '')
4645
	{
4646
		// phpcs:enable
4647
		global $langs;
4648
		$langs->load('customers');
4649
4650
		if ($mode == 2) {
4651
			if ($status == '-1' || $status == 'ST_NO') {
4652
				return img_action($langs->trans("StatusProspect-1"), -1, $picto).' '.$langs->trans("StatusProspect-1");
4653
			} elseif ($status == '0' || $status == 'ST_NEVER') {
4654
				return img_action($langs->trans("StatusProspect0"), 0, $picto).' '.$langs->trans("StatusProspect0");
4655
			} elseif ($status == '1' || $status == 'ST_TODO') {
4656
				return img_action($langs->trans("StatusProspect1"), 1, $picto).' '.$langs->trans("StatusProspect1");
4657
			} elseif ($status == '2' || $status == 'ST_PEND') {
4658
				return img_action($langs->trans("StatusProspect2"), 2, $picto).' '.$langs->trans("StatusProspect2");
4659
			} elseif ($status == '3' || $status == 'ST_DONE') {
4660
				return img_action($langs->trans("StatusProspect3"), 3, $picto).' '.$langs->trans("StatusProspect3");
4661
			} else {
4662
				return img_action(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label, 0, $picto).' '.(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label);
4663
			}
4664
		} elseif ($mode == 3) {
4665
			if ($status == '-1' || $status == 'ST_NO') {
4666
				return img_action($langs->trans("StatusProspect-1"), -1, $picto);
4667
			} elseif ($status == '0' || $status == 'ST_NEVER') {
4668
				return img_action($langs->trans("StatusProspect0"), 0, $picto);
4669
			} elseif ($status == '1' || $status == 'ST_TODO') {
4670
				return img_action($langs->trans("StatusProspect1"), 1, $picto);
4671
			} elseif ($status == '2' || $status == 'ST_PEND') {
4672
				return img_action($langs->trans("StatusProspect2"), 2, $picto);
4673
			} elseif ($status == '3' || $status == 'ST_DONE') {
4674
				return img_action($langs->trans("StatusProspect3"), 3, $picto);
4675
			} else {
4676
				return img_action(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label, 0, $picto);
4677
			}
4678
		} elseif ($mode == 4) {
4679
			if ($status == '-1' || $status == 'ST_NO') {
4680
				return img_action($langs->trans("StatusProspect-1"), -1, $picto).' '.$langs->trans("StatusProspect-1");
4681
			} elseif ($status == '0' || $status == 'ST_NEVER') {
4682
				return img_action($langs->trans("StatusProspect0"), 0, $picto).' '.$langs->trans("StatusProspect0");
4683
			} elseif ($status == '1' || $status == 'ST_TODO') {
4684
				return img_action($langs->trans("StatusProspect1"), 1, $picto).' '.$langs->trans("StatusProspect1");
4685
			} elseif ($status == '2' || $status == 'ST_PEND') {
4686
				return img_action($langs->trans("StatusProspect2"), 2, $picto).' '.$langs->trans("StatusProspect2");
4687
			} elseif ($status == '3' || $status == 'ST_DONE') {
4688
				return img_action($langs->trans("StatusProspect3"), 3, $picto).' '.$langs->trans("StatusProspect3");
4689
			} else {
4690
				return img_action(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label, 0, $picto).' '.(($langs->trans("StatusProspect".$status) != "StatusProspect".$status) ? $langs->trans("StatusProspect".$status) : $label);
4691
			}
4692
		}
4693
4694
		return "Error, mode/status not found";
4695
	}
4696
4697
	/**
4698
	 *  Return amount of proposal not yet paid and total an dlist of all proposals
4699
	 *
4700
	 *  @param     string      $mode    'customer' or 'supplier'
4701
	 *  @return    array				array('opened'=>Amount including tax that remains to pay, 'total_ht'=>Total amount without tax of all objects paid or not, 'total_ttc'=>Total amunt including tax of all object paid or not)
4702
	 */
4703
	public function getOutstandingProposals($mode = 'customer')
4704
	{
4705
		$table = 'propal';
4706
		if ($mode == 'supplier') {
4707
			$table = 'supplier_proposal';
4708
		}
4709
4710
		$sql  = "SELECT rowid, ref, total_ht, total_ttc, fk_statut as status FROM ".MAIN_DB_PREFIX.$table." as f";
4711
		$sql .= " WHERE fk_soc = ".((int) $this->id);
4712
		if ($mode == 'supplier') {
4713
			$sql .= " AND entity IN (".getEntity('supplier_proposal').")";
4714
		} else {
4715
			$sql .= " AND entity IN (".getEntity('propal').")";
4716
		}
4717
4718
		dol_syslog("getOutstandingProposals for fk_soc = ".((int) $this->id), LOG_DEBUG);
4719
4720
		$resql = $this->db->query($sql);
4721
		if ($resql) {
4722
			$outstandingOpened = 0;
4723
			$outstandingTotal = 0;
4724
			$outstandingTotalIncTax = 0;
4725
			$arrayofref = array();
4726
			while ($obj = $this->db->fetch_object($resql)) {
4727
				$arrayofref[$obj->rowid] = $obj->ref;
4728
				$outstandingTotal += $obj->total_ht;
4729
				$outstandingTotalIncTax += $obj->total_ttc;
4730
				if ($obj->status != 0) {
4731
					// Not a draft
4732
					$outstandingOpened += $obj->total_ttc;
4733
				}
4734
			}
4735
			return array('opened'=>$outstandingOpened, 'total_ht'=>$outstandingTotal, 'total_ttc'=>$outstandingTotalIncTax, 'refs'=>$arrayofref); // 'opened' is 'incl taxes'
4736
		} else {
4737
			return array();
4738
		}
4739
	}
4740
4741
	/**
4742
	 *  Return amount of order not yet paid and total and list of all orders
4743
	 *
4744
	 *  @param     string      $mode    'customer' or 'supplier'
4745
	 *  @return    array				array('opened'=>Amount including tax that remains to pay, 'total_ht'=>Total amount without tax of all objects paid or not, 'total_ttc'=>Total amunt including tax of all object paid or not)
4746
	 */
4747
	public function getOutstandingOrders($mode = 'customer')
4748
	{
4749
		$table = 'commande';
4750
		if ($mode == 'supplier') {
4751
			$table = 'commande_fournisseur';
4752
		}
4753
4754
		$sql  = "SELECT rowid, ref, total_ht, total_ttc, fk_statut as status FROM ".MAIN_DB_PREFIX.$table." as f";
4755
		$sql .= " WHERE fk_soc = ".((int) $this->id);
4756
		if ($mode == 'supplier') {
4757
			$sql .= " AND entity IN (".getEntity('supplier_order').")";
4758
		} else {
4759
			$sql .= " AND entity IN (".getEntity('commande').")";
4760
		}
4761
4762
		dol_syslog("getOutstandingOrders", LOG_DEBUG);
4763
		$resql = $this->db->query($sql);
4764
		if ($resql) {
4765
			$outstandingOpened = 0;
4766
			$outstandingTotal = 0;
4767
			$outstandingTotalIncTax = 0;
4768
			$arrayofref = array();
4769
			while ($obj = $this->db->fetch_object($resql)) {
4770
				$arrayofref[$obj->rowid] = $obj->ref;
4771
				$outstandingTotal += $obj->total_ht;
4772
				$outstandingTotalIncTax += $obj->total_ttc;
4773
				if ($obj->status != 0) {
4774
					// Not a draft
4775
					$outstandingOpened += $obj->total_ttc;
4776
				}
4777
			}
4778
			return array('opened'=>$outstandingOpened, 'total_ht'=>$outstandingTotal, 'total_ttc'=>$outstandingTotalIncTax, 'refs'=>$arrayofref); // 'opened' is 'incl taxes'
4779
		} else {
4780
			return array();
4781
		}
4782
	}
4783
4784
	/**
4785
	 *  Return amount of bill not yet paid and total of all invoices
4786
	 *
4787
	 *  @param     string   $mode    	'customer' or 'supplier'
4788
	 *  @param     int      $late    	0 => all invoice, 1=> only late
4789
	 *  @return    array				array('opened'=>Amount including tax that remains to pay, 'total_ht'=>Total amount without tax of all objects paid or not, 'total_ttc'=>Total amunt including tax of all object paid or not)
4790
	 */
4791
	public function getOutstandingBills($mode = 'customer', $late = 0)
4792
	{
4793
		$table = 'facture';
4794
		if ($mode == 'supplier') {
4795
			$table = 'facture_fourn';
4796
		}
4797
4798
		/* Accurate value of remain to pay is to sum remaintopay for each invoice
4799
		 $paiement = $invoice->getSommePaiement();
4800
		 $creditnotes=$invoice->getSumCreditNotesUsed();
4801
		 $deposits=$invoice->getSumDepositsUsed();
4802
		 $alreadypayed=price2num($paiement + $creditnotes + $deposits,'MT');
4803
		 $remaintopay=price2num($invoice->total_ttc - $paiement - $creditnotes - $deposits,'MT');
4804
		 */
4805
		$sql = "SELECT rowid, ref, total_ht, total_ttc, paye, type, fk_statut as status, close_code FROM ".MAIN_DB_PREFIX.$table." as f";
4806
		$sql .= " WHERE fk_soc = ".((int) $this->id);
4807
		if (!empty($late)) {
4808
			$sql .= " AND date_lim_reglement < '".$this->db->idate(dol_now())."'";
4809
		}
4810
		if ($mode == 'supplier') {
4811
			$sql .= " AND entity IN (".getEntity('facture_fourn').")";
4812
		} else {
4813
			$sql .= " AND entity IN (".getEntity('invoice').")";
4814
		}
4815
4816
		dol_syslog("getOutstandingBills", LOG_DEBUG);
4817
		$resql = $this->db->query($sql);
4818
		if ($resql) {
4819
			$outstandingOpened = 0;
4820
			$outstandingTotal = 0;
4821
			$outstandingTotalIncTax = 0;
4822
			$arrayofref = array();
4823
			$arrayofrefopened = array();
4824
			if ($mode == 'supplier') {
4825
				require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
4826
				$tmpobject = new FactureFournisseur($this->db);
4827
			} else {
4828
				require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
4829
				$tmpobject = new Facture($this->db);
4830
			}
4831
			while ($obj = $this->db->fetch_object($resql)) {
4832
				$arrayofref[$obj->rowid] = $obj->ref;
4833
				$tmpobject->id = $obj->rowid;
4834
4835
				if ($obj->status != $tmpobject::STATUS_DRAFT                                           // Not a draft
4836
					&& !($obj->status == $tmpobject::STATUS_ABANDONED && $obj->close_code == 'replaced')  // Not a replaced invoice
4837
					) {
4838
					$outstandingTotal += $obj->total_ht;
4839
					$outstandingTotalIncTax += $obj->total_ttc;
4840
				}
4841
4842
				$remaintopay = 0;
4843
4844
				if ($obj->paye == 0
4845
					&& $obj->status != $tmpobject::STATUS_DRAFT    		// Not a draft
4846
					&& $obj->status != $tmpobject::STATUS_ABANDONED	    // Not abandonned
4847
					&& $obj->status != $tmpobject::STATUS_CLOSED) {		// Not classified as paid
4848
					//$sql .= " AND (status <> 3 OR close_code <> 'abandon')";		// Not abandonned for undefined reason
4849
					$paiement = $tmpobject->getSommePaiement();
4850
					$creditnotes = $tmpobject->getSumCreditNotesUsed();
4851
					$deposits = $tmpobject->getSumDepositsUsed();
4852
4853
					$remaintopay = ($obj->total_ttc - $paiement - $creditnotes - $deposits);
4854
					$outstandingOpened += $remaintopay;
4855
				}
4856
4857
				//if credit note is converted but not used
4858
				// TODO Do this also for customer ?
4859
				if ($mode == 'supplier' && $obj->type == FactureFournisseur::TYPE_CREDIT_NOTE && $tmpobject->isCreditNoteUsed()) {
0 ignored issues
show
Bug introduced by
The method isCreditNoteUsed() does not exist on Facture. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

4859
				if ($mode == 'supplier' && $obj->type == FactureFournisseur::TYPE_CREDIT_NOTE && $tmpobject->/** @scrutinizer ignore-call */ isCreditNoteUsed()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
4860
					$remainingcreditnote = $tmpobject->getSumFromThisCreditNotesNotUsed();
4861
					$remaintopay -= $remainingcreditnote;
4862
					$outstandingOpened -= $remainingcreditnote;
4863
				}
4864
4865
				if ($remaintopay) {
4866
					$arrayofrefopened[$obj->rowid] = $obj->ref;
4867
				}
4868
			}
4869
			return array('opened'=>$outstandingOpened, 'total_ht'=>$outstandingTotal, 'total_ttc'=>$outstandingTotalIncTax, 'refs'=>$arrayofref, 'refsopened'=>$arrayofrefopened); // 'opened' is 'incl taxes'
4870
		} else {
4871
			dol_syslog("Sql error ".$this->db->lasterror, LOG_ERR);
4872
			return array();
4873
		}
4874
	}
4875
4876
	/**
4877
	 * Return label of status customer is prospect/customer
4878
	 *
4879
	 * @return   string        	Label
4880
	 * @see getTypeUrl()
4881
	 */
4882
	public function getLibCustProspStatut()
4883
	{
4884
		return $this->LibCustProspStatut($this->client);
4885
	}
4886
4887
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
4888
	/**
4889
	 *  Return the label of the customer/prospect status
4890
	 *
4891
	 *  @param	int		$status         Id of prospection status
4892
	 *  @return	string          		Label of prospection status
4893
	 */
4894
	public function LibCustProspStatut($status)
4895
	{
4896
		// phpcs:enable
4897
		global $langs;
4898
		$langs->load('companies');
4899
4900
		if ($status == 0) {
4901
			return $langs->trans("NorProspectNorCustomer");
4902
		} elseif ($status == 1) {
4903
			return $langs->trans("Customer");
4904
		} elseif ($status == 2) {
4905
			return $langs->trans("Prospect");
4906
		} elseif ($status == 3) {
4907
			return $langs->trans("ProspectCustomer");
4908
		}
4909
4910
		return '';
4911
	}
4912
4913
4914
	/**
4915
	 *  Create a document onto disk according to template module.
4916
	 *
4917
	 *	@param	string		$modele			Generator to use. Caller must set it to obj->model_pdf or GETPOST('model','alpha') for example.
4918
	 *	@param	Translate	$outputlangs	objet lang a utiliser pour traduction
4919
	 *  @param  int			$hidedetails    Hide details of lines
4920
	 *  @param  int			$hidedesc       Hide description
4921
	 *  @param  int			$hideref        Hide ref
4922
	 *  @param  null|array  $moreparams     Array to provide more information
4923
	 *	@return int        					<0 if KO, >0 if OK
4924
	 */
4925
	public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
4926
	{
4927
		global $conf, $user, $langs;
4928
4929
		if (!empty($moreparams) && !empty($moreparams['use_companybankid'])) {
4930
			$modelpath = "core/modules/bank/doc/";
4931
4932
			include_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
4933
			$companybankaccount = new CompanyBankAccount($this->db);
4934
			$result = $companybankaccount->fetch($moreparams['use_companybankid']);
4935
			if (!$result) {
4936
				dol_print_error($this->db, $companybankaccount->error, $companybankaccount->errors);
4937
			}
4938
			$result = $companybankaccount->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
4939
		} else {
4940
			// Positionne le modele sur le nom du modele a utiliser
4941
			if (!dol_strlen($modele)) {
4942
				if (!empty($conf->global->COMPANY_ADDON_PDF)) {
4943
					$modele = $conf->global->COMPANY_ADDON_PDF;
4944
				} else {
4945
					print $langs->trans("Error")." ".$langs->trans("Error_COMPANY_ADDON_PDF_NotDefined");
4946
					return 0;
4947
				}
4948
			}
4949
4950
			if (!isset($this->bank_account)) {
4951
				require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php';
4952
				$bac = new CompanyBankAccount($this->db);
4953
				$result = $bac->fetch(0, $this->id);
4954
				if ($result > 0) {
4955
					$this->bank_account = $bac;
4956
				} else {
4957
					$this->bank_account = '';
4958
				}
4959
			}
4960
4961
			$modelpath = "core/modules/societe/doc/";
4962
4963
			$result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
4964
		}
4965
4966
		return $result;
4967
	}
4968
4969
4970
	/**
4971
	 * Sets object to supplied categories.
4972
	 *
4973
	 * Deletes object from existing categories not supplied.
4974
	 * Adds it to non existing supplied categories.
4975
	 * Existing categories are left untouch.
4976
	 *
4977
	 * @param 	int[]|int 	$categories 	Category ID or array of Categories IDs
4978
	 * @param 	string 		$type_categ 	Category type ('customer' or 'supplier')
4979
	 * @return	int							<0 if KO, >0 if OK
4980
	 */
4981
	public function setCategories($categories, $type_categ)
4982
	{
4983
		require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
4984
4985
		// Decode type
4986
		if (!in_array($type_categ, array(Categorie::TYPE_CUSTOMER, Categorie::TYPE_SUPPLIER))) {
4987
			dol_syslog(__METHOD__.': Type '.$type_categ.'is an unknown company category type. Done nothing.', LOG_ERR);
4988
			return -1;
4989
		}
4990
4991
		return parent::setCategoriesCommon($categories, $type_categ);
4992
	}
4993
4994
	/**
4995
	 * Sets sales representatives of the thirdparty
4996
	 *
4997
	 * @param 	int[]|int 	$salesrep	 	User ID or array of user IDs
4998
	 * @param   bool        $onlyAdd        Only add (no delete before)
4999
	 * @return	int							<0 if KO, >0 if OK
5000
	 */
5001
	public function setSalesRep($salesrep, $onlyAdd = false)
5002
	{
5003
		global $user;
5004
5005
		// Handle single user
5006
		if (!is_array($salesrep)) {
5007
			$salesrep = array($salesrep);
5008
		}
5009
5010
		$to_del = array(); // Nothing to delete
5011
		$to_add = $salesrep;
5012
		if ($onlyAdd === false) {
5013
			// Get current users
5014
			$existing = $this->getSalesRepresentatives($user, 1);
5015
5016
			// Diff
5017
			if (is_array($existing)) {
5018
				$to_del = array_diff($existing, $salesrep);
5019
				$to_add = array_diff($salesrep, $existing);
5020
			}
5021
		}
5022
5023
		$error = 0;
5024
5025
		// Process
5026
		foreach ($to_del as $del) {
5027
			$this->del_commercial($user, $del);
5028
		}
5029
		foreach ($to_add as $add) {
5030
			$result = $this->add_commercial($user, $add);
5031
			if ($result < 0) {
5032
				$error++;
5033
				break;
5034
			}
5035
		}
5036
5037
		return $error ? -1 : 1;
5038
	}
5039
5040
	/**
5041
	 *    Define third-party type of current company
5042
	 *
5043
	 *    @param	int		$typent_id	third party type rowid in llx_c_typent
5044
	 *    @return	int     			<0 if KO, >0 if OK
5045
	 */
5046
	public function setThirdpartyType($typent_id)
5047
	{
5048
		global $user;
5049
5050
		dol_syslog(__METHOD__, LOG_DEBUG);
5051
5052
		if ($this->id) {
5053
			$result = $this->setValueFrom('fk_typent', $typent_id, '', null, '', '', $user, 'COMPANY_MODIFY');
5054
5055
			if ($result > 0) {
5056
				$this->typent_id = $typent_id;
5057
				$this->typent_code = dol_getIdFromCode($this->db, $this->typent_id, 'c_typent', 'id', 'code');
5058
				return 1;
5059
			} else {
5060
				return -1;
5061
			}
5062
		} else {
5063
			return -1;
5064
		}
5065
	}
5066
5067
	/**
5068
	 * Function used to replace a thirdparty id with another one.
5069
	 * It must be used within a transaction to avoid trouble
5070
	 *
5071
	 * @param 	DoliDB 	$dbs 		Database handler, because function is static we name it $dbs not $db to avoid breaking coding test
5072
	 * @param 	int 	$origin_id 	Old thirdparty id (will be removed)
5073
	 * @param 	int 	$dest_id 	New thirdparty id
5074
	 * @return 	bool				True if success, False if error
5075
	 */
5076
	public static function replaceThirdparty(DoliDB $dbs, $origin_id, $dest_id)
5077
	{
5078
		if ($origin_id == $dest_id) {
5079
			dol_syslog('Error: Try to merge a thirdparty into itself');
5080
			return false;
5081
		}
5082
5083
		/**
5084
		 * Thirdparty commercials cannot be the same in both thirdparties so we look for them and remove some to avoid duplicate.
5085
		 * Because this function is meant to be executed within a transaction, we won't take care of begin/commit.
5086
		 */
5087
		$sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'societe_commerciaux ';
5088
		$sql .= ' WHERE fk_soc = '.(int) $dest_id.' AND fk_user IN ( ';
5089
		$sql .= ' SELECT fk_user ';
5090
		$sql .= ' FROM '.MAIN_DB_PREFIX.'societe_commerciaux ';
5091
		$sql .= ' WHERE fk_soc = '.(int) $origin_id.') ';
5092
5093
		$resql = $dbs->query($sql);
5094
		while ($obj = $dbs->fetch_object($resql)) {
5095
			$dbs->query('DELETE FROM '.MAIN_DB_PREFIX.'societe_commerciaux WHERE rowid = '.((int) $obj->rowid));
5096
		}
5097
5098
		/**
5099
		 * llx_societe_extrafields table must not be here because we don't care about the old thirdparty data
5100
		 * Do not include llx_societe because it will be replaced later
5101
		 */
5102
		$tables = array(
5103
			'societe_address',
5104
			'societe_commerciaux',
5105
			'societe_prices',
5106
			'societe_remise',
5107
			'societe_remise_except',
5108
			'societe_rib'
5109
		);
5110
5111
		return CommonObject::commonReplaceThirdparty($dbs, $origin_id, $dest_id, $tables);
5112
	}
5113
5114
	/**
5115
	 * Sets an accountancy code for a thirdparty.
5116
	 * Also calls COMPANY_MODIFY trigger when modified
5117
	 *
5118
	 * @param   string  $type   It can be only 'buy' or 'sell'
5119
	 * @param   string  $value  Accountancy code
5120
	 * @return  int             <0 KO >0 OK
5121
	 */
5122
	public function setAccountancyCode($type, $value)
5123
	{
5124
		global $user, $langs, $conf;
5125
5126
		$this->db->begin();
5127
5128
		$field = 'accountancy_code_sell';
5129
		if ($type == 'buy') {
5130
			$field = 'accountancy_code_buy';
5131
		} elseif ($type == 'sell') {
5132
			$field = 'accountancy_code_sell';
5133
		} else {
5134
			return -1;
5135
		}
5136
5137
		$sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET ";
5138
		$sql .= $field." = '".$this->db->escape($value)."'";
5139
		$sql .= " WHERE rowid = ".((int) $this->id);
5140
5141
		dol_syslog(get_class($this)."::".__FUNCTION__, LOG_DEBUG);
5142
		$resql = $this->db->query($sql);
5143
5144
		if ($resql) {
5145
			// Call triggers
5146
			include_once DOL_DOCUMENT_ROOT.'/core/class/interfaces.class.php';
5147
			$interface = new Interfaces($this->db);
5148
			$result = $interface->run_triggers('COMPANY_MODIFY', $this, $user, $langs, $conf);
5149
			if ($result < 0) {
5150
				$this->errors = $interface->errors;
5151
				$this->db->rollback();
5152
				return -1;
5153
			}
5154
			// End call triggers
5155
5156
			$this->$field = $value;
5157
5158
			$this->db->commit();
5159
			return 1;
5160
		} else {
5161
			$this->error = $this->db->lasterror();
5162
			$this->db->rollback();
5163
			return -1;
5164
		}
5165
	}
5166
5167
	/**
5168
	 *	Function to get partnerships array
5169
	 *
5170
	 *  @param		string		$mode		'member' or 'thirdparty'
5171
	 *	@return		int						<0 if KO, >0 if OK
5172
	 */
5173
	public function fetchPartnerships($mode)
5174
	{
5175
		global $langs;
5176
5177
		require_once DOL_DOCUMENT_ROOT.'/partnership/class/partnership.class.php';
5178
5179
5180
		$this->partnerships[] = array();
5181
5182
		return 1;
5183
	}
5184
}
5185