1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* Copyright (C) 2004-2005 Rodolphe Quiedeville <[email protected]> |
4
|
|
|
* Copyright (C) 2005-2012 Regis Houssin <[email protected]> |
5
|
|
|
* Copyright (C) 2010-2015 Juanjo Menent <[email protected]> |
6
|
|
|
* Copyright (C) 2010-2014 Laurent Destailleur <[email protected]> |
7
|
|
|
* Copyright (C) 2014-2016 Ferran Marcet <[email protected]> |
8
|
|
|
* Copyright (C) 2018 Nicolas ZABOURI <[email protected]> |
9
|
|
|
* Copyright (C) 2019 JC Prieto <[email protected]><[email protected]> |
10
|
|
|
* Copyright (C) 2024 MDW <[email protected]> |
11
|
|
|
* Copyright (C) 2024 Frédéric France <[email protected]> |
12
|
|
|
* Copyright (C) 2024 Rafael San José <[email protected]> |
13
|
|
|
* |
14
|
|
|
* This program is free software; you can redistribute it and/or modify |
15
|
|
|
* it under the terms of the GNU General Public License as published by |
16
|
|
|
* the Free Software Foundation; either version 3 of the License, or |
17
|
|
|
* (at your option) any later version. |
18
|
|
|
* |
19
|
|
|
* This program is distributed in the hope that it will be useful, |
20
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
21
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22
|
|
|
* GNU General Public License for more details. |
23
|
|
|
* |
24
|
|
|
* You should have received a copy of the GNU General Public License |
25
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. |
26
|
|
|
*/ |
27
|
|
|
|
28
|
|
|
namespace Dolibarr\Code\Compta\Classes; |
29
|
|
|
|
30
|
|
|
use Dolibarr\Code\Fourn\Classes\FactureFournisseur; |
31
|
|
|
use Dolibarr\Code\Fourn\Classes\PaiementFourn; |
32
|
|
|
use Dolibarr\Code\Salaries\Classes\PaymentSalary; |
33
|
|
|
use Dolibarr\Code\Salaries\Classes\Salary; |
34
|
|
|
use Dolibarr\Code\User\Classes\User; |
35
|
|
|
use Dolibarr\Core\Base\CommonObject; |
36
|
|
|
use Dolibarr\Code\Societe\Classes\Societe; |
37
|
|
|
use DoliDB; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* \file htdocs/compta/prelevement/class/bonprelevement.class.php |
41
|
|
|
* \ingroup prelevement |
42
|
|
|
* \brief File of withdrawal receipts class |
43
|
|
|
*/ |
44
|
|
|
|
45
|
|
|
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/bank.lib.php'; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Class to manage withdrawal receipts |
49
|
|
|
* Model PrelevementBon |
50
|
|
|
*/ |
51
|
|
|
class BonPrelevement extends CommonObject |
52
|
|
|
{ |
53
|
|
|
/** |
54
|
|
|
* @var string ID to identify managed object |
55
|
|
|
*/ |
56
|
|
|
public $element = 'widthdraw'; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @var string Name of table without prefix where object is stored |
60
|
|
|
*/ |
61
|
|
|
public $table_element = 'prelevement_bons'; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png |
65
|
|
|
*/ |
66
|
|
|
public $picto = 'payment'; |
67
|
|
|
|
68
|
|
|
public $date_echeance; |
69
|
|
|
public $raison_sociale; |
70
|
|
|
public $reference_remise; |
71
|
|
|
public $emetteur_code_guichet; |
72
|
|
|
public $emetteur_numero_compte; |
73
|
|
|
public $emetteur_code_banque; |
74
|
|
|
public $emetteur_number_key; |
75
|
|
|
public $sepa_xml_pti_in_ctti; |
76
|
|
|
|
77
|
|
|
public $emetteur_iban; |
78
|
|
|
public $emetteur_bic; |
79
|
|
|
public $emetteur_ics; |
80
|
|
|
|
81
|
|
|
public $user_trans; |
82
|
|
|
public $user_credit; |
83
|
|
|
|
84
|
|
|
public $total; |
85
|
|
|
public $fetched; |
86
|
|
|
public $labelStatus = array(); |
87
|
|
|
|
88
|
|
|
public $factures = array(); |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* @var array<int,string> |
92
|
|
|
*/ |
93
|
|
|
public $methodes_trans = array(); |
94
|
|
|
|
95
|
|
|
public $invoice_in_error = array(); |
96
|
|
|
public $thirdparty_in_error = array(); |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* @var resource Handler of the file for direct debit or credit transfer order |
100
|
|
|
*/ |
101
|
|
|
public $file; |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* @var string filename |
105
|
|
|
*/ |
106
|
|
|
public $filename; |
107
|
|
|
|
108
|
|
|
const STATUS_DRAFT = 0; |
109
|
|
|
const STATUS_TRANSFERED = 1; |
110
|
|
|
const STATUS_CREDITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type |
111
|
|
|
const STATUS_DEBITED = 2; // STATUS_CREDITED and STATUS_DEBITED is same. Difference is in ->type |
112
|
|
|
|
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* 'type' field format: |
116
|
|
|
* 'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]', |
117
|
|
|
* 'select' (list of values are in 'options'), |
118
|
|
|
* 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:Sortfield]]]]', |
119
|
|
|
* 'chkbxlst:...', |
120
|
|
|
* 'varchar(x)', |
121
|
|
|
* 'text', 'text:none', 'html', |
122
|
|
|
* 'double(24,8)', 'real', 'price', |
123
|
|
|
* 'date', 'datetime', 'timestamp', 'duration', |
124
|
|
|
* 'boolean', 'checkbox', 'radio', 'array', |
125
|
|
|
* 'mail', 'phone', 'url', 'password', 'ip' |
126
|
|
|
* Note: Filter must be a Dolibarr filter syntax string. Example: "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.status:!=:0) or (t.nature:is:NULL)" |
127
|
|
|
* 'label' the translation key. |
128
|
|
|
* 'picto' is code of a picto to show before value in forms |
129
|
|
|
* 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM' or 'isModEnabled("multicurrency")' ...) |
130
|
|
|
* 'position' is the sort order of field. |
131
|
|
|
* 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). |
132
|
|
|
* '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) |
133
|
|
|
* 'noteditable' says if field is not editable (1 or 0) |
134
|
|
|
* 'alwayseditable' says if field can be modified also when status is not draft ('1' or '0') |
135
|
|
|
* '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. |
136
|
|
|
* 'index' if we want an index in database. |
137
|
|
|
* 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...). |
138
|
|
|
* 'searchall' is 1 if we want to search in this field when making a search from the quick search button. |
139
|
|
|
* 'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage) |
140
|
|
|
* '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: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200' |
141
|
|
|
* 'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click. |
142
|
|
|
* 'showoncombobox' if value of the field must be visible into the label of the combobox that list record |
143
|
|
|
* '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. |
144
|
|
|
* 'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar' |
145
|
|
|
* 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. |
146
|
|
|
* 'comment' is not used. You can store here any text of your choice. It is not used by application. |
147
|
|
|
* 'validate' is 1 if need to validate with $this->validateField() |
148
|
|
|
* 'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value) |
149
|
|
|
* |
150
|
|
|
* Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. |
151
|
|
|
*/ |
152
|
|
|
|
153
|
|
|
// BEGIN MODULEBUILDER PROPERTIES |
154
|
|
|
/** |
155
|
|
|
* @var array<string,array{type:string,label:string,enabled:int<0,2>|string,position:int,notnull?:int,visible:int,noteditable?:int,default?:string,index?:int,foreignkey?:string,searchall?:int,isameasure?:int,css?:string,csslist?:string,help?:string,showoncombobox?:int,disabled?:int,arrayofkeyval?:array<int,string>,comment?:string}> Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. |
|
|
|
|
156
|
|
|
*/ |
157
|
|
|
public $fields = array( |
158
|
|
|
'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 10, 'notnull' => 1, 'visible' => 0,), |
159
|
|
|
'ref' => array('type' => 'varchar(12)', 'label' => 'Ref', 'enabled' => 1, 'position' => 15, 'notnull' => 0, 'visible' => -1, 'csslist' => 'tdoverflowmax150', 'showoncombobox' => 1,), |
160
|
|
|
'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'position' => 25, 'notnull' => 0, 'visible' => -1,), |
161
|
|
|
'amount' => array('type' => 'double(24,8)', 'label' => 'Amount', 'enabled' => 1, 'position' => 30, 'notnull' => 0, 'visible' => -1,), |
162
|
|
|
'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'position' => 500, 'notnull' => 0, 'visible' => -1, 'arrayofkeyval' => array(0 => 'Wait', 1 => 'Transfered', 2 => 'Credited')), |
163
|
|
|
'credite' => array('type' => 'smallint(6)', 'label' => 'Credite', 'enabled' => 1, 'position' => 40, 'notnull' => 0, 'visible' => -1,), |
164
|
|
|
'note' => array('type' => 'text', 'label' => 'Note', 'enabled' => 1, 'position' => 45, 'notnull' => 0, 'visible' => -1,), |
165
|
|
|
'date_trans' => array('type' => 'datetime', 'label' => 'Datetrans', 'enabled' => 1, 'position' => 50, 'notnull' => 0, 'visible' => -1,), |
166
|
|
|
'method_trans' => array('type' => 'smallint(6)', 'label' => 'Methodtrans', 'enabled' => 1, 'position' => 55, 'notnull' => 0, 'visible' => -1,), |
167
|
|
|
'fk_user_trans' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fkusertrans', 'enabled' => 1, 'position' => 60, 'notnull' => 0, 'visible' => -1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150',), |
168
|
|
|
'date_credit' => array('type' => 'datetime', 'label' => 'Datecredit', 'enabled' => 1, 'position' => 65, 'notnull' => 0, 'visible' => -1,), |
169
|
|
|
'fk_user_credit' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fkusercredit', 'enabled' => 1, 'position' => 70, 'notnull' => 0, 'visible' => -1, 'css' => 'maxwidth500 widthcentpercentminusxx', 'csslist' => 'tdoverflowmax150',), |
170
|
|
|
'type' => array('type' => 'varchar(16)', 'label' => 'Type', 'enabled' => 1, 'position' => 75, 'notnull' => 0, 'visible' => -1,), |
171
|
|
|
'fk_bank_account' => array('type' => 'integer', 'label' => 'Fkbankaccount', 'enabled' => 1, 'position' => 80, 'notnull' => 0, 'visible' => -1, 'css' => 'maxwidth500 widthcentpercentminusxx',), |
172
|
|
|
); |
173
|
|
|
public $rowid; |
174
|
|
|
public $ref; |
175
|
|
|
public $datec; |
176
|
|
|
public $amount; |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* @var int Status |
180
|
|
|
* @deprecated |
181
|
|
|
*/ |
182
|
|
|
public $statut; |
183
|
|
|
/** |
184
|
|
|
* @var int Status |
185
|
|
|
*/ |
186
|
|
|
public $status; |
187
|
|
|
|
188
|
|
|
public $credite; |
189
|
|
|
public $note; |
190
|
|
|
public $date_trans; |
191
|
|
|
/** |
192
|
|
|
* @var int Current transport method, index to $methodes_trans |
193
|
|
|
*/ |
194
|
|
|
public $method_trans; |
195
|
|
|
public $fk_user_trans; |
196
|
|
|
public $date_credit; |
197
|
|
|
public $fk_user_credit; |
198
|
|
|
public $type; |
199
|
|
|
public $fk_bank_account; |
200
|
|
|
// END MODULEBUILDER PROPERTIES |
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* Constructor |
204
|
|
|
* |
205
|
|
|
* @param DoliDB $db Database handler |
206
|
|
|
*/ |
207
|
|
|
public function __construct($db) |
208
|
|
|
{ |
209
|
|
|
$this->db = $db; |
210
|
|
|
|
211
|
|
|
$this->filename = ''; |
212
|
|
|
|
213
|
|
|
$this->date_echeance = dol_now(); |
214
|
|
|
$this->raison_sociale = ""; |
215
|
|
|
$this->reference_remise = ""; |
216
|
|
|
|
217
|
|
|
$this->emetteur_code_guichet = ""; |
218
|
|
|
$this->emetteur_numero_compte = ""; |
219
|
|
|
$this->emetteur_code_banque = ""; |
220
|
|
|
$this->emetteur_number_key = ""; |
221
|
|
|
$this->sepa_xml_pti_in_ctti = false; |
222
|
|
|
|
223
|
|
|
$this->emetteur_iban = ""; |
224
|
|
|
$this->emetteur_bic = ""; |
225
|
|
|
$this->emetteur_ics = ""; |
226
|
|
|
|
227
|
|
|
$this->factures = array(); |
228
|
|
|
|
229
|
|
|
$this->methodes_trans = array(0 => 'Internet', 2 => 'Email', 3 => 'Api'); |
230
|
|
|
|
231
|
|
|
$this->fetched = 0; |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
235
|
|
|
/** |
236
|
|
|
* Add invoice to withdrawal |
237
|
|
|
* |
238
|
|
|
* @param int $invoice_id ID of invoice to add or ID of salary to add |
239
|
|
|
* @param int $client_id id invoice customer |
240
|
|
|
* @param string $client_nom customer name |
241
|
|
|
* @param int $amount amount of invoice |
242
|
|
|
* @param string $code_banque code of bank withdrawal |
243
|
|
|
* @param string $code_guichet code of bank's office |
244
|
|
|
* @param string $number bank account number |
245
|
|
|
* @param string $number_key number key of account number |
246
|
|
|
* @param string $type 'debit-order' or 'bank-transfer' |
247
|
|
|
* @param string $sourcetype 'salary' for salary, '' for invoices |
248
|
|
|
* @return int >0 if OK, <0 if KO |
249
|
|
|
*/ |
250
|
|
|
public function AddFacture($invoice_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $type = 'debit-order', $sourcetype = '') |
251
|
|
|
{ |
252
|
|
|
// phpcs:enable |
253
|
|
|
$result = 0; |
254
|
|
|
$line_id = 0; |
255
|
|
|
|
256
|
|
|
// Add lines into prelevement_lignes |
257
|
|
|
$result = $this->addline($line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $sourcetype); |
258
|
|
|
|
259
|
|
|
|
260
|
|
|
if ($result == 0) { |
261
|
|
|
if ($line_id > 0) { |
262
|
|
|
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement ("; |
263
|
|
|
if ($type != 'bank-transfer') { |
264
|
|
|
$sql .= "fk_facture"; |
265
|
|
|
} else { |
266
|
|
|
if ($sourcetype == 'salary') { |
267
|
|
|
$sql .= "fk_salary"; |
268
|
|
|
} else { |
269
|
|
|
$sql .= "fk_facture_fourn"; |
270
|
|
|
} |
271
|
|
|
} |
272
|
|
|
$sql .= ",fk_prelevement_lignes"; |
273
|
|
|
$sql .= ") VALUES ("; |
274
|
|
|
$sql .= ((int) $invoice_id); |
275
|
|
|
$sql .= ", " . ((int) $line_id); |
276
|
|
|
$sql .= ")"; |
277
|
|
|
|
278
|
|
|
if ($this->db->query($sql)) { |
279
|
|
|
$result = 0; |
280
|
|
|
} else { |
281
|
|
|
$result = -1; |
282
|
|
|
$this->errors[] = get_only_class($this) . "::AddFacture " . $this->db->lasterror; |
283
|
|
|
dol_syslog(get_only_class($this) . "::AddFacture Error $result"); |
284
|
|
|
} |
285
|
|
|
} else { |
286
|
|
|
$result = -2; |
287
|
|
|
$this->errors[] = get_only_class($this) . "::AddFacture linedid Empty"; |
288
|
|
|
dol_syslog(get_only_class($this) . "::AddFacture Error $result"); |
289
|
|
|
} |
290
|
|
|
} else { |
291
|
|
|
$result = -3; |
292
|
|
|
dol_syslog(get_only_class($this) . "::AddFacture Error $result"); |
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
return $result; |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* Add line to withdrawal |
300
|
|
|
* |
301
|
|
|
* @param int $line_id ID of line added (returned parameter) |
302
|
|
|
* @param int $client_id ID of thirdparty for invoices, ID of user for salaries |
303
|
|
|
* @param string $client_nom customer name |
304
|
|
|
* @param int $amount amount of invoice |
305
|
|
|
* @param string $code_banque code of bank withdrawal |
306
|
|
|
* @param string $code_guichet code of bank's office |
307
|
|
|
* @param string $number bank account number |
308
|
|
|
* @param string $number_key number key of account number |
309
|
|
|
* @param string $sourcetype 'salary' for salary, '' for invoices |
310
|
|
|
* @return int >0 if OK, <0 if KO |
311
|
|
|
*/ |
312
|
|
|
public function addline(&$line_id, $client_id, $client_nom, $amount, $code_banque, $code_guichet, $number, $number_key, $sourcetype = '') |
313
|
|
|
{ |
314
|
|
|
$result = -1; |
315
|
|
|
$concat = 0; // ??? what is this for. Seems not used. |
316
|
|
|
|
317
|
|
|
if ($concat == 1) { |
318
|
|
|
/* |
319
|
|
|
* We aggregate the lines |
320
|
|
|
*/ |
321
|
|
|
$sql = "SELECT rowid"; |
322
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_lignes"; |
323
|
|
|
$sql .= " WHERE fk_prelevement_bons = " . ((int) $this->id); |
324
|
|
|
if ($sourcetype == 'salary') { |
325
|
|
|
$sql .= " AND fk_soc = " . ((int) $client_id); |
326
|
|
|
} else { |
327
|
|
|
$sql .= " AND fk_user = " . ((int) $client_id); |
328
|
|
|
} |
329
|
|
|
$sql .= " AND code_banque = '" . $this->db->escape($code_banque) . "'"; |
330
|
|
|
$sql .= " AND code_guichet = '" . $this->db->escape($code_guichet) . "'"; |
331
|
|
|
$sql .= " AND number = '" . $this->db->escape($number) . "'"; |
332
|
|
|
|
333
|
|
|
$resql = $this->db->query($sql); |
334
|
|
|
if ($resql) { |
335
|
|
|
$num = $this->db->num_rows($resql); |
336
|
|
|
} else { |
337
|
|
|
$result = -1; |
338
|
|
|
} |
339
|
|
|
} else { |
340
|
|
|
/* |
341
|
|
|
* No aggregate |
342
|
|
|
*/ |
343
|
|
|
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_lignes ("; |
344
|
|
|
$sql .= "fk_prelevement_bons"; |
345
|
|
|
$sql .= ", fk_soc"; |
346
|
|
|
$sql .= ", client_nom"; |
347
|
|
|
$sql .= ", amount"; |
348
|
|
|
$sql .= ", code_banque"; |
349
|
|
|
$sql .= ", code_guichet"; |
350
|
|
|
$sql .= ", number"; |
351
|
|
|
$sql .= ", cle_rib"; |
352
|
|
|
$sql .= ($sourcetype == 'salary' ? ", fk_user" : ""); |
353
|
|
|
$sql .= ") VALUES ("; |
354
|
|
|
$sql .= $this->id; |
355
|
|
|
$sql .= ", " . (($sourcetype != 'salary') ? ((int) $client_id) : "0"); // fk_soc can't be null |
356
|
|
|
$sql .= ", '" . $this->db->escape($client_nom) . "'"; |
357
|
|
|
$sql .= ", " . ((float) price2num($amount)); |
358
|
|
|
$sql .= ", '" . $this->db->escape($code_banque) . "'"; |
359
|
|
|
$sql .= ", '" . $this->db->escape($code_guichet) . "'"; |
360
|
|
|
$sql .= ", '" . $this->db->escape($number) . "'"; |
361
|
|
|
$sql .= ", '" . $this->db->escape($number_key) . "'"; |
362
|
|
|
$sql .= (($sourcetype == 'salary') ? ", " . ((int) $client_id) : ''); |
363
|
|
|
$sql .= ")"; |
364
|
|
|
if ($this->db->query($sql)) { |
365
|
|
|
$line_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "prelevement_lignes"); |
366
|
|
|
$result = 0; |
367
|
|
|
} else { |
368
|
|
|
$this->errors[] = get_only_class($this) . "::addline Error -2 " . $this->db->lasterror; |
369
|
|
|
dol_syslog(get_only_class($this) . "::addline Error -2"); |
370
|
|
|
$result = -2; |
371
|
|
|
} |
372
|
|
|
} |
373
|
|
|
|
374
|
|
|
return $result; |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
/** |
378
|
|
|
* Return error string |
379
|
|
|
* |
380
|
|
|
* @param int $error Id of error |
381
|
|
|
* @return string Error string |
382
|
|
|
*/ |
383
|
|
|
public function getErrorString($error) |
384
|
|
|
{ |
385
|
|
|
global $langs; |
386
|
|
|
|
387
|
|
|
$errors = array(); |
388
|
|
|
|
389
|
|
|
$errors[1027] = $langs->trans("DateInvalid"); |
390
|
|
|
|
391
|
|
|
return $errors[abs($error)]; |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
/** |
395
|
|
|
* Get object and lines from database |
396
|
|
|
* |
397
|
|
|
* @param int $rowid Id of object to load |
398
|
|
|
* @param string $ref Ref of direct debit |
399
|
|
|
* @return int >0 if OK, <0 if KO |
400
|
|
|
*/ |
401
|
|
|
public function fetch($rowid, $ref = '') |
402
|
|
|
{ |
403
|
|
|
$sql = "SELECT p.rowid, p.ref, p.amount, p.note"; |
404
|
|
|
$sql .= ", p.datec as dc"; |
405
|
|
|
$sql .= ", p.date_trans as date_trans"; |
406
|
|
|
$sql .= ", p.method_trans, p.fk_user_trans"; |
407
|
|
|
$sql .= ", p.date_credit as date_credit"; |
408
|
|
|
$sql .= ", p.fk_user_credit"; |
409
|
|
|
$sql .= ", p.type"; |
410
|
|
|
$sql .= ", p.fk_bank_account"; |
411
|
|
|
$sql .= ", p.statut as status"; |
412
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as p"; |
413
|
|
|
$sql .= " WHERE p.entity IN (" . getEntity('invoice') . ")"; |
414
|
|
|
if ($rowid > 0) { |
415
|
|
|
$sql .= " AND p.rowid = " . ((int) $rowid); |
416
|
|
|
} else { |
417
|
|
|
$sql .= " AND p.ref = '" . $this->db->escape($ref) . "'"; |
418
|
|
|
} |
419
|
|
|
|
420
|
|
|
dol_syslog(get_only_class($this) . "::fetch", LOG_DEBUG); |
421
|
|
|
$result = $this->db->query($sql); |
422
|
|
|
if ($result) { |
423
|
|
|
if ($this->db->num_rows($result)) { |
424
|
|
|
$obj = $this->db->fetch_object($result); |
425
|
|
|
|
426
|
|
|
$this->id = $obj->rowid; |
427
|
|
|
$this->ref = $obj->ref; |
428
|
|
|
$this->amount = $obj->amount; |
429
|
|
|
$this->note = $obj->note; |
430
|
|
|
$this->datec = $this->db->jdate($obj->dc); |
431
|
|
|
|
432
|
|
|
$this->date_trans = $this->db->jdate($obj->date_trans); |
433
|
|
|
$this->method_trans = $obj->method_trans; |
434
|
|
|
$this->user_trans = $obj->fk_user_trans; |
435
|
|
|
|
436
|
|
|
$this->date_credit = $this->db->jdate($obj->date_credit); |
437
|
|
|
$this->user_credit = $obj->fk_user_credit; |
438
|
|
|
|
439
|
|
|
$this->type = $obj->type; |
440
|
|
|
$this->fk_bank_account = $obj->fk_bank_account; |
441
|
|
|
|
442
|
|
|
$this->status = $obj->status; |
443
|
|
|
if (empty($this->status)) { // Value is sometimes null in database |
444
|
|
|
$this->status = 0; |
445
|
|
|
} |
446
|
|
|
$this->statut = $this->status; // For backward compatibility |
447
|
|
|
|
448
|
|
|
$this->fetched = 1; |
449
|
|
|
|
450
|
|
|
return 1; |
451
|
|
|
} else { |
452
|
|
|
dol_syslog(get_only_class($this) . "::Fetch Erreur aucune ligne retournee"); |
453
|
|
|
return -1; |
454
|
|
|
} |
455
|
|
|
} else { |
456
|
|
|
return -2; |
457
|
|
|
} |
458
|
|
|
} |
459
|
|
|
|
460
|
|
|
/** |
461
|
|
|
* Update object into database |
462
|
|
|
* |
463
|
|
|
* @param User $user User that modifies |
464
|
|
|
* @param int $notrigger 0=launch triggers after, 1=disable triggers |
465
|
|
|
* @return int Return integer <0 if KO, >0 if OK |
466
|
|
|
*/ |
467
|
|
|
public function update(User $user, $notrigger = 0) |
468
|
|
|
{ |
469
|
|
|
return $this->updateCommon($user, $notrigger); |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
473
|
|
|
/** |
474
|
|
|
* Set direct debit or credit transfer order to "paid" status. |
475
|
|
|
* Then create the payment for each invoice or salary of the prelemevement_bon. |
476
|
|
|
* |
477
|
|
|
* @param User $user Id of user |
478
|
|
|
* @param int $date date of action |
479
|
|
|
* @param string $type 'salary' for type=salary |
480
|
|
|
* @return int >0 if OK, <0 if KO |
481
|
|
|
*/ |
482
|
|
|
public function set_infocredit($user, $date, $type = '') |
483
|
|
|
{ |
484
|
|
|
// phpcs:enable |
485
|
|
|
global $conf, $langs; |
486
|
|
|
|
487
|
|
|
$error = 0; |
488
|
|
|
|
489
|
|
|
if ($this->fetched == 1) { |
490
|
|
|
if ($date < $this->date_trans) { |
491
|
|
|
$langs->load("errors"); |
492
|
|
|
$this->error = $langs->trans('ErrorDateOfMovementLowerThanDateOfFileTransmission'); |
493
|
|
|
dol_syslog("bon-prelevment::set_infocredit 1027 " . $this->error); |
494
|
|
|
return -1027; |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
$this->db->begin(); |
498
|
|
|
|
499
|
|
|
$sql = " UPDATE " . MAIN_DB_PREFIX . "prelevement_bons"; |
500
|
|
|
$sql .= " SET fk_user_credit = " . ((int) $user->id); |
501
|
|
|
$sql .= ", statut = " . self::STATUS_CREDITED; |
502
|
|
|
$sql .= ", date_credit = '" . $this->db->idate($date) . "'"; |
503
|
|
|
$sql .= " WHERE rowid = " . ((int) $this->id); |
504
|
|
|
$sql .= " AND entity = " . ((int) $conf->entity); |
505
|
|
|
$sql .= " AND statut = " . self::STATUS_TRANSFERED; |
506
|
|
|
|
507
|
|
|
$resql = $this->db->query($sql); |
508
|
|
|
if ($resql) { |
509
|
|
|
$langs->load('withdrawals'); |
510
|
|
|
$subject = $langs->trans("InfoCreditSubject", $this->ref); |
511
|
|
|
$message = $langs->trans("InfoCreditMessage", $this->ref, dol_print_date($date, 'dayhour')); |
512
|
|
|
|
513
|
|
|
// Add payment of withdrawal into bank |
514
|
|
|
$fk_bank_account = $this->fk_bank_account; |
515
|
|
|
if (empty($fk_bank_account)) { |
516
|
|
|
$fk_bank_account = ($this->type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT')); |
517
|
|
|
} |
518
|
|
|
|
519
|
|
|
$facs = array(); |
520
|
|
|
$amounts = array(); |
521
|
|
|
$amountsperthirdparty = array(); |
522
|
|
|
|
523
|
|
|
$facs = $this->getListInvoices(1, $type); |
524
|
|
|
if ($this->error) { |
525
|
|
|
$error++; |
526
|
|
|
} |
527
|
|
|
|
528
|
|
|
// Loop on each invoice or salary. |
529
|
|
|
// $facs should be array(0=>id, 1=>amount requested) |
530
|
|
|
$num = count($facs); |
531
|
|
|
for ($i = 0; $i < $num; $i++) { |
532
|
|
|
if ($this->type == 'bank-transfer') { |
533
|
|
|
if ($type == 'salary') { |
534
|
|
|
$fac = new Salary($this->db); |
535
|
|
|
} else { |
536
|
|
|
$fac = new FactureFournisseur($this->db); |
537
|
|
|
} |
538
|
|
|
} else { |
539
|
|
|
$fac = new Facture($this->db); |
540
|
|
|
} |
541
|
|
|
|
542
|
|
|
$result = $fac->fetch($facs[$i][0]); |
543
|
|
|
|
544
|
|
|
$amounts[$fac->id] = $facs[$i][1]; |
545
|
|
|
if ($this->type == 'bank-transfer') { |
546
|
|
|
if ($type == 'salary') { |
547
|
|
|
$amountsperthirdparty[$fac->fk_user][$fac->id] = $facs[$i][1]; |
548
|
|
|
} else { |
549
|
|
|
$amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1]; |
550
|
|
|
} |
551
|
|
|
} else { |
552
|
|
|
$amountsperthirdparty[$fac->socid][$fac->id] = $facs[$i][1]; |
553
|
|
|
} |
554
|
|
|
|
555
|
|
|
$totalpaid = $fac->getSommePaiement(); |
556
|
|
|
$totalcreditnotes = 0; |
557
|
|
|
if (method_exists($fac, 'getSumCreditNotesUsed')) { |
558
|
|
|
$totalcreditnotes = $fac->getSumCreditNotesUsed(); |
|
|
|
|
559
|
|
|
} |
560
|
|
|
$totaldeposits = 0; |
561
|
|
|
if (method_exists($fac, 'getSumDepositsUsed')) { |
562
|
|
|
$totaldeposits = $fac->getSumDepositsUsed(); |
|
|
|
|
563
|
|
|
} |
564
|
|
|
$alreadypayed = $totalpaid + $totalcreditnotes + $totaldeposits; |
565
|
|
|
|
566
|
|
|
// Set the main document to pay with status Paid. |
567
|
|
|
// @TODO Move this after creation of payments done after |
568
|
|
|
$amountofdocument = $fac->total_ttc; |
569
|
|
|
if ($type == 'salary') { |
570
|
|
|
$amountofdocument = $fac->amount; |
571
|
|
|
} |
572
|
|
|
if (price2num($alreadypayed + $facs[$i][1], 'MT') == price2num($amountofdocument, 'MT')) { |
573
|
|
|
$result = $fac->setPaid($user); |
574
|
|
|
if ($result < 0) { |
575
|
|
|
$this->error = $fac->error; |
576
|
|
|
$this->errors = $fac->errors; |
577
|
|
|
} |
578
|
|
|
} |
579
|
|
|
} |
580
|
|
|
|
581
|
|
|
// Make one payment per customer or employee |
582
|
|
|
foreach ($amountsperthirdparty as $thirdpartyid => $cursoramounts) { |
583
|
|
|
if ($this->type == 'bank-transfer') { |
584
|
|
|
if ($type == 'salary') { |
585
|
|
|
$paiement = new PaymentSalary($this->db); |
586
|
|
|
} else { |
587
|
|
|
$paiement = new PaiementFourn($this->db); |
588
|
|
|
} |
589
|
|
|
} else { |
590
|
|
|
$paiement = new Paiement($this->db); |
591
|
|
|
} |
592
|
|
|
$paiement->datepaye = $date; |
593
|
|
|
$paiement->amounts = $cursoramounts; // Array with detail of dispatching of payments for each invoice |
594
|
|
|
|
595
|
|
|
if ($this->type == 'bank-transfer') { |
596
|
|
|
if ($type == 'salary') { |
597
|
|
|
$paiement->datep = $date; |
|
|
|
|
598
|
|
|
|
599
|
|
|
$paiement->paiementid = 2; |
|
|
|
|
600
|
|
|
$paiement->fk_typepayment = 2; |
|
|
|
|
601
|
|
|
$paiement->paiementcode = 'VIR'; |
|
|
|
|
602
|
|
|
} else { |
603
|
|
|
$paiement->paiementid = 2; |
604
|
|
|
$paiement->paiementcode = 'VIR'; |
605
|
|
|
} |
606
|
|
|
} else { |
607
|
|
|
$paiement->paiementid = 3; |
608
|
|
|
$paiement->paiementcode = 'PRE'; |
609
|
|
|
} |
610
|
|
|
|
611
|
|
|
$paiement->num_payment = $this->ref; // Set ref of direct debit note |
612
|
|
|
$paiement->id_prelevement = $this->id; |
|
|
|
|
613
|
|
|
|
614
|
|
|
$result = $paiement->create($user); // This use ->paiementid, that is ID of payment mode |
615
|
|
|
|
616
|
|
|
if ($result < 0) { |
617
|
|
|
$error++; |
618
|
|
|
$this->error = $paiement->error; |
619
|
|
|
$this->errors = $paiement->errors; |
620
|
|
|
dol_syslog(get_only_class($this) . "::set_infocredit AddPayment Error " . $this->error); |
621
|
|
|
} else { |
622
|
|
|
if ($this->type == 'bank-transfer') { |
623
|
|
|
if ($type == 'salary') { |
624
|
|
|
$modeforaddpayment = 'payment_salary'; |
625
|
|
|
$labelforaddpayment = '(SalaryPayment)'; |
626
|
|
|
$addbankurl = 'credit-transfer'; |
627
|
|
|
} else { |
628
|
|
|
$modeforaddpayment = 'payment_supplier'; |
629
|
|
|
$labelforaddpayment = '(SupplierInvoicePayment)'; |
630
|
|
|
$addbankurl = 'credit-transfer'; |
631
|
|
|
} |
632
|
|
|
} else { |
633
|
|
|
$modeforaddpayment = 'payment'; |
634
|
|
|
$labelforaddpayment = '(CustomerInvoicePayment)'; |
635
|
|
|
$addbankurl = 'direct-debit'; // = 'directdebit' |
636
|
|
|
} |
637
|
|
|
|
638
|
|
|
$result = $paiement->addPaymentToBank($user, $modeforaddpayment, $labelforaddpayment, $fk_bank_account, '', '', 0, '', $addbankurl); |
639
|
|
|
|
640
|
|
|
if ($result < 0) { |
641
|
|
|
$error++; |
642
|
|
|
$this->error = $paiement->error; |
643
|
|
|
$this->errors = $paiement->errors; |
644
|
|
|
dol_syslog(get_only_class($this) . "::set_infocredit AddPaymentToBank Error " . $this->error); |
645
|
|
|
} |
646
|
|
|
} |
647
|
|
|
} |
648
|
|
|
|
649
|
|
|
// Update withdrawal line |
650
|
|
|
// TODO: Translate to ligneprelevement.class.php |
651
|
|
|
if (!$error) { |
652
|
|
|
$sql = " UPDATE " . MAIN_DB_PREFIX . "prelevement_lignes"; |
653
|
|
|
$sql .= " SET statut = 2"; |
654
|
|
|
$sql .= " WHERE fk_prelevement_bons = " . ((int) $this->id); |
655
|
|
|
|
656
|
|
|
if (!$this->db->query($sql)) { |
657
|
|
|
dol_syslog(get_only_class($this) . "::set_infocredit Update lines Error"); |
658
|
|
|
$error++; |
659
|
|
|
} |
660
|
|
|
} |
661
|
|
|
} else { |
662
|
|
|
$this->error = $this->db->lasterror(); |
663
|
|
|
dol_syslog(get_only_class($this) . "::set_infocredit Update Bons Error"); |
664
|
|
|
$error++; |
665
|
|
|
} |
666
|
|
|
|
667
|
|
|
// End of procedure |
668
|
|
|
if ($error == 0) { |
669
|
|
|
$this->date_credit = $date; // date credit or debit |
670
|
|
|
$this->statut = self::STATUS_CREDITED; |
671
|
|
|
$this->status = self::STATUS_CREDITED; |
672
|
|
|
|
673
|
|
|
$this->db->commit(); |
674
|
|
|
return 0; |
675
|
|
|
} else { |
676
|
|
|
$this->db->rollback(); |
677
|
|
|
return -1; |
678
|
|
|
} |
679
|
|
|
} else { |
680
|
|
|
return -1026; |
681
|
|
|
} |
682
|
|
|
} |
683
|
|
|
|
684
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
685
|
|
|
/** |
686
|
|
|
* Set withdrawal to transmitted status |
687
|
|
|
* |
688
|
|
|
* @param User $user Id of user |
689
|
|
|
* @param int $date Date of action |
690
|
|
|
* @param int $method Method of transmission to bank (0=Internet, 1=Api...) |
691
|
|
|
* @return int >0 if OK, <0 if KO |
692
|
|
|
*/ |
693
|
|
|
public function set_infotrans($user, $date, $method) |
694
|
|
|
{ |
695
|
|
|
// phpcs:enable |
696
|
|
|
global $conf, $langs; |
697
|
|
|
|
698
|
|
|
$error = 0; |
699
|
|
|
|
700
|
|
|
dol_syslog(get_only_class($this) . "::set_infotrans Start", LOG_INFO); |
701
|
|
|
|
702
|
|
|
if ($this->db->begin()) { |
703
|
|
|
$sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_bons "; |
704
|
|
|
$sql .= " SET fk_user_trans = " . $user->id; |
705
|
|
|
$sql .= " , date_trans = '" . $this->db->idate($date) . "'"; |
706
|
|
|
$sql .= " , method_trans = " . ((int) $method); |
707
|
|
|
$sql .= " , statut = " . self::STATUS_TRANSFERED; |
708
|
|
|
$sql .= " WHERE rowid = " . ((int) $this->id); |
709
|
|
|
$sql .= " AND entity = " . ((int) $conf->entity); |
710
|
|
|
$sql .= " AND statut = " . self::STATUS_DRAFT; |
711
|
|
|
|
712
|
|
|
if ($this->db->query($sql)) { |
713
|
|
|
$this->method_trans = $method; |
714
|
|
|
$langs->load('withdrawals'); |
715
|
|
|
$subject = $langs->trans("InfoTransSubject", $this->ref); |
716
|
|
|
$message = $langs->trans("InfoTransMessage", $this->ref, dolGetFirstLastname($user->firstname, $user->lastname)); |
717
|
|
|
$message .= $langs->trans("InfoTransData", price($this->amount), $this->methodes_trans[$this->method_trans], dol_print_date($date, 'day')); |
718
|
|
|
|
719
|
|
|
// TODO Call trigger to create a notification using notification module |
720
|
|
|
} else { |
721
|
|
|
$error++; |
722
|
|
|
} |
723
|
|
|
|
724
|
|
|
if ($error == 0) { |
725
|
|
|
$this->date_trans = $date; |
726
|
|
|
$this->statut = self::STATUS_TRANSFERED; |
727
|
|
|
$this->status = self::STATUS_TRANSFERED; |
728
|
|
|
$this->user_trans = $user->id; |
729
|
|
|
|
730
|
|
|
$this->db->commit(); |
731
|
|
|
|
732
|
|
|
return 0; |
733
|
|
|
} else { |
734
|
|
|
$this->db->rollback(); |
735
|
|
|
dol_syslog(get_only_class($this) . "::set_infotrans ROLLBACK", LOG_ERR); |
736
|
|
|
|
737
|
|
|
return -1; |
738
|
|
|
} |
739
|
|
|
} else { |
740
|
|
|
dol_syslog(get_only_class($this) . "::set_infotrans Ouverture transaction SQL impossible", LOG_CRIT); |
741
|
|
|
return -2; |
742
|
|
|
} |
743
|
|
|
} |
744
|
|
|
|
745
|
|
|
/** |
746
|
|
|
* Get invoice or salary list (with amount or not) |
747
|
|
|
* |
748
|
|
|
* @param int $amounts If you want to get the amount of the order for each invoice or salary |
749
|
|
|
* @param string $type 'salary' for type=salary |
750
|
|
|
* @return array Array(Id of invoices/salary, Amount to pay) |
751
|
|
|
*/ |
752
|
|
|
private function getListInvoices($amounts = 0, $type = '') |
753
|
|
|
{ |
754
|
|
|
global $conf; |
755
|
|
|
|
756
|
|
|
$arr = array(); |
757
|
|
|
|
758
|
|
|
dol_syslog(get_only_class($this) . "::getListInvoices"); |
759
|
|
|
|
760
|
|
|
// Returns all invoices presented within same order |
761
|
|
|
$sql = "SELECT "; |
762
|
|
|
if ($this->type == 'bank-transfer') { |
763
|
|
|
if ($type == 'salary') { |
764
|
|
|
$sql .= " p.fk_salary"; |
765
|
|
|
} else { |
766
|
|
|
$sql .= " p.fk_facture_fourn"; |
767
|
|
|
} |
768
|
|
|
} else { |
769
|
|
|
$sql .= " p.fk_facture"; |
770
|
|
|
} |
771
|
|
|
if ($amounts) { |
772
|
|
|
$sql .= ", SUM(pl.amount)"; |
773
|
|
|
} |
774
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as pb,"; |
775
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,"; |
776
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement as p"; |
777
|
|
|
$sql .= " WHERE p.fk_prelevement_lignes = pl.rowid"; |
778
|
|
|
$sql .= " AND pl.fk_prelevement_bons = pb.rowid"; |
779
|
|
|
$sql .= " AND pb.rowid = " . ((int) $this->id); |
780
|
|
|
$sql .= " AND pb.entity = " . ((int) $conf->entity); |
781
|
|
|
if ($amounts) { |
782
|
|
|
if ($this->type == 'bank-transfer') { |
783
|
|
|
if ($type == 'salary') { |
784
|
|
|
$sql .= " GROUP BY p.fk_salary"; |
785
|
|
|
} else { |
786
|
|
|
$sql .= " GROUP BY p.fk_facture_fourn"; |
787
|
|
|
} |
788
|
|
|
} else { |
789
|
|
|
$sql .= " GROUP BY p.fk_facture"; |
790
|
|
|
} |
791
|
|
|
} |
792
|
|
|
|
793
|
|
|
$resql = $this->db->query($sql); |
794
|
|
|
if ($resql) { |
795
|
|
|
$num = $this->db->num_rows($resql); |
796
|
|
|
|
797
|
|
|
if ($num) { |
798
|
|
|
$i = 0; |
799
|
|
|
while ($i < $num) { |
800
|
|
|
$row = $this->db->fetch_row($resql); |
801
|
|
|
if (!$amounts) { |
802
|
|
|
$arr[$i] = $row[0]; |
803
|
|
|
} else { |
804
|
|
|
$arr[$i] = array( |
805
|
|
|
$row[0], |
806
|
|
|
$row[1] |
807
|
|
|
); |
808
|
|
|
} |
809
|
|
|
$i++; |
810
|
|
|
} |
811
|
|
|
} |
812
|
|
|
$this->db->free($resql); |
813
|
|
|
} else { |
814
|
|
|
$this->error = $this->db->lasterror(); |
815
|
|
|
} |
816
|
|
|
|
817
|
|
|
return $arr; |
818
|
|
|
} |
819
|
|
|
|
820
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
821
|
|
|
/** |
822
|
|
|
* Returns amount waiting for direct debit payment or credit transfer payment |
823
|
|
|
* |
824
|
|
|
* @param string $mode 'direct-debit' or 'bank-transfer' |
825
|
|
|
* @param string $type for type=salary |
826
|
|
|
* @return double Return integer <O if KO, Total amount |
827
|
|
|
*/ |
828
|
|
|
public function SommeAPrelever($mode = 'direct-debit', $type = '') |
829
|
|
|
{ |
830
|
|
|
// phpcs:enable |
831
|
|
|
$sql = "SELECT sum(pd.amount) as nb"; |
832
|
|
|
if ($type !== 'salary') { |
833
|
|
|
if ($mode != 'bank-transfer') { |
834
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "facture as f,"; |
835
|
|
|
} else { |
836
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f,"; |
837
|
|
|
} |
838
|
|
|
} else { |
839
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "salary as s,"; |
840
|
|
|
} |
841
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement_demande as pd"; |
842
|
|
|
$sql .= ($type !== 'salary' ? " WHERE f.entity IN (" . getEntity('invoice') . ")" : " WHERE s.entity IN (" . getEntity('salary') . ")"); |
843
|
|
|
if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) { |
844
|
|
|
$sql .= ($type !== 'salary' ? " AND f.fk_statut = " . Facture::STATUS_VALIDATED : " AND s.paye = " . Salary::STATUS_UNPAID); |
845
|
|
|
} |
846
|
|
|
if ($type !== 'salary') { |
847
|
|
|
if ($mode != 'bank-transfer') { |
848
|
|
|
$sql .= " AND f.rowid = pd.fk_facture"; |
849
|
|
|
} else { |
850
|
|
|
$sql .= " AND f.rowid = pd.fk_facture_fourn"; |
851
|
|
|
} |
852
|
|
|
} else { |
853
|
|
|
$sql .= " AND s.rowid = pd.fk_salary"; |
854
|
|
|
} |
855
|
|
|
$sql .= ($type !== 'salary' ? " AND f.paye = 0" : ""); |
856
|
|
|
$sql .= " AND pd.traite = 0"; |
857
|
|
|
$sql .= " AND pd.ext_payment_id IS NULL"; |
858
|
|
|
$sql .= ($type !== 'salary' ? " AND f.total_ttc > 0" : ""); |
859
|
|
|
|
860
|
|
|
$resql = $this->db->query($sql); |
861
|
|
|
if ($resql) { |
862
|
|
|
$obj = $this->db->fetch_object($resql); |
863
|
|
|
|
864
|
|
|
$this->db->free($resql); |
865
|
|
|
|
866
|
|
|
return $obj->nb; |
867
|
|
|
} else { |
868
|
|
|
$error = 1; |
869
|
|
|
dol_syslog(get_only_class($this) . "::SommeAPrelever Erreur -1"); |
870
|
|
|
dol_syslog($this->db->error()); |
871
|
|
|
|
872
|
|
|
return -1; |
873
|
|
|
} |
874
|
|
|
} |
875
|
|
|
|
876
|
|
|
/** |
877
|
|
|
* Get number of invoices waiting for payment |
878
|
|
|
* |
879
|
|
|
* @param string $mode 'direct-debit' or 'bank-transfer' |
880
|
|
|
* @param string $type for salary invoice |
881
|
|
|
* @return int Return integer <O if KO, number of invoices if OK |
882
|
|
|
*/ |
883
|
|
|
public function nbOfInvoiceToPay($mode = 'direct-debit', $type = '') |
884
|
|
|
{ |
885
|
|
|
if ($type === 'salary') { |
886
|
|
|
return $this->NbFactureAPrelever($mode, 1); |
887
|
|
|
} else { |
888
|
|
|
return $this->NbFactureAPrelever($mode); |
889
|
|
|
} |
890
|
|
|
} |
891
|
|
|
|
892
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
893
|
|
|
/** |
894
|
|
|
* Get number of invoices to pay |
895
|
|
|
* |
896
|
|
|
* @param string $type 'direct-debit' or 'bank-transfer' |
897
|
|
|
* @param int $forsalary 0= for facture & facture_supplier, 1=for salary |
898
|
|
|
* @return int Return integer <O if KO, number of invoices if OK |
899
|
|
|
*/ |
900
|
|
|
public function NbFactureAPrelever($type = 'direct-debit', $forsalary = 0) |
901
|
|
|
{ |
902
|
|
|
// phpcs:enable |
903
|
|
|
if ($forsalary == 1) { |
904
|
|
|
$sql = "SELECT count(s.rowid) as nb"; |
905
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "salary as s"; |
906
|
|
|
} else { |
907
|
|
|
$sql = "SELECT count(f.rowid) as nb"; |
908
|
|
|
|
909
|
|
|
if ($type == 'bank-transfer') { |
910
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f"; |
911
|
|
|
} else { |
912
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "facture as f"; |
913
|
|
|
} |
914
|
|
|
} |
915
|
|
|
$sql .= ", " . MAIN_DB_PREFIX . "prelevement_demande as pd"; |
916
|
|
|
if ($forsalary == 1) { |
917
|
|
|
$sql .= " WHERE s.entity IN (" . getEntity('invoice') . ")"; |
918
|
|
|
if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) { |
919
|
|
|
$sql .= " AND s.paye = 0"; |
920
|
|
|
} |
921
|
|
|
} else { |
922
|
|
|
$sql .= " WHERE f.entity IN (" . getEntity('invoice') . ")"; |
923
|
|
|
if (!getDolGlobalString('WITHDRAWAL_ALLOW_ANY_INVOICE_STATUS')) { |
924
|
|
|
$sql .= " AND f.fk_statut = " . Facture::STATUS_VALIDATED; |
925
|
|
|
} |
926
|
|
|
} |
927
|
|
|
if ($forsalary == 1) { |
928
|
|
|
$sql .= " AND s.rowid = pd.fk_salary"; |
929
|
|
|
} else { |
930
|
|
|
if ($type == 'bank-transfer') { |
931
|
|
|
$sql .= " AND f.rowid = pd.fk_facture_fourn"; |
932
|
|
|
} else { |
933
|
|
|
$sql .= " AND f.rowid = pd.fk_facture"; |
934
|
|
|
} |
935
|
|
|
} |
936
|
|
|
$sql .= " AND pd.traite = 0"; |
937
|
|
|
$sql .= " AND pd.ext_payment_id IS NULL"; |
938
|
|
|
if (!$forsalary == 1) { |
939
|
|
|
$sql .= " AND f.total_ttc > 0"; |
940
|
|
|
} else { |
941
|
|
|
$sql .= " AND s.paye = 0"; |
942
|
|
|
} |
943
|
|
|
|
944
|
|
|
dol_syslog(get_only_class($this) . "::NbFactureAPrelever"); |
945
|
|
|
$resql = $this->db->query($sql); |
946
|
|
|
|
947
|
|
|
if ($resql) { |
948
|
|
|
$obj = $this->db->fetch_object($resql); |
949
|
|
|
$this->db->free($resql); |
950
|
|
|
|
951
|
|
|
return $obj->nb; |
952
|
|
|
} else { |
953
|
|
|
$this->error = get_only_class($this) . "::NbFactureAPrelever Erreur -1 sql=" . $this->db->error(); |
954
|
|
|
return -1; |
955
|
|
|
} |
956
|
|
|
} |
957
|
|
|
|
958
|
|
|
|
959
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
960
|
|
|
/** |
961
|
|
|
* Create a BAN payment order: |
962
|
|
|
* - Select waiting requests from prelevement_demande (or use $did if provided) |
963
|
|
|
* - Check BAN values |
964
|
|
|
* - Then create a direct debit order or a credit transfer order |
965
|
|
|
* - Link the order with the prelevement_demande lines |
966
|
|
|
* TODO delete params banque and agence when not necessary |
967
|
|
|
* |
968
|
|
|
* @param int $banque dolibarr mysoc bank |
969
|
|
|
* @param int $agence dolibarr mysoc bank office (guichet) |
970
|
|
|
* @param string $mode real=do action, simu=test only |
971
|
|
|
* @param string $format FRST, RCUR or ALL |
972
|
|
|
* @param string $executiondate Date to execute the transfer |
973
|
|
|
* @param int $notrigger Disable triggers |
974
|
|
|
* @param string $type 'direct-debit' or 'bank-transfer' |
975
|
|
|
* @param int $did ID of an existing payment request. If $did is defined, we use the existing payment request. |
976
|
|
|
* @param int $fk_bank_account Bank account ID the receipt is generated for. Will use the ID into the setup of module Direct Debit or Credit Transfer if 0. |
977
|
|
|
* @param string $sourcetype 'invoice' or 'salary' |
978
|
|
|
* @return int Return integer <0 if KO, No of invoice included into file if OK |
979
|
|
|
*/ |
980
|
|
|
public function create($banque = 0, $agence = 0, $mode = 'real', $format = 'ALL', $executiondate = '', $notrigger = 0, $type = 'direct-debit', $did = 0, $fk_bank_account = 0, $sourcetype = 'invoice') |
981
|
|
|
{ |
982
|
|
|
// phpcs:enable |
983
|
|
|
global $conf, $langs, $user; |
984
|
|
|
|
985
|
|
|
dol_syslog(__METHOD__ . " Bank=" . $banque . " Office=" . $agence . " mode=" . $mode . " format=" . $format, LOG_DEBUG); |
986
|
|
|
|
987
|
|
|
|
988
|
|
|
// Check params |
989
|
|
|
if ($type != 'bank-transfer') { |
990
|
|
|
if (empty($format)) { |
991
|
|
|
$this->error = 'ErrorBadParametersForDirectDebitFileCreate'; |
992
|
|
|
return -1; |
993
|
|
|
} |
994
|
|
|
} |
995
|
|
|
|
996
|
|
|
// Clean params |
997
|
|
|
if (empty($fk_bank_account)) { |
998
|
|
|
$fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT')); |
999
|
|
|
} |
1000
|
|
|
|
1001
|
|
|
$error = 0; |
1002
|
|
|
|
1003
|
|
|
$datetimeprev = dol_now('gmt'); |
1004
|
|
|
// Choice the date of the execution direct debit |
1005
|
|
|
if (!empty($executiondate)) { |
1006
|
|
|
$datetimeprev = $executiondate; |
1007
|
|
|
} |
1008
|
|
|
|
1009
|
|
|
$month = dol_print_date($datetimeprev, "%m", 'gmt'); |
1010
|
|
|
$year = dol_print_date($datetimeprev, "%Y", 'gmt'); |
1011
|
|
|
|
1012
|
|
|
$this->invoice_in_error = array(); |
1013
|
|
|
$this->thirdparty_in_error = array(); |
1014
|
|
|
|
1015
|
|
|
// Read invoices |
1016
|
|
|
$factures = array(); |
1017
|
|
|
$factures_prev = array(); |
1018
|
|
|
$factures_result = array(); |
1019
|
|
|
$factures_prev_id = array(); |
1020
|
|
|
$factures_errors = array(); |
1021
|
|
|
if (!$error) { |
1022
|
|
|
dol_syslog(__METHOD__ . " Read invoices for did=" . ((int) $did), LOG_DEBUG); |
1023
|
|
|
|
1024
|
|
|
$sql = "SELECT f.rowid, pd.rowid as pfdrowid"; |
1025
|
|
|
if ($sourcetype != 'salary') { |
1026
|
|
|
$sql .= ", f.fk_soc"; |
1027
|
|
|
} else { |
1028
|
|
|
$sql .= ", f.fk_user"; |
1029
|
|
|
} |
1030
|
|
|
$sql .= ", pd.code_banque, pd.code_guichet, pd.number, pd.cle_rib"; |
1031
|
|
|
$sql .= ", pd.amount"; |
1032
|
|
|
if ($sourcetype != 'salary') { |
1033
|
|
|
$sql .= ", s.nom as name"; |
1034
|
|
|
$sql .= ", f.ref, sr.bic, sr.iban_prefix, sr.frstrecur"; |
1035
|
|
|
} else { |
1036
|
|
|
$sql .= ", CONCAT(s.firstname,' ',s.lastname) as name"; |
1037
|
|
|
$sql .= ", f.ref, sr.bic, sr.iban_prefix, 'FRST' as frstrecur"; |
1038
|
|
|
} |
1039
|
|
|
if ($sourcetype != 'salary') { |
1040
|
|
|
if ($type != 'bank-transfer') { |
1041
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "facture as f"; |
1042
|
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_facture"; |
1043
|
|
|
} else { |
1044
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "facture_fourn as f"; |
1045
|
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_facture_fourn"; |
1046
|
|
|
} |
1047
|
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s ON s.rowid = f.fk_soc"; |
1048
|
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "societe_rib as sr ON s.rowid = sr.fk_soc AND sr.default_rib = 1"; |
1049
|
|
|
} else { |
1050
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "salary as f"; |
1051
|
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "prelevement_demande as pd ON f.rowid = pd.fk_salary"; |
1052
|
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user as s ON s.rowid = f.fk_user"; |
1053
|
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "user_rib as sr ON s.rowid = sr.fk_user"; // TODO Add AND sr.default_rib = 1 here |
1054
|
|
|
} |
1055
|
|
|
if ($sourcetype != 'salary') { |
1056
|
|
|
if ($type != 'bank-transfer') { |
1057
|
|
|
$sql .= " WHERE f.entity IN (" . getEntity('invoice') . ')'; |
1058
|
|
|
} else { |
1059
|
|
|
$sql .= " WHERE f.entity IN (" . getEntity('supplier_invoice') . ')'; |
1060
|
|
|
} |
1061
|
|
|
} else { |
1062
|
|
|
$sql .= " WHERE f.entity IN (" . getEntity('salary') . ')'; |
1063
|
|
|
} |
1064
|
|
|
if ($sourcetype != 'salary') { |
1065
|
|
|
$sql .= " AND f.fk_statut = 1"; // Invoice validated |
1066
|
|
|
$sql .= " AND f.paye = 0"; |
1067
|
|
|
$sql .= " AND f.total_ttc > 0"; |
1068
|
|
|
} else { |
1069
|
|
|
//$sql .= " AND f.fk_statut = 1"; // Invoice validated |
1070
|
|
|
$sql .= " AND f.paye = 0"; |
1071
|
|
|
$sql .= " AND f.amount > 0"; |
1072
|
|
|
} |
1073
|
|
|
$sql .= " AND pd.traite = 0"; |
1074
|
|
|
$sql .= " AND pd.ext_payment_id IS NULL"; |
1075
|
|
|
if ($sourcetype != 'salary') { |
1076
|
|
|
$sql .= " AND sr.type = 'ban'"; // TODO Add AND sr.type = 'ban' for users too |
1077
|
|
|
} |
1078
|
|
|
if ($did > 0) { |
1079
|
|
|
$sql .= " AND pd.rowid = " . ((int) $did); |
1080
|
|
|
} |
1081
|
|
|
|
1082
|
|
|
$resql = $this->db->query($sql); |
1083
|
|
|
if ($resql) { |
1084
|
|
|
$num = $this->db->num_rows($resql); |
1085
|
|
|
$i = 0; |
1086
|
|
|
|
1087
|
|
|
while ($i < $num) { |
1088
|
|
|
$row = $this->db->fetch_row($resql); // TODO Replace with fetch_object() |
1089
|
|
|
$factures[$i] = $row; // All fields |
1090
|
|
|
|
1091
|
|
|
if ($row[7] == 0) { |
1092
|
|
|
$error++; |
1093
|
|
|
dol_syslog(__METHOD__ . " Read invoices/salary error Found a null amount", LOG_ERR); |
1094
|
|
|
$this->invoice_in_error[$row[0]] = "Error for invoice or salary id " . $row[0] . ", found a null amount"; |
1095
|
|
|
break; |
1096
|
|
|
} |
1097
|
|
|
$i++; |
1098
|
|
|
} |
1099
|
|
|
|
1100
|
|
|
$this->db->free($resql); |
1101
|
|
|
dol_syslog(__METHOD__ . " Read invoices/salary, " . $i . " invoices/salary to withdraw", LOG_DEBUG); |
1102
|
|
|
} else { |
1103
|
|
|
$error++; |
1104
|
|
|
$this->error = $this->db->lasterror(); |
1105
|
|
|
dol_syslog(__METHOD__ . " Read invoices/salary error " . $this->db->lasterror(), LOG_ERR); |
1106
|
|
|
return -1; |
1107
|
|
|
} |
1108
|
|
|
} |
1109
|
|
|
|
1110
|
|
|
if (!$error) { |
1111
|
|
|
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/bank.lib.php'; |
1112
|
|
|
|
1113
|
|
|
$tmpsoc = new Societe($this->db); |
1114
|
|
|
$tmpuser = new User($this->db); |
1115
|
|
|
|
1116
|
|
|
// Check BAN |
1117
|
|
|
$i = 0; |
1118
|
|
|
dol_syslog(__METHOD__ . " Check BAN", LOG_DEBUG); |
1119
|
|
|
|
1120
|
|
|
if (count($factures) > 0) { |
1121
|
|
|
foreach ($factures as $key => $fac) { |
1122
|
|
|
/* |
1123
|
|
|
if ($type != 'bank-transfer') { |
1124
|
|
|
$tmpinvoice = new Facture($this->db); |
1125
|
|
|
} else { |
1126
|
|
|
$tmpinvoice = new FactureFournisseur($this->db); |
1127
|
|
|
} |
1128
|
|
|
$resfetch = $tmpinvoice->fetch($fac[0]); |
1129
|
|
|
if ($resfetch >= 0) { // Field 0 of $fac is rowid of invoice |
1130
|
|
|
*/ |
1131
|
|
|
|
1132
|
|
|
// Check if $fac[8] s.nom is null |
1133
|
|
|
if ($fac[8] != null) { |
1134
|
|
|
if ($type != 'bank-transfer') { |
1135
|
|
|
if ($format == 'FRST' && $fac[12] != 'FRST') { |
1136
|
|
|
continue; |
1137
|
|
|
} |
1138
|
|
|
if ($format == 'RCUR' && $fac[12] != 'RCUR') { |
1139
|
|
|
continue; |
1140
|
|
|
} |
1141
|
|
|
} |
1142
|
|
|
|
1143
|
|
|
$verif = checkSwiftForAccount(null, $fac[10]); |
1144
|
|
|
if ($verif) { |
1145
|
|
|
$verif = checkIbanForAccount(null, $fac[11]); |
1146
|
|
|
} |
1147
|
|
|
|
1148
|
|
|
if ($verif) { |
1149
|
|
|
$factures_prev[$i] = $fac; |
1150
|
|
|
/* second array necessary for BonPrelevement */ |
1151
|
|
|
$factures_prev_id[$i] = $fac[0]; |
1152
|
|
|
$i++; |
1153
|
|
|
//dol_syslog(__METHOD__."::RIB is ok", LOG_DEBUG); |
1154
|
|
|
} else { |
1155
|
|
|
if ($type != 'bank-transfer') { |
1156
|
|
|
$tmpsoc->id = $fac[2]; |
1157
|
|
|
$tmpsoc->name = $fac[8]; |
1158
|
|
|
$invoice_url = "<a href='" . constant('BASE_URL') . '/compta/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>"; |
1159
|
|
|
$this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0); |
1160
|
|
|
$this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0); |
1161
|
|
|
$error++; |
1162
|
|
|
} |
1163
|
|
|
if ($type == 'bank-transfer' && $sourcetype != 'salary') { |
1164
|
|
|
$tmpsoc->id = $fac[2]; |
1165
|
|
|
$tmpsoc->name = $fac[8]; |
1166
|
|
|
$invoice_url = "<a href='" . constant('BASE_URL') . '/fourn/facture/card.php?facid=' . $fac[0] . "'>" . $fac[9] . "</a>"; |
1167
|
|
|
$this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0); |
1168
|
|
|
$this->thirdparty_in_error[$tmpsoc->id] = "Error on default bank number IBAN/BIC for invoice " . $invoice_url . " for thirdparty " . $tmpsoc->getNomUrl(0); |
1169
|
|
|
$error++; |
1170
|
|
|
} |
1171
|
|
|
if ($type == 'bank-transfer' && $sourcetype == 'salary') { |
1172
|
|
|
$tmpuser->id = $fac[2]; |
1173
|
|
|
$tmpuser->firstname = $fac[8]; |
1174
|
|
|
$salary_url = "<a href='" . constant('BASE_URL') . '/salaries/card.php?id=' . $fac[0] . "'>" . $fac[0] . "</a>"; |
1175
|
|
|
$this->invoice_in_error[$fac[0]] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0); |
1176
|
|
|
$this->thirdparty_in_error[$tmpuser->id] = "Error on default bank number IBAN/BIC for salary " . $salary_url . " for employee " . $tmpuser->getNomUrl(0); |
1177
|
|
|
$error++; |
1178
|
|
|
} |
1179
|
|
|
dol_syslog(__METHOD__ . " Check BAN Error on default bank number IBAN/BIC reported by verif(): " . implode(', ', $fac), LOG_WARNING); |
1180
|
|
|
} |
1181
|
|
|
} else { |
1182
|
|
|
dol_syslog(__METHOD__ . " Check BAN Failed to read company", LOG_WARNING); |
1183
|
|
|
} |
1184
|
|
|
/* |
1185
|
|
|
} else { |
1186
|
|
|
dol_syslog(__METHOD__." Check BAN Failed to read invoice", LOG_WARNING); |
1187
|
|
|
} |
1188
|
|
|
*/ |
1189
|
|
|
} |
1190
|
|
|
} else { |
1191
|
|
|
dol_syslog(__METHOD__ . " Check BAN No invoice to process", LOG_WARNING); |
1192
|
|
|
} |
1193
|
|
|
} |
1194
|
|
|
|
1195
|
|
|
$ok = 0; |
1196
|
|
|
|
1197
|
|
|
// Withdraw invoices in factures_prev array |
1198
|
|
|
$out = count($factures_prev) . " invoices will be included."; |
1199
|
|
|
//print $out."\n"; |
1200
|
|
|
dol_syslog($out); |
1201
|
|
|
|
1202
|
|
|
// Return warning |
1203
|
|
|
/*$i=0; |
1204
|
|
|
foreach ($this->thirdparty_in_error as $key => $val) |
1205
|
|
|
{ |
1206
|
|
|
if ($i < 10) setEventMessages($val, null, 'warnings'); |
1207
|
|
|
else setEventMessages('More error were discarded...', null, 'warnings'); |
1208
|
|
|
$i++; |
1209
|
|
|
}*/ |
1210
|
|
|
|
1211
|
|
|
if (count($factures_prev) > 0) { |
1212
|
|
|
if ($mode == 'real') { |
1213
|
|
|
$ok = 1; |
1214
|
|
|
} else { |
1215
|
|
|
print $langs->trans("ModeWarning"); // "Option for real mode was not set, we stop after this simulation\n"; |
1216
|
|
|
} |
1217
|
|
|
} |
1218
|
|
|
if ($ok) { |
1219
|
|
|
/* |
1220
|
|
|
* We are in real mode. |
1221
|
|
|
* We create order and build file into disk |
1222
|
|
|
*/ |
1223
|
|
|
$this->db->begin(); |
1224
|
|
|
|
1225
|
|
|
$now = dol_now(); |
1226
|
|
|
$ref = ''; |
1227
|
|
|
|
1228
|
|
|
/* |
1229
|
|
|
* Process order generation |
1230
|
|
|
*/ |
1231
|
|
|
if (!$error) { |
1232
|
|
|
$ref = substr($year, -2) . $month; |
1233
|
|
|
|
1234
|
|
|
// Get next free number for the ref of bon prelevement |
1235
|
|
|
$sql = "SELECT substring(ref from char_length(ref) - 1)"; // To extract "YYMMXX" from "TYYMMXX" |
1236
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons"; |
1237
|
|
|
$sql .= " WHERE ref LIKE '_" . $this->db->escape($ref) . "%'"; |
1238
|
|
|
$sql .= " AND entity = " . ((int) $conf->entity); |
1239
|
|
|
$sql .= " ORDER BY ref DESC LIMIT 1"; |
1240
|
|
|
|
1241
|
|
|
dol_syslog(get_only_class($this) . " get next free number", LOG_DEBUG); |
1242
|
|
|
$resql = $this->db->query($sql); |
1243
|
|
|
|
1244
|
|
|
if ($resql) { |
1245
|
|
|
$row = $this->db->fetch_row($resql); |
1246
|
|
|
|
1247
|
|
|
// Build the new ref |
1248
|
|
|
$ref = "T" . $ref . sprintf("%02d", (intval($row[0]) + 1)); |
1249
|
|
|
|
1250
|
|
|
// $conf->abc->dir_output may be: |
1251
|
|
|
// /home/ldestailleur/git/dolibarr_15.0/documents/abc/ |
1252
|
|
|
// or |
1253
|
|
|
// /home/ldestailleur/git/dolibarr_15.0/documents/X/abc with X >= 2 with multicompany. |
1254
|
|
|
if ($type != 'bank-transfer') { |
1255
|
|
|
$dir = $conf->prelevement->dir_output . '/receipts'; |
1256
|
|
|
} else { |
1257
|
|
|
$dir = $conf->paymentbybanktransfer->dir_output . '/receipts'; |
1258
|
|
|
} |
1259
|
|
|
if (!is_dir($dir)) { |
1260
|
|
|
dol_mkdir($dir); |
1261
|
|
|
} |
1262
|
|
|
|
1263
|
|
|
if (isModEnabled('multicompany')) { |
1264
|
|
|
$labelentity = $conf->entity; |
1265
|
|
|
$this->filename = $dir . '/' . $ref . '-' . $labelentity . '.xml'; |
1266
|
|
|
} else { |
1267
|
|
|
$this->filename = $dir . '/' . $ref . '.xml'; |
1268
|
|
|
} |
1269
|
|
|
|
1270
|
|
|
// Create withdraw order in database |
1271
|
|
|
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_bons ("; |
1272
|
|
|
$sql .= "ref, entity, datec, type, fk_bank_account"; |
1273
|
|
|
$sql .= ") VALUES ("; |
1274
|
|
|
$sql .= "'" . $this->db->escape($ref) . "'"; |
1275
|
|
|
$sql .= ", " . ((int) $conf->entity); |
1276
|
|
|
$sql .= ", '" . $this->db->idate($now) . "'"; |
1277
|
|
|
$sql .= ", '" . ($type == 'bank-transfer' ? 'bank-transfer' : 'debit-order') . "'"; |
1278
|
|
|
$sql .= ", " . ((int) $fk_bank_account); |
1279
|
|
|
$sql .= ")"; |
1280
|
|
|
|
1281
|
|
|
$resql = $this->db->query($sql); |
1282
|
|
|
|
1283
|
|
|
|
1284
|
|
|
if ($resql) { |
1285
|
|
|
$prev_id = $this->db->last_insert_id(MAIN_DB_PREFIX . "prelevement_bons"); |
1286
|
|
|
$this->id = $prev_id; |
1287
|
|
|
$this->ref = $ref; |
1288
|
|
|
} else { |
1289
|
|
|
$error++; |
1290
|
|
|
dol_syslog(__METHOD__ . " Create withdraw receipt " . $this->db->lasterror(), LOG_ERR); |
1291
|
|
|
} |
1292
|
|
|
} else { |
1293
|
|
|
$error++; |
1294
|
|
|
dol_syslog(__METHOD__ . " Get last withdraw receipt " . $this->db->lasterror(), LOG_ERR); |
1295
|
|
|
} |
1296
|
|
|
} |
1297
|
|
|
|
1298
|
|
|
if (!$error) { |
1299
|
|
|
dol_syslog(__METHOD__ . " Now loop on each document to insert them in llx_prelevement_demande"); |
1300
|
|
|
|
1301
|
|
|
// Add lines for the bon |
1302
|
|
|
if (count($factures_prev) > 0) { |
1303
|
|
|
foreach ($factures_prev as $fac) { // Add a link in database for each invoice ro salary |
1304
|
|
|
/* |
1305
|
|
|
* Add standing order. This add record into llx_prelevement_lignes and llx_prelevement |
1306
|
|
|
* |
1307
|
|
|
* $fac[0] : invoice_id |
1308
|
|
|
* $fac[1] : ??? |
1309
|
|
|
* $fac[2] : third party id |
1310
|
|
|
* $fac[3] : banque |
1311
|
|
|
* $fac[4] : guichet |
1312
|
|
|
* $fac[5] : number |
1313
|
|
|
* $fac[6] : cle rib |
1314
|
|
|
* $fac[7] : amount |
1315
|
|
|
* $fac[8] : client nom |
1316
|
|
|
* $fac[9] : Invoice ref |
1317
|
|
|
* $fac[10] : BIC |
1318
|
|
|
* $fac[11] : IBAN |
1319
|
|
|
* $fac[12] : frstrcur |
1320
|
|
|
*/ |
1321
|
|
|
$ri = $this->AddFacture($fac[0], $fac[2], $fac[8], $fac[7], $fac[3], $fac[4], $fac[5], $fac[6], $type, $sourcetype); |
1322
|
|
|
|
1323
|
|
|
if ($ri != 0) { |
1324
|
|
|
$error++; |
1325
|
|
|
} |
1326
|
|
|
|
1327
|
|
|
// Update invoice requests as done |
1328
|
|
|
$sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande"; |
1329
|
|
|
$sql .= " SET traite = 1"; |
1330
|
|
|
$sql .= ", date_traite = '" . $this->db->idate($now) . "'"; |
1331
|
|
|
$sql .= ", fk_prelevement_bons = " . ((int) $this->id); |
1332
|
|
|
$sql .= " WHERE rowid = " . ((int) $fac[1]); |
1333
|
|
|
|
1334
|
|
|
$resql = $this->db->query($sql); |
1335
|
|
|
if (!$resql) { |
1336
|
|
|
$error++; |
1337
|
|
|
$this->errors[] = $this->db->lasterror(); |
1338
|
|
|
dol_syslog(__METHOD__ . " Update Error=" . $this->db->lasterror(), LOG_ERR); |
1339
|
|
|
} |
1340
|
|
|
} |
1341
|
|
|
} |
1342
|
|
|
} |
1343
|
|
|
|
1344
|
|
|
if (!$error) { |
1345
|
|
|
/* |
1346
|
|
|
* Create file of type='direct-debit' for direct debit order or type='bank-transfer' for credit transfer into a XML file |
1347
|
|
|
*/ |
1348
|
|
|
|
1349
|
|
|
dol_syslog(__METHOD__ . " Init direct debit or credit transfer file for " . count($factures_prev) . " invoices", LOG_DEBUG); |
1350
|
|
|
|
1351
|
|
|
if (count($factures_prev) > 0) { |
1352
|
|
|
$this->date_echeance = $datetimeprev; |
1353
|
|
|
$this->reference_remise = $ref; |
1354
|
|
|
|
1355
|
|
|
$account = new Account($this->db); |
1356
|
|
|
if ($account->fetch($fk_bank_account) > 0) { |
1357
|
|
|
$this->emetteur_code_banque = $account->code_banque; |
1358
|
|
|
$this->emetteur_code_guichet = $account->code_guichet; |
1359
|
|
|
$this->emetteur_numero_compte = $account->number; |
1360
|
|
|
$this->emetteur_number_key = $account->cle_rib; |
1361
|
|
|
$this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti; |
1362
|
|
|
$this->emetteur_iban = $account->iban; |
1363
|
|
|
$this->emetteur_bic = $account->bic; |
1364
|
|
|
|
1365
|
|
|
$this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics); // Example "FR78ZZZ123456" |
1366
|
|
|
|
1367
|
|
|
$this->raison_sociale = $account->proprio; |
|
|
|
|
1368
|
|
|
} |
1369
|
|
|
$this->factures = $factures_prev_id; |
1370
|
|
|
$this->context['factures_prev'] = $factures_prev; |
1371
|
|
|
// Generation of direct debit or credit transfer file $this->filename (May be a SEPA file for european countries) |
1372
|
|
|
// This also set the property $this->total with amount that is included into file |
1373
|
|
|
$userid = 0; |
1374
|
|
|
if ($sourcetype == 'salary') { |
1375
|
|
|
$userid = $this->context['factures_prev'][0][2]; |
1376
|
|
|
} |
1377
|
|
|
$result = $this->generate($format, $executiondate, $type, $fk_bank_account, $userid); |
1378
|
|
|
if ($result < 0) { |
1379
|
|
|
//var_dump($this->error); |
1380
|
|
|
//var_dump($this->invoice_in_error); |
1381
|
|
|
$error++; |
1382
|
|
|
} |
1383
|
|
|
} |
1384
|
|
|
dol_syslog(__METHOD__ . " Bank order file has been generated under filename " . $this->filename, LOG_DEBUG); |
1385
|
|
|
} |
1386
|
|
|
|
1387
|
|
|
|
1388
|
|
|
/* |
1389
|
|
|
* Update total defined after generation of file |
1390
|
|
|
*/ |
1391
|
|
|
if (!$error) { |
1392
|
|
|
$sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_bons"; |
1393
|
|
|
$sql .= " SET amount = " . price2num($this->total); |
1394
|
|
|
$sql .= " WHERE rowid = " . ((int) $this->id); |
1395
|
|
|
$sql .= " AND entity = " . ((int) $conf->entity); |
1396
|
|
|
$resql = $this->db->query($sql); |
1397
|
|
|
|
1398
|
|
|
if (!$resql) { |
1399
|
|
|
$error++; |
1400
|
|
|
dol_syslog(__METHOD__ . " Error update total: " . $this->db->error(), LOG_ERR); |
1401
|
|
|
} |
1402
|
|
|
} |
1403
|
|
|
|
1404
|
|
|
if (!$error && !$notrigger) { |
1405
|
|
|
$triggername = 'DIRECT_DEBIT_ORDER_CREATE'; |
1406
|
|
|
if ($type != 'bank-transfer') { |
1407
|
|
|
$triggername = 'CREDIT_TRANSFER_ORDER_CREATE'; |
1408
|
|
|
} |
1409
|
|
|
|
1410
|
|
|
// Call trigger |
1411
|
|
|
$result = $this->call_trigger($triggername, $user); |
1412
|
|
|
if ($result < 0) { |
1413
|
|
|
$error++; |
1414
|
|
|
} |
1415
|
|
|
// End call triggers |
1416
|
|
|
} |
1417
|
|
|
|
1418
|
|
|
if (!$error) { |
1419
|
|
|
$this->db->commit(); |
1420
|
|
|
return count($factures_prev); // The error of failed lines are into $this->invoice_in_error and $this->thirdparty_in_error |
1421
|
|
|
} else { |
1422
|
|
|
$this->db->rollback(); |
1423
|
|
|
return -1; |
1424
|
|
|
} |
1425
|
|
|
} else { |
1426
|
|
|
return 0; |
1427
|
|
|
} |
1428
|
|
|
} |
1429
|
|
|
|
1430
|
|
|
|
1431
|
|
|
/** |
1432
|
|
|
* Get object and lines from database |
1433
|
|
|
* |
1434
|
|
|
* @param User $user Object user that delete |
1435
|
|
|
* @param int $notrigger 1=Does not execute triggers, 0= execute triggers |
1436
|
|
|
* @return int >0 if OK, <0 if KO |
1437
|
|
|
*/ |
1438
|
|
|
public function delete($user = null, $notrigger = 0) |
1439
|
|
|
{ |
1440
|
|
|
$this->db->begin(); |
1441
|
|
|
|
1442
|
|
|
$error = 0; |
1443
|
|
|
$resql1 = $resql2 = $resql3 = $resql4 = 0; |
1444
|
|
|
|
1445
|
|
|
if (!$notrigger) { |
1446
|
|
|
$triggername = 'DIRECT_DEBIT_ORDER_DELETE'; |
1447
|
|
|
if ($this->type == 'bank-transfer') { |
1448
|
|
|
$triggername = 'PAYMENTBYBANKTRANFER_DELETE'; |
1449
|
|
|
} |
1450
|
|
|
// Call trigger |
1451
|
|
|
$result = $this->call_trigger($triggername, $user); |
1452
|
|
|
if ($result < 0) { |
1453
|
|
|
$error++; |
1454
|
|
|
} |
1455
|
|
|
// End call triggers |
1456
|
|
|
} |
1457
|
|
|
|
1458
|
|
|
if (!$error) { |
1459
|
|
|
$sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement WHERE fk_prelevement_lignes IN (SELECT rowid FROM " . MAIN_DB_PREFIX . "prelevement_lignes WHERE fk_prelevement_bons = " . ((int) $this->id) . ")"; |
1460
|
|
|
$resql1 = $this->db->query($sql); |
1461
|
|
|
if (!$resql1) { |
1462
|
|
|
dol_print_error($this->db); |
1463
|
|
|
} |
1464
|
|
|
} |
1465
|
|
|
|
1466
|
|
|
if (!$error) { |
1467
|
|
|
$sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_lignes WHERE fk_prelevement_bons = " . ((int) $this->id); |
1468
|
|
|
$resql2 = $this->db->query($sql); |
1469
|
|
|
if (!$resql2) { |
1470
|
|
|
dol_print_error($this->db); |
1471
|
|
|
} |
1472
|
|
|
} |
1473
|
|
|
|
1474
|
|
|
if (!$error) { |
1475
|
|
|
$sql = "DELETE FROM " . MAIN_DB_PREFIX . "prelevement_bons WHERE rowid = " . ((int) $this->id); |
1476
|
|
|
$resql3 = $this->db->query($sql); |
1477
|
|
|
if (!$resql3) { |
1478
|
|
|
dol_print_error($this->db); |
1479
|
|
|
} |
1480
|
|
|
} |
1481
|
|
|
|
1482
|
|
|
if (!$error) { |
1483
|
|
|
$sql = "UPDATE " . MAIN_DB_PREFIX . "prelevement_demande SET fk_prelevement_bons = NULL, traite = 0 WHERE fk_prelevement_bons = " . ((int) $this->id); |
1484
|
|
|
$resql4 = $this->db->query($sql); |
1485
|
|
|
if (!$resql4) { |
1486
|
|
|
dol_print_error($this->db); |
1487
|
|
|
} |
1488
|
|
|
} |
1489
|
|
|
|
1490
|
|
|
if ($resql1 && $resql2 && $resql3 && $resql4 && !$error) { |
1491
|
|
|
$this->db->commit(); |
1492
|
|
|
return 1; |
1493
|
|
|
} else { |
1494
|
|
|
$this->db->rollback(); |
1495
|
|
|
return -1; |
1496
|
|
|
} |
1497
|
|
|
} |
1498
|
|
|
|
1499
|
|
|
|
1500
|
|
|
/** |
1501
|
|
|
* Returns clickable name (with picto) |
1502
|
|
|
* |
1503
|
|
|
* @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) |
1504
|
|
|
* @param string $option On what the link point to ('nolink', ...) |
1505
|
|
|
* @param int $notooltip 1=Disable tooltip |
1506
|
|
|
* @param string $morecss Add more css on link |
1507
|
|
|
* @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking |
1508
|
|
|
* @return string URL of target |
1509
|
|
|
*/ |
1510
|
|
|
public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) |
1511
|
|
|
{ |
1512
|
|
|
global $conf, $langs, $hookmanager; |
1513
|
|
|
|
1514
|
|
|
if (!empty($conf->dol_no_mouse_hover)) { |
1515
|
|
|
$notooltip = 1; // Force disable tooltips |
1516
|
|
|
} |
1517
|
|
|
|
1518
|
|
|
$result = ''; |
1519
|
|
|
|
1520
|
|
|
$labeltoshow = 'PaymentByDirectDebit'; |
1521
|
|
|
if (!empty($this->type) && $this->type == 'bank-transfer') { |
1522
|
|
|
$labeltoshow = 'PaymentByBankTransfer'; |
1523
|
|
|
} |
1524
|
|
|
|
1525
|
|
|
$label = img_picto('', $this->picto) . ' <u>' . $langs->trans($labeltoshow) . '</u> ' . $this->getLibStatut(5); |
1526
|
|
|
$label .= '<br>'; |
1527
|
|
|
$label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->ref; |
1528
|
|
|
if (isset($this->amount)) { |
1529
|
|
|
$label .= '<br><b>' . $langs->trans("Amount") . ":</b> " . price($this->amount); |
1530
|
|
|
} |
1531
|
|
|
if (isset($this->date_trans)) { |
1532
|
|
|
$label .= '<br><b>' . $langs->trans("TransData") . ":</b> " . dol_print_date($this->date_trans, 'dayhour', 'tzuserrel'); |
1533
|
|
|
} |
1534
|
|
|
/*if (isset($this->date_credit)) { |
1535
|
|
|
$label .= '<br><b>'.$langs->trans("TransData").":</b> ".dol_print_date($this->date_credit, 'dayhour', 'tzuserrel'); |
1536
|
|
|
}*/ |
1537
|
|
|
|
1538
|
|
|
$url = constant('BASE_URL') . '/compta/prelevement/card.php?id=' . $this->id; |
1539
|
|
|
if (!empty($this->type) && $this->type == 'bank-transfer') { |
1540
|
|
|
$url = constant('BASE_URL') . '/compta/prelevement/card.php?id=' . $this->id; |
1541
|
|
|
} |
1542
|
|
|
|
1543
|
|
|
if ($option != 'nolink') { |
1544
|
|
|
// Add param to save lastsearch_values or not |
1545
|
|
|
$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); |
1546
|
|
|
if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) { |
1547
|
|
|
$add_save_lastsearch_values = 1; |
1548
|
|
|
} |
1549
|
|
|
if ($add_save_lastsearch_values) { |
1550
|
|
|
$url .= '&save_lastsearch_values=1'; |
1551
|
|
|
} |
1552
|
|
|
} |
1553
|
|
|
|
1554
|
|
|
$linkclose = ''; |
1555
|
|
|
if (empty($notooltip)) { |
1556
|
|
|
if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
1557
|
|
|
$label = $langs->trans("ShowMyObject"); |
1558
|
|
|
$linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"'; |
1559
|
|
|
} |
1560
|
|
|
$linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"'; |
1561
|
|
|
$linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"'; |
1562
|
|
|
} else { |
1563
|
|
|
$linkclose = ($morecss ? ' class="' . $morecss . '"' : ''); |
1564
|
|
|
} |
1565
|
|
|
|
1566
|
|
|
$linkstart = '<a href="' . $url . '"'; |
1567
|
|
|
$linkstart .= $linkclose . '>'; |
1568
|
|
|
$linkend = '</a>'; |
1569
|
|
|
|
1570
|
|
|
$result .= $linkstart; |
1571
|
|
|
if ($withpicto) { |
1572
|
|
|
$result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="' . (($withpicto != 2) ? 'paddingright ' : '') . 'classfortooltip"'), 0, 0, $notooltip ? 0 : 1); |
1573
|
|
|
} |
1574
|
|
|
if ($withpicto != 2) { |
1575
|
|
|
$result .= $this->ref; |
1576
|
|
|
} |
1577
|
|
|
$result .= $linkend; |
1578
|
|
|
|
1579
|
|
|
global $action, $hookmanager; |
1580
|
|
|
$hookmanager->initHooks(array('banktransferdao')); |
1581
|
|
|
$parameters = array('id' => $this->id, 'getnomurl' => &$result); |
1582
|
|
|
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks |
1583
|
|
|
if ($reshook > 0) { |
1584
|
|
|
$result = $hookmanager->resPrint; |
1585
|
|
|
} else { |
1586
|
|
|
$result .= $hookmanager->resPrint; |
1587
|
|
|
} |
1588
|
|
|
|
1589
|
|
|
return $result; |
1590
|
|
|
} |
1591
|
|
|
|
1592
|
|
|
|
1593
|
|
|
/** |
1594
|
|
|
* Delete a notification def by id |
1595
|
|
|
* |
1596
|
|
|
* @param int $rowid id of notification |
1597
|
|
|
* @return int 0 if OK, <0 if KO |
1598
|
|
|
*/ |
1599
|
|
|
public function deleteNotificationById($rowid) |
1600
|
|
|
{ |
1601
|
|
|
$sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def"; |
1602
|
|
|
$sql .= " WHERE rowid = " . ((int) $rowid); |
1603
|
|
|
|
1604
|
|
|
if ($this->db->query($sql)) { |
1605
|
|
|
return 0; |
1606
|
|
|
} else { |
1607
|
|
|
return -1; |
1608
|
|
|
} |
1609
|
|
|
} |
1610
|
|
|
|
1611
|
|
|
/** |
1612
|
|
|
* Delete a notification |
1613
|
|
|
* |
1614
|
|
|
* @param int|User $user notification user |
1615
|
|
|
* @param string $action notification action |
1616
|
|
|
* @return int >0 if OK, <0 if KO |
1617
|
|
|
*/ |
1618
|
|
|
public function deleteNotification($user, $action) |
1619
|
|
|
{ |
1620
|
|
|
if (is_object($user)) { |
1621
|
|
|
$userid = $user->id; |
1622
|
|
|
} else { // If user is an id |
1623
|
|
|
$userid = $user; |
1624
|
|
|
} |
1625
|
|
|
|
1626
|
|
|
$sql = "DELETE FROM " . MAIN_DB_PREFIX . "notify_def"; |
1627
|
|
|
$sql .= " WHERE fk_user=" . ((int) $userid) . " AND fk_action='" . $this->db->escape($action) . "'"; |
1628
|
|
|
|
1629
|
|
|
if ($this->db->query($sql)) { |
1630
|
|
|
return 0; |
1631
|
|
|
} else { |
1632
|
|
|
return -1; |
1633
|
|
|
} |
1634
|
|
|
} |
1635
|
|
|
|
1636
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
1637
|
|
|
/** |
1638
|
|
|
* Add a notification |
1639
|
|
|
* |
1640
|
|
|
* @param DoliDB $db database handler |
1641
|
|
|
* @param int|User $user notification user |
1642
|
|
|
* @param string $action notification action |
1643
|
|
|
* @return int 0 if OK, <0 if KO |
1644
|
|
|
*/ |
1645
|
|
|
public function addNotification($db, $user, $action) |
1646
|
|
|
{ |
1647
|
|
|
// phpcs:enable |
1648
|
|
|
$result = 0; |
1649
|
|
|
|
1650
|
|
|
if (is_object($user)) { |
1651
|
|
|
$userid = $user->id; |
1652
|
|
|
} else { // If user is an id |
1653
|
|
|
$userid = $user; |
1654
|
|
|
} |
1655
|
|
|
|
1656
|
|
|
if ($this->deleteNotification($user, $action) == 0) { |
1657
|
|
|
$now = dol_now(); |
1658
|
|
|
|
1659
|
|
|
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "notify_def (datec,fk_user, fk_soc, fk_contact, fk_action)"; |
1660
|
|
|
$sql .= " VALUES ('" . $this->db->idate($now) . "', " . ((int) $userid) . ", 'NULL', 'NULL', '" . $this->db->escape($action) . "')"; |
1661
|
|
|
|
1662
|
|
|
dol_syslog("adnotiff: " . $sql); |
1663
|
|
|
if ($this->db->query($sql)) { |
1664
|
|
|
$result = 0; |
1665
|
|
|
} else { |
1666
|
|
|
$result = -1; |
1667
|
|
|
dol_syslog(get_only_class($this) . "::addNotification Error $result"); |
1668
|
|
|
} |
1669
|
|
|
} |
1670
|
|
|
|
1671
|
|
|
return $result; |
1672
|
|
|
} |
1673
|
|
|
|
1674
|
|
|
|
1675
|
|
|
/** |
1676
|
|
|
* Generate a direct debit or credit transfer file. |
1677
|
|
|
* Generation Formats: |
1678
|
|
|
* - Europe: SEPA (France: CFONB no more supported, Spain: AEB19 if external module EsAEB is enabled) |
1679
|
|
|
* - Others countries: Warning message |
1680
|
|
|
* File is generated with name this->filename |
1681
|
|
|
* |
1682
|
|
|
* @param string $format FRST, RCUR or ALL |
1683
|
|
|
* @param int $executiondate Timestamp date to execute transfer |
1684
|
|
|
* @param string $type 'direct-debit' or 'bank-transfer' |
1685
|
|
|
* @param int $fk_bank_account Bank account ID the receipt is generated for. Will use the ID into the setup of module Direct Debit or Credit Transfer if 0. |
1686
|
|
|
* @param int $forsalary If the SEPA is to pay salaries |
1687
|
|
|
* @return int >=0 if OK, <0 if KO |
1688
|
|
|
*/ |
1689
|
|
|
public function generate($format = 'ALL', $executiondate = 0, $type = 'direct-debit', $fk_bank_account = 0, $forsalary = 0) |
1690
|
|
|
{ |
1691
|
|
|
global $conf, $langs, $mysoc; |
1692
|
|
|
|
1693
|
|
|
//TODO: Optimize code to read lines in a single function |
1694
|
|
|
|
1695
|
|
|
// Clean params |
1696
|
|
|
if (empty($fk_bank_account)) { |
1697
|
|
|
$fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT')); |
1698
|
|
|
} |
1699
|
|
|
|
1700
|
|
|
$result = 0; |
1701
|
|
|
|
1702
|
|
|
dol_syslog(get_only_class($this) . "::generate build file=" . $this->filename . " type=" . $type); |
1703
|
|
|
|
1704
|
|
|
$this->file = fopen($this->filename, "w"); |
1705
|
|
|
if ($this->file == false) { |
1706
|
|
|
$this->error = $langs->trans('ErrorFailedToOpenFile', $this->filename); |
1707
|
|
|
return -1; |
1708
|
|
|
} |
1709
|
|
|
|
1710
|
|
|
$found = 0; |
1711
|
|
|
$this->total = 0; |
1712
|
|
|
|
1713
|
|
|
// Build file for European countries |
1714
|
|
|
if ($mysoc->isInEEC()) { |
1715
|
|
|
$found++; |
1716
|
|
|
|
1717
|
|
|
if ($type != 'bank-transfer') { |
1718
|
|
|
/** |
1719
|
|
|
* SECTION CREATION FICHIER SEPA - DIRECT DEBIT |
1720
|
|
|
*/ |
1721
|
|
|
// SEPA Initialisation |
1722
|
|
|
$CrLf = "\n"; |
1723
|
|
|
|
1724
|
|
|
$now = dol_now(); |
1725
|
|
|
|
1726
|
|
|
$dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S'); |
1727
|
|
|
|
1728
|
|
|
$date_actu = $now; |
1729
|
|
|
if (!empty($executiondate)) { |
1730
|
|
|
$date_actu = $executiondate; |
1731
|
|
|
} |
1732
|
|
|
|
1733
|
|
|
$dateTime_YMD = dol_print_date($date_actu, '%Y%m%d'); |
1734
|
|
|
$dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S'); |
1735
|
|
|
$fileDebiteurSection = ''; |
1736
|
|
|
$fileEmetteurSection = ''; |
1737
|
|
|
$i = 0; |
1738
|
|
|
|
1739
|
|
|
/* |
1740
|
|
|
* Section Debitor (sepa Debiteurs block lines) |
1741
|
|
|
*/ |
1742
|
|
|
|
1743
|
|
|
$sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,"; |
1744
|
|
|
$sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,"; |
1745
|
|
|
$sql .= " f.ref as reffac, p.fk_facture as idfac,"; |
1746
|
|
|
$sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum"; |
1747
|
|
|
$sql .= " FROM"; |
1748
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,"; |
1749
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "facture as f,"; |
1750
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement as p,"; |
1751
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "societe as soc,"; |
1752
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "c_country as c,"; |
1753
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib"; |
1754
|
|
|
$sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id); |
1755
|
|
|
$sql .= " AND pl.rowid = p.fk_prelevement_lignes"; |
1756
|
|
|
$sql .= " AND p.fk_facture = f.rowid"; |
1757
|
|
|
$sql .= " AND f.fk_soc = soc.rowid"; |
1758
|
|
|
$sql .= " AND soc.fk_pays = c.rowid"; |
1759
|
|
|
$sql .= " AND rib.fk_soc = f.fk_soc"; |
1760
|
|
|
$sql .= " AND rib.default_rib = 1"; |
1761
|
|
|
$sql .= " AND rib.type = 'ban'"; |
1762
|
|
|
|
1763
|
|
|
// Define $fileDebiteurSection. One section DrctDbtTxInf per invoice. |
1764
|
|
|
$resql = $this->db->query($sql); |
1765
|
|
|
if ($resql) { |
1766
|
|
|
$cachearraytotestduplicate = array(); |
1767
|
|
|
|
1768
|
|
|
$num = $this->db->num_rows($resql); |
1769
|
|
|
while ($i < $num) { |
1770
|
|
|
$obj = $this->db->fetch_object($resql); |
1771
|
|
|
|
1772
|
|
|
if (!empty($cachearraytotestduplicate[$obj->idfac])) { |
1773
|
|
|
$this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid); |
1774
|
|
|
$this->invoice_in_error[$obj->idfac] = $this->error; |
1775
|
|
|
$result = -2; |
1776
|
|
|
break; |
1777
|
|
|
} |
1778
|
|
|
$cachearraytotestduplicate[$obj->idfac] = $obj->rowid; |
1779
|
|
|
|
1780
|
|
|
$daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec); |
1781
|
|
|
|
1782
|
|
|
$fileDebiteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $obj->reffac, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type); |
1783
|
|
|
|
1784
|
|
|
$this->total = $this->total + $obj->somme; |
1785
|
|
|
$i++; |
1786
|
|
|
} |
1787
|
|
|
$nbtotalDrctDbtTxInf = $i; |
1788
|
|
|
} else { |
1789
|
|
|
$this->error = $this->db->lasterror(); |
1790
|
|
|
fwrite($this->file, 'ERROR DEBITOR ' . $sql . $CrLf); // DEBITOR = Customers |
1791
|
|
|
$result = -2; |
1792
|
|
|
} |
1793
|
|
|
|
1794
|
|
|
// Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf |
1795
|
|
|
if ($result != -2) { |
1796
|
|
|
$fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type, $fk_bank_account); |
1797
|
|
|
} |
1798
|
|
|
|
1799
|
|
|
if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) { |
1800
|
|
|
$this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", ""); |
1801
|
|
|
} |
1802
|
|
|
|
1803
|
|
|
/** |
1804
|
|
|
* SECTION CREATION SEPA FILE - ISO200022 |
1805
|
|
|
*/ |
1806
|
|
|
// SEPA File Header |
1807
|
|
|
fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf); |
1808
|
|
|
fwrite($this->file, '<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.02" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' . $CrLf); |
1809
|
|
|
fwrite($this->file, ' <CstmrDrctDbtInitn>' . $CrLf); |
1810
|
|
|
// SEPA Group header |
1811
|
|
|
fwrite($this->file, ' <GrpHdr>' . $CrLf); |
1812
|
|
|
fwrite($this->file, ' <MsgId>' . ('DD/' . $dateTime_YMD . '/REF' . $this->id) . '</MsgId>' . $CrLf); |
1813
|
|
|
fwrite($this->file, ' <CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf); |
1814
|
|
|
fwrite($this->file, ' <NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf); |
1815
|
|
|
fwrite($this->file, ' <CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf); |
1816
|
|
|
fwrite($this->file, ' <InitgPty>' . $CrLf); |
1817
|
|
|
fwrite($this->file, ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf); |
1818
|
|
|
fwrite($this->file, ' <Id>' . $CrLf); |
1819
|
|
|
fwrite($this->file, ' <PrvtId>' . $CrLf); |
1820
|
|
|
fwrite($this->file, ' <Othr>' . $CrLf); |
1821
|
|
|
fwrite($this->file, ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf); |
1822
|
|
|
fwrite($this->file, ' </Othr>' . $CrLf); |
1823
|
|
|
fwrite($this->file, ' </PrvtId>' . $CrLf); |
1824
|
|
|
fwrite($this->file, ' </Id>' . $CrLf); |
1825
|
|
|
fwrite($this->file, ' </InitgPty>' . $CrLf); |
1826
|
|
|
fwrite($this->file, ' </GrpHdr>' . $CrLf); |
1827
|
|
|
// SEPA File Emetteur |
1828
|
|
|
if ($result != -2) { |
1829
|
|
|
fwrite($this->file, $fileEmetteurSection); |
1830
|
|
|
} |
1831
|
|
|
// SEPA File Debiteurs |
1832
|
|
|
if ($result != -2) { |
1833
|
|
|
fwrite($this->file, $fileDebiteurSection); |
1834
|
|
|
} |
1835
|
|
|
// SEPA FILE FOOTER |
1836
|
|
|
fwrite($this->file, ' </PmtInf>' . $CrLf); |
1837
|
|
|
fwrite($this->file, ' </CstmrDrctDbtInitn>' . $CrLf); |
1838
|
|
|
fwrite($this->file, '</Document>' . $CrLf); |
1839
|
|
|
} else { |
1840
|
|
|
/** |
1841
|
|
|
* SECTION CREATION FICHIER SEPA - CREDIT TRANSFER |
1842
|
|
|
*/ |
1843
|
|
|
// SEPA Initialisation |
1844
|
|
|
$CrLf = "\n"; |
1845
|
|
|
|
1846
|
|
|
$now = dol_now(); |
1847
|
|
|
|
1848
|
|
|
$dateTime_ECMA = dol_print_date($now, '%Y-%m-%dT%H:%M:%S'); |
1849
|
|
|
|
1850
|
|
|
$date_actu = $now; |
1851
|
|
|
if (!empty($executiondate)) { |
1852
|
|
|
$date_actu = $executiondate; |
1853
|
|
|
} |
1854
|
|
|
|
1855
|
|
|
$dateTime_YMD = dol_print_date($date_actu, '%Y%m%d'); |
1856
|
|
|
$dateTime_YMDHMS = dol_print_date($date_actu, '%Y%m%d%H%M%S'); |
1857
|
|
|
$fileCrediteurSection = ''; |
1858
|
|
|
$fileEmetteurSection = ''; |
1859
|
|
|
$i = 0; |
1860
|
|
|
|
1861
|
|
|
/* |
1862
|
|
|
* Section Creditor (sepa Crediteurs block lines) |
1863
|
|
|
*/ |
1864
|
|
|
if (!empty($forsalary)) { |
1865
|
|
|
$sql = "SELECT u.rowid as userId, u.address, u.zip, u.town, c.code as country_code, CONCAT(u.firstname,' ',u.lastname) as nom,"; |
1866
|
|
|
$sql .= " pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,"; |
1867
|
|
|
$sql .= " s.ref as reffac, p.fk_salary as idfac,"; |
1868
|
|
|
$sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, '' as rum, '' as date_rum"; |
1869
|
|
|
$sql .= " FROM"; |
1870
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,"; |
1871
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "salary as s,"; |
1872
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement as p,"; |
1873
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "user as u"; |
1874
|
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON u.fk_country = c.rowid,"; |
1875
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "user_rib as rib"; |
1876
|
|
|
$sql .= " WHERE pl.fk_prelevement_bons=" . ((int) $this->id); |
1877
|
|
|
$sql .= " AND pl.rowid = p.fk_prelevement_lignes"; |
1878
|
|
|
$sql .= " AND p.fk_salary = s.rowid"; |
1879
|
|
|
$sql .= " AND s.fk_user = u.rowid"; |
1880
|
|
|
$sql .= " AND rib.fk_user = s.fk_user"; |
1881
|
|
|
} else { |
1882
|
|
|
$sql = "SELECT soc.rowid as socid, soc.code_client as code, soc.address, soc.zip, soc.town, c.code as country_code,"; |
1883
|
|
|
$sql .= " pl.client_nom as nom, pl.code_banque as cb, pl.code_guichet as cg, pl.number as cc, pl.amount as somme,"; |
1884
|
|
|
$sql .= " f.ref as reffac, f.ref_supplier as fac_ref_supplier, p.fk_facture_fourn as idfac,"; |
1885
|
|
|
$sql .= " rib.rowid, rib.datec, rib.iban_prefix as iban, rib.bic as bic, rib.rowid as drum, rib.rum, rib.date_rum"; |
1886
|
|
|
$sql .= " FROM"; |
1887
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,"; |
1888
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,"; |
1889
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement as p,"; |
1890
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "societe as soc"; |
1891
|
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_country as c ON soc.fk_pays = c.rowid,"; |
1892
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "societe_rib as rib"; |
1893
|
|
|
$sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id); |
1894
|
|
|
$sql .= " AND pl.rowid = p.fk_prelevement_lignes"; |
1895
|
|
|
$sql .= " AND p.fk_facture_fourn = f.rowid"; |
1896
|
|
|
$sql .= " AND f.fk_soc = soc.rowid"; |
1897
|
|
|
$sql .= " AND rib.fk_soc = f.fk_soc"; |
1898
|
|
|
$sql .= " AND rib.default_rib = 1"; |
1899
|
|
|
$sql .= " AND rib.type = 'ban'"; |
1900
|
|
|
} |
1901
|
|
|
// Define $fileCrediteurSection. One section DrctDbtTxInf per invoice. |
1902
|
|
|
$resql = $this->db->query($sql); |
1903
|
|
|
if ($resql) { |
1904
|
|
|
$cachearraytotestduplicate = array(); |
1905
|
|
|
|
1906
|
|
|
$num = $this->db->num_rows($resql); |
1907
|
|
|
while ($i < $num) { |
1908
|
|
|
$obj = $this->db->fetch_object($resql); |
1909
|
|
|
if (!empty($cachearraytotestduplicate[$obj->idfac])) { |
1910
|
|
|
$this->error = $langs->trans('ErrorCompanyHasDuplicateDefaultBAN', $obj->socid); |
1911
|
|
|
$this->invoice_in_error[$obj->idfac] = $this->error; |
1912
|
|
|
$result = -2; |
1913
|
|
|
break; |
1914
|
|
|
} |
1915
|
|
|
$cachearraytotestduplicate[$obj->idfac] = $obj->rowid; |
1916
|
|
|
|
1917
|
|
|
$daterum = (!empty($obj->date_rum)) ? $this->db->jdate($obj->date_rum) : $this->db->jdate($obj->datec); |
1918
|
|
|
$refobj = $obj->reffac; |
1919
|
|
|
if (empty($refobj) && !empty($forsalary)) { // If ref of salary not defined, we force a value |
1920
|
|
|
$refobj = "SAL" . $obj->idfac; |
1921
|
|
|
} |
1922
|
|
|
|
1923
|
|
|
$fileCrediteurSection .= $this->EnregDestinataireSEPA($obj->code, $obj->nom, $obj->address, $obj->zip, $obj->town, $obj->country_code, $obj->cb, $obj->cg, $obj->cc, $obj->somme, $refobj, $obj->idfac, $obj->iban, $obj->bic, $daterum, $obj->drum, $obj->rum, $type, $obj->fac_ref_supplier); |
1924
|
|
|
|
1925
|
|
|
$this->total = $this->total + $obj->somme; |
1926
|
|
|
$i++; |
1927
|
|
|
} |
1928
|
|
|
$nbtotalDrctDbtTxInf = $i; |
1929
|
|
|
} else { |
1930
|
|
|
$this->error = $this->db->lasterror(); |
1931
|
|
|
fwrite($this->file, 'ERROR CREDITOR ' . $sql . $CrLf); // CREDITORS = Suppliers |
1932
|
|
|
$result = -2; |
1933
|
|
|
} |
1934
|
|
|
// Define $fileEmetteurSection. Start of block PmtInf. Will contains all $nbtotalDrctDbtTxInf |
1935
|
|
|
if ($result != -2) { |
1936
|
|
|
$fileEmetteurSection .= $this->EnregEmetteurSEPA($conf, $date_actu, $nbtotalDrctDbtTxInf, $this->total, $CrLf, $format, $type); |
1937
|
|
|
} |
1938
|
|
|
|
1939
|
|
|
if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) { |
1940
|
|
|
$this->total = number_format((float) price2num($this->total, 'MT'), 2, ".", ""); |
1941
|
|
|
} |
1942
|
|
|
|
1943
|
|
|
/** |
1944
|
|
|
* SECTION CREATION SEPA FILE - CREDIT TRANSFER - ISO200022 |
1945
|
|
|
*/ |
1946
|
|
|
// SEPA File Header |
1947
|
|
|
fwrite($this->file, '<' . '?xml version="1.0" encoding="UTF-8" standalone="yes"?' . '>' . $CrLf); |
1948
|
|
|
fwrite($this->file, '<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' . $CrLf); |
1949
|
|
|
fwrite($this->file, ' <CstmrCdtTrfInitn>' . $CrLf); |
1950
|
|
|
// SEPA Group header |
1951
|
|
|
fwrite($this->file, ' <GrpHdr>' . $CrLf); |
1952
|
|
|
fwrite($this->file, ' <MsgId>' . ('TRF/' . $dateTime_YMD . '/REF' . $this->id) . '</MsgId>' . $CrLf); |
1953
|
|
|
fwrite($this->file, ' <CreDtTm>' . $dateTime_ECMA . '</CreDtTm>' . $CrLf); |
1954
|
|
|
fwrite($this->file, ' <NbOfTxs>' . $i . '</NbOfTxs>' . $CrLf); |
1955
|
|
|
fwrite($this->file, ' <CtrlSum>' . $this->total . '</CtrlSum>' . $CrLf); |
1956
|
|
|
fwrite($this->file, ' <InitgPty>' . $CrLf); |
1957
|
|
|
fwrite($this->file, ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf); |
1958
|
|
|
fwrite($this->file, ' <Id>' . $CrLf); |
1959
|
|
|
fwrite($this->file, ' <PrvtId>' . $CrLf); |
1960
|
|
|
fwrite($this->file, ' <Othr>' . $CrLf); |
1961
|
|
|
fwrite($this->file, ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf); |
1962
|
|
|
fwrite($this->file, ' </Othr>' . $CrLf); |
1963
|
|
|
fwrite($this->file, ' </PrvtId>' . $CrLf); |
1964
|
|
|
fwrite($this->file, ' </Id>' . $CrLf); |
1965
|
|
|
fwrite($this->file, ' </InitgPty>' . $CrLf); |
1966
|
|
|
fwrite($this->file, ' </GrpHdr>' . $CrLf); |
1967
|
|
|
// SEPA File Emetteur (mycompany) |
1968
|
|
|
if ($result != -2) { |
1969
|
|
|
fwrite($this->file, $fileEmetteurSection); |
1970
|
|
|
} |
1971
|
|
|
// SEPA File Creditors |
1972
|
|
|
if ($result != -2) { |
1973
|
|
|
fwrite($this->file, $fileCrediteurSection); |
1974
|
|
|
} |
1975
|
|
|
// SEPA FILE FOOTER |
1976
|
|
|
fwrite($this->file, ' </PmtInf>' . $CrLf); |
1977
|
|
|
fwrite($this->file, ' </CstmrCdtTrfInitn>' . $CrLf); |
1978
|
|
|
fwrite($this->file, '</Document>' . $CrLf); |
1979
|
|
|
} |
1980
|
|
|
} |
1981
|
|
|
|
1982
|
|
|
// Build file for Other Countries with unknown format |
1983
|
|
|
if (!$found) { |
1984
|
|
|
if ($type != 'bank-transfer') { |
1985
|
|
|
$sql = "SELECT pl.amount"; |
1986
|
|
|
$sql .= " FROM"; |
1987
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,"; |
1988
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "facture as f,"; |
1989
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement as p"; |
1990
|
|
|
$sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id); |
1991
|
|
|
$sql .= " AND pl.rowid = p.fk_prelevement_lignes"; |
1992
|
|
|
$sql .= " AND p.fk_facture = f.rowid"; |
1993
|
|
|
|
1994
|
|
|
// Lines |
1995
|
|
|
$i = 0; |
1996
|
|
|
$resql = $this->db->query($sql); |
1997
|
|
|
if ($resql) { |
1998
|
|
|
$num = $this->db->num_rows($resql); |
1999
|
|
|
|
2000
|
|
|
while ($i < $num) { |
2001
|
|
|
$obj = $this->db->fetch_object($resql); |
2002
|
|
|
$this->total = $this->total + $obj->amount; |
2003
|
|
|
|
2004
|
|
|
// TODO Write record into file |
2005
|
|
|
$i++; |
2006
|
|
|
} |
2007
|
|
|
} else { |
2008
|
|
|
$result = -2; |
2009
|
|
|
} |
2010
|
|
|
} else { |
2011
|
|
|
$sql = "SELECT pl.amount"; |
2012
|
|
|
$sql .= " FROM"; |
2013
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement_lignes as pl,"; |
2014
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "facture_fourn as f,"; |
2015
|
|
|
$sql .= " " . MAIN_DB_PREFIX . "prelevement as p"; |
2016
|
|
|
$sql .= " WHERE pl.fk_prelevement_bons = " . ((int) $this->id); |
2017
|
|
|
$sql .= " AND pl.rowid = p.fk_prelevement_lignes"; |
2018
|
|
|
$sql .= " AND p.fk_facture_fourn = f.rowid"; |
2019
|
|
|
// Lines |
2020
|
|
|
$i = 0; |
2021
|
|
|
$resql = $this->db->query($sql); |
2022
|
|
|
if ($resql) { |
2023
|
|
|
$num = $this->db->num_rows($resql); |
2024
|
|
|
|
2025
|
|
|
while ($i < $num) { |
2026
|
|
|
$obj = $this->db->fetch_object($resql); |
2027
|
|
|
$this->total = $this->total + $obj->amount; |
2028
|
|
|
|
2029
|
|
|
// TODO Write record into file |
2030
|
|
|
$i++; |
2031
|
|
|
} |
2032
|
|
|
} else { |
2033
|
|
|
$result = -2; |
2034
|
|
|
} |
2035
|
|
|
} |
2036
|
|
|
|
2037
|
|
|
$langs->load('withdrawals'); |
2038
|
|
|
|
2039
|
|
|
// TODO Add here code to generate a generic file |
2040
|
|
|
fwrite($this->file, $langs->transnoentitiesnoconv('WithdrawalFileNotCapable', $mysoc->country_code)); |
2041
|
|
|
} |
2042
|
|
|
|
2043
|
|
|
fclose($this->file); |
2044
|
|
|
dolChmod($this->filename); |
2045
|
|
|
|
2046
|
|
|
return $result; |
2047
|
|
|
} |
2048
|
|
|
|
2049
|
|
|
|
2050
|
|
|
/** |
2051
|
|
|
* Generate dynamically a RUM number for a customer bank account |
2052
|
|
|
* |
2053
|
|
|
* @param string $row_code_client Customer code (soc.code_client) |
2054
|
|
|
* @param int $row_datec Creation date of bank account (rib.datec) |
2055
|
|
|
* @param string $row_drum Id of customer bank account (rib.rowid) |
2056
|
|
|
* @return string RUM number |
2057
|
|
|
*/ |
2058
|
|
|
public static function buildRumNumber($row_code_client, $row_datec, $row_drum) |
2059
|
|
|
{ |
2060
|
|
|
global $langs; |
2061
|
|
|
|
2062
|
|
|
$pre = substr(dol_string_nospecial(dol_string_unaccent($langs->transnoentitiesnoconv('RUM'))), 0, 3); // Must always be on 3 char ('RUM' or 'UMR'. This is a protection against bad translation) |
2063
|
|
|
|
2064
|
|
|
// 3 char + '-' + 12 + '-' + id + '-' + code Must be lower than 32. |
2065
|
|
|
return $pre . '-' . dol_print_date($row_datec, 'dayhourlogsmall') . '-' . dol_trunc($row_drum . ($row_code_client ? '-' . $row_code_client : ''), 13, 'right', 'UTF-8', 1); |
2066
|
|
|
} |
2067
|
|
|
|
2068
|
|
|
|
2069
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
2070
|
|
|
/** |
2071
|
|
|
* Write recipient of request (customer) |
2072
|
|
|
* |
2073
|
|
|
* @param int $rowid id of line |
2074
|
|
|
* @param string $client_nom name of customer |
2075
|
|
|
* @param string $rib_banque code of bank |
2076
|
|
|
* @param string $rib_guichet code of bank office |
2077
|
|
|
* @param string $rib_number bank account |
2078
|
|
|
* @param float $amount amount |
2079
|
|
|
* @param string $ref ref of invoice |
2080
|
|
|
* @param int $facid id of invoice |
2081
|
|
|
* @param string $rib_dom bank address |
2082
|
|
|
* @param string $type 'direct-debit' or 'bank-transfer' |
2083
|
|
|
* @return void |
2084
|
|
|
* @see EnregDestinataireSEPA() |
2085
|
|
|
*/ |
2086
|
|
|
public function EnregDestinataire($rowid, $client_nom, $rib_banque, $rib_guichet, $rib_number, $amount, $ref, $facid, $rib_dom = '', $type = 'direct-debit') |
2087
|
|
|
{ |
2088
|
|
|
// phpcs:enable |
2089
|
|
|
fwrite($this->file, "06"); |
2090
|
|
|
fwrite($this->file, "08"); // Prelevement ordinaire |
2091
|
|
|
|
2092
|
|
|
fwrite($this->file, " "); // Zone Reservee B2 |
2093
|
|
|
|
2094
|
|
|
fwrite($this->file, $this->emetteur_ics); // ICS |
2095
|
|
|
|
2096
|
|
|
// Date d'echeance C1 |
2097
|
|
|
|
2098
|
|
|
fwrite($this->file, " "); |
2099
|
|
|
fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt')); |
2100
|
|
|
fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1)); |
2101
|
|
|
|
2102
|
|
|
// Raison Sociale Destinataire C2 |
2103
|
|
|
|
2104
|
|
|
fwrite($this->file, substr(strtoupper($client_nom) . " ", 0, 24)); |
2105
|
|
|
|
2106
|
|
|
// Address optional D1 |
2107
|
|
|
$address = strtr($rib_dom, array(" " => "-", chr(13) => " ", chr(10) => "")); |
2108
|
|
|
fwrite($this->file, substr($address . " ", 0, 24)); |
2109
|
|
|
|
2110
|
|
|
// Zone Reservee D2 |
2111
|
|
|
|
2112
|
|
|
fwrite($this->file, substr(" ", 0, 8)); |
2113
|
|
|
|
2114
|
|
|
// Code Guichet D3 |
2115
|
|
|
|
2116
|
|
|
fwrite($this->file, $rib_guichet); |
2117
|
|
|
|
2118
|
|
|
// Numero de compte D4 |
2119
|
|
|
|
2120
|
|
|
fwrite($this->file, substr("000000000000000" . $rib_number, -11)); |
2121
|
|
|
|
2122
|
|
|
// Zone E Montant |
2123
|
|
|
|
2124
|
|
|
$montant = (round($amount, 2) * 100); |
2125
|
|
|
|
2126
|
|
|
fwrite($this->file, substr("000000000000000" . $montant, -16)); |
2127
|
|
|
|
2128
|
|
|
// Label F |
2129
|
|
|
|
2130
|
|
|
fwrite($this->file, substr("*_" . $ref . "_RDVnet" . $rowid . " ", 0, 31)); |
2131
|
|
|
|
2132
|
|
|
// Code etablissement G1 |
2133
|
|
|
|
2134
|
|
|
fwrite($this->file, $rib_banque); |
2135
|
|
|
|
2136
|
|
|
// Zone Reservee G2 |
2137
|
|
|
|
2138
|
|
|
fwrite($this->file, substr(" ", 0, 5)); |
2139
|
|
|
|
2140
|
|
|
fwrite($this->file, "\n"); |
2141
|
|
|
} |
2142
|
|
|
|
2143
|
|
|
|
2144
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
2145
|
|
|
/** |
2146
|
|
|
* Write recipient (thirdparty concerned by request) |
2147
|
|
|
* |
2148
|
|
|
* @param string $row_code_client soc.code_client as code, |
2149
|
|
|
* @param string $row_nom pl.client_nom AS name, |
2150
|
|
|
* @param string $row_address soc.address AS adr, |
2151
|
|
|
* @param string $row_zip soc.zip |
2152
|
|
|
* @param string $row_town soc.town |
2153
|
|
|
* @param string $row_country_code c.code AS country, |
2154
|
|
|
* @param string $row_cb pl.code_banque AS cb, Not used for SEPA |
2155
|
|
|
* @param string $row_cg pl.code_guichet AS cg, Not used for SEPA |
2156
|
|
|
* @param string $row_cc pl.number AS cc, Not used for SEPA |
2157
|
|
|
* @param float $row_somme pl.amount AS somme, |
2158
|
|
|
* @param string $row_ref Invoice ref (f.ref) or Salary ref |
2159
|
|
|
* @param int $row_idfac p.fk_facture AS idfac or p.fk_facture_fourn or p.fk_salary, |
2160
|
|
|
* @param string $row_iban rib.iban_prefix AS iban, |
2161
|
|
|
* @param string $row_bic rib.bic AS bic, |
2162
|
|
|
* @param string $row_datec rib.datec, |
2163
|
|
|
* @param string $row_drum rib.rowid used to generate rum |
2164
|
|
|
* @param string $row_rum rib.rum Rum defined on company bank account |
2165
|
|
|
* @param string $type 'direct-debit' or 'bank-transfer' |
2166
|
|
|
* @param string $row_comment A free text string for the Unstructured data field |
2167
|
|
|
* @return string Return string with SEPA part DrctDbtTxInf |
2168
|
|
|
* @see EnregDestinataire() |
2169
|
|
|
*/ |
2170
|
|
|
public function EnregDestinataireSEPA($row_code_client, $row_nom, $row_address, $row_zip, $row_town, $row_country_code, $row_cb, $row_cg, $row_cc, $row_somme, $row_ref, $row_idfac, $row_iban, $row_bic, $row_datec, $row_drum, $row_rum, $type = 'direct-debit', $row_comment = '') |
2171
|
|
|
{ |
2172
|
|
|
// phpcs:enable |
2173
|
|
|
global $conf; |
2174
|
|
|
|
2175
|
|
|
if (getDolGlobalString('SEPA_FORCE_TWO_DECIMAL')) { |
2176
|
|
|
$row_somme = number_format((float) price2num($row_somme, 'MT'), 2, ".", ""); |
2177
|
|
|
} else { |
2178
|
|
|
$row_somme = round((float) $row_somme, 2); |
2179
|
|
|
} |
2180
|
|
|
|
2181
|
|
|
include_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php'; |
2182
|
|
|
|
2183
|
|
|
$CrLf = "\n"; |
2184
|
|
|
$Rowing = sprintf("%010d", $row_idfac); |
2185
|
|
|
|
2186
|
|
|
// Define value for RUM |
2187
|
|
|
// Example: RUM-CustomerCode-CustomerBankAccountId-01424448606 (note: Date is the timestamp of the date of creation of CustomerBankAccountId) |
2188
|
|
|
$Rum = (empty($row_rum) ? $this->buildRumNumber($row_code_client, $row_datec, $row_drum) : $row_rum); |
2189
|
|
|
|
2190
|
|
|
// Define date of RUM signature |
2191
|
|
|
$DtOfSgntr = dol_print_date($row_datec, '%Y-%m-%d'); |
2192
|
|
|
|
2193
|
|
|
if ($type != 'bank-transfer') { |
2194
|
|
|
// SEPA Paiement Information of buyer for Direct Debit |
2195
|
|
|
$XML_DEBITOR = ''; |
2196
|
|
|
$XML_DEBITOR .= ' <DrctDbtTxInf>' . $CrLf; |
2197
|
|
|
$XML_DEBITOR .= ' <PmtId>' . $CrLf; |
2198
|
|
|
// Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum) |
2199
|
|
|
$XML_DEBITOR .= ' <EndToEndId>' . ((getDolGlobalString('PRELEVEMENT_END_TO_END') != "") ? $conf->global->PRELEVEMENT_END_TO_END : ('DD-' . dol_trunc($row_idfac . '-' . $row_ref, 20, 'right', 'UTF-8', 1)) . '-' . $Rowing) . '</EndToEndId>' . $CrLf; // ISO20022 states that EndToEndId has a MaxLength of 35 characters |
2200
|
|
|
$XML_DEBITOR .= ' </PmtId>' . $CrLf; |
2201
|
|
|
$XML_DEBITOR .= ' <InstdAmt Ccy="EUR">' . $row_somme . '</InstdAmt>' . $CrLf; |
2202
|
|
|
$XML_DEBITOR .= ' <DrctDbtTx>' . $CrLf; |
2203
|
|
|
$XML_DEBITOR .= ' <MndtRltdInf>' . $CrLf; |
2204
|
|
|
$XML_DEBITOR .= ' <MndtId>' . $Rum . '</MndtId>' . $CrLf; |
2205
|
|
|
$XML_DEBITOR .= ' <DtOfSgntr>' . $DtOfSgntr . '</DtOfSgntr>' . $CrLf; |
2206
|
|
|
$XML_DEBITOR .= ' <AmdmntInd>false</AmdmntInd>' . $CrLf; |
2207
|
|
|
$XML_DEBITOR .= ' </MndtRltdInf>' . $CrLf; |
2208
|
|
|
$XML_DEBITOR .= ' </DrctDbtTx>' . $CrLf; |
2209
|
|
|
$XML_DEBITOR .= ' <DbtrAgt>' . $CrLf; |
2210
|
|
|
$XML_DEBITOR .= ' <FinInstnId>' . $CrLf; |
2211
|
|
|
$XML_DEBITOR .= ' <BIC>' . $row_bic . '</BIC>' . $CrLf; |
2212
|
|
|
$XML_DEBITOR .= ' </FinInstnId>' . $CrLf; |
2213
|
|
|
$XML_DEBITOR .= ' </DbtrAgt>' . $CrLf; |
2214
|
|
|
$XML_DEBITOR .= ' <Dbtr>' . $CrLf; |
2215
|
|
|
$XML_DEBITOR .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf; |
2216
|
|
|
$XML_DEBITOR .= ' <PstlAdr>' . $CrLf; |
2217
|
|
|
$XML_DEBITOR .= ' <Ctry>' . $row_country_code . '</Ctry>' . $CrLf; |
2218
|
|
|
$addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => "")); |
2219
|
|
|
$addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => "")); |
2220
|
|
|
if (trim($addressline1)) { |
2221
|
|
|
$XML_DEBITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf; |
2222
|
|
|
} |
2223
|
|
|
if (trim($addressline2)) { |
2224
|
|
|
$XML_DEBITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf; |
2225
|
|
|
} |
2226
|
|
|
$XML_DEBITOR .= ' </PstlAdr>' . $CrLf; |
2227
|
|
|
$XML_DEBITOR .= ' </Dbtr>' . $CrLf; |
2228
|
|
|
$XML_DEBITOR .= ' <DbtrAcct>' . $CrLf; |
2229
|
|
|
$XML_DEBITOR .= ' <Id>' . $CrLf; |
2230
|
|
|
$XML_DEBITOR .= ' <IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf; |
2231
|
|
|
$XML_DEBITOR .= ' </Id>' . $CrLf; |
2232
|
|
|
$XML_DEBITOR .= ' </DbtrAcct>' . $CrLf; |
2233
|
|
|
$XML_DEBITOR .= ' <RmtInf>' . $CrLf; |
2234
|
|
|
// A string with some information on payment - 140 max |
2235
|
|
|
$XML_DEBITOR .= ' <Ustrd>' . getDolGlobalString('PRELEVEMENT_USTRD', dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($row_ref . ($row_comment ? ' - ' . $row_comment : '')), '', '', '', 1), 135, 'right', 'UTF-8', 1))) . '</Ustrd>' . $CrLf; // Free unstuctured data - 140 max |
2236
|
|
|
$XML_DEBITOR .= ' </RmtInf>' . $CrLf; |
2237
|
|
|
$XML_DEBITOR .= ' </DrctDbtTxInf>' . $CrLf; |
2238
|
|
|
return $XML_DEBITOR; |
2239
|
|
|
} else { |
2240
|
|
|
// SEPA Payment Information of seller for Credit Transfer |
2241
|
|
|
$XML_CREDITOR = ''; |
2242
|
|
|
$XML_CREDITOR .= ' <CdtTrfTxInf>' . $CrLf; |
2243
|
|
|
$XML_CREDITOR .= ' <PmtId>' . $CrLf; |
2244
|
|
|
// Add EndToEndId. Must be a unique ID for each payment (for example by including bank, buyer or seller, date, checksum) |
2245
|
|
|
$XML_CREDITOR .= ' <EndToEndId>' . ((getDolGlobalString('PRELEVEMENT_END_TO_END') != "") ? $conf->global->PRELEVEMENT_END_TO_END : ('CT-' . dol_trunc($row_idfac . '-' . $row_ref, 20, 'right', 'UTF-8', 1)) . '-' . $Rowing) . '</EndToEndId>' . $CrLf; // ISO20022 states that EndToEndId has a MaxLength of 35 characters |
2246
|
|
|
$XML_CREDITOR .= ' </PmtId>' . $CrLf; |
2247
|
|
|
if (!empty($this->sepa_xml_pti_in_ctti)) { |
2248
|
|
|
$XML_CREDITOR .= ' <PmtTpInf>' . $CrLf; |
2249
|
|
|
|
2250
|
|
|
// Can be 'NORM' for normal or 'HIGH' for high priority level |
2251
|
|
|
if (getDolGlobalString('PAYMENTBYBANKTRANSFER_FORCE_HIGH_PRIORITY')) { |
2252
|
|
|
$instrprty = 'HIGH'; |
2253
|
|
|
} else { |
2254
|
|
|
$instrprty = 'NORM'; |
2255
|
|
|
} |
2256
|
|
|
$XML_CREDITOR .= ' <InstrPrty>' . $instrprty . '</InstrPrty>' . $CrLf; |
2257
|
|
|
$XML_CREDITOR .= ' <SvcLvl>' . $CrLf; |
2258
|
|
|
$XML_CREDITOR .= ' <Cd>SEPA</Cd>' . $CrLf; |
2259
|
|
|
$XML_CREDITOR .= ' </SvcLvl>' . $CrLf; |
2260
|
|
|
$XML_CREDITOR .= ' <CtgyPurp>' . $CrLf; |
2261
|
|
|
$XML_CREDITOR .= ' <Cd>CORE</Cd>' . $CrLf; |
2262
|
|
|
$XML_CREDITOR .= ' </CtgyPurp>' . $CrLf; |
2263
|
|
|
$XML_CREDITOR .= ' </PmtTpInf>' . $CrLf; |
2264
|
|
|
} |
2265
|
|
|
$XML_CREDITOR .= ' <Amt>' . $CrLf; |
2266
|
|
|
$XML_CREDITOR .= ' <InstdAmt Ccy="EUR">' . round((float) $row_somme, 2) . '</InstdAmt>' . $CrLf; |
2267
|
|
|
$XML_CREDITOR .= ' </Amt>' . $CrLf; |
2268
|
|
|
/* |
2269
|
|
|
$XML_CREDITOR .= ' <DrctDbtTx>'.$CrLf; |
2270
|
|
|
$XML_CREDITOR .= ' <MndtRltdInf>'.$CrLf; |
2271
|
|
|
$XML_CREDITOR .= ' <MndtId>'.$Rum.'</MndtId>'.$CrLf; |
2272
|
|
|
$XML_CREDITOR .= ' <DtOfSgntr>'.$DtOfSgntr.'</DtOfSgntr>'.$CrLf; |
2273
|
|
|
$XML_CREDITOR .= ' <AmdmntInd>false</AmdmntInd>'.$CrLf; |
2274
|
|
|
$XML_CREDITOR .= ' </MndtRltdInf>'.$CrLf; |
2275
|
|
|
$XML_CREDITOR .= ' </DrctDbtTx>'.$CrLf; |
2276
|
|
|
*/ |
2277
|
|
|
//$XML_CREDITOR .= ' <ChrgBr>SLEV</ChrgBr>'.$CrLf; |
2278
|
|
|
$XML_CREDITOR .= ' <CdtrAgt>' . $CrLf; |
2279
|
|
|
$XML_CREDITOR .= ' <FinInstnId>' . $CrLf; |
2280
|
|
|
$XML_CREDITOR .= ' <BIC>' . $row_bic . '</BIC>' . $CrLf; |
2281
|
|
|
$XML_CREDITOR .= ' </FinInstnId>' . $CrLf; |
2282
|
|
|
$XML_CREDITOR .= ' </CdtrAgt>' . $CrLf; |
2283
|
|
|
$XML_CREDITOR .= ' <Cdtr>' . $CrLf; |
2284
|
|
|
$XML_CREDITOR .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '</Nm>' . $CrLf; |
2285
|
|
|
$XML_CREDITOR .= ' <PstlAdr>' . $CrLf; |
2286
|
|
|
$XML_CREDITOR .= ' <Ctry>' . $row_country_code . '</Ctry>' . $CrLf; |
2287
|
|
|
$addressline1 = strtr($row_address, array(chr(13) => ", ", chr(10) => "")); |
2288
|
|
|
$addressline2 = strtr($row_zip . (($row_zip && $row_town) ? ' ' : (string) $row_town), array(chr(13) => ", ", chr(10) => "")); |
2289
|
|
|
if (trim($addressline1)) { |
2290
|
|
|
$XML_CREDITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf; |
2291
|
|
|
} |
2292
|
|
|
if (trim($addressline2)) { |
2293
|
|
|
$XML_CREDITOR .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf; |
2294
|
|
|
} |
2295
|
|
|
$XML_CREDITOR .= ' </PstlAdr>' . $CrLf; |
2296
|
|
|
$XML_CREDITOR .= ' </Cdtr>' . $CrLf; |
2297
|
|
|
$XML_CREDITOR .= ' <CdtrAcct>' . $CrLf; |
2298
|
|
|
$XML_CREDITOR .= ' <Id>' . $CrLf; |
2299
|
|
|
$XML_CREDITOR .= ' <IBAN>' . preg_replace('/\s/', '', $row_iban) . '</IBAN>' . $CrLf; |
2300
|
|
|
$XML_CREDITOR .= ' </Id>' . $CrLf; |
2301
|
|
|
$XML_CREDITOR .= ' </CdtrAcct>' . $CrLf; |
2302
|
|
|
$XML_CREDITOR .= ' <RmtInf>' . $CrLf; |
2303
|
|
|
// A string with some information on payment - 140 max |
2304
|
|
|
$XML_CREDITOR .= ' <Ustrd>' . getDolGlobalString('CREDITTRANSFER_USTRD', dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($row_ref . ($row_comment ? ' - ' . $row_comment : '')), '', '', '', 1), 135, 'right', 'UTF-8', 1))) . '</Ustrd>' . $CrLf; // Free unstructured data - 140 max |
2305
|
|
|
$XML_CREDITOR .= ' </RmtInf>' . $CrLf; |
2306
|
|
|
$XML_CREDITOR .= ' </CdtTrfTxInf>' . $CrLf; |
2307
|
|
|
return $XML_CREDITOR; |
2308
|
|
|
} |
2309
|
|
|
} |
2310
|
|
|
|
2311
|
|
|
|
2312
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
2313
|
|
|
/** |
2314
|
|
|
* Write sender of request (me). |
2315
|
|
|
* |
2316
|
|
|
* @param string $type 'direct-debit' or 'bank-transfer' |
2317
|
|
|
* @return void |
2318
|
|
|
* @see EnregEmetteurSEPA() |
2319
|
|
|
*/ |
2320
|
|
|
public function EnregEmetteur($type = 'direct-debit') |
2321
|
|
|
{ |
2322
|
|
|
// phpcs:enable |
2323
|
|
|
fwrite($this->file, "03"); |
2324
|
|
|
fwrite($this->file, "08"); // Prelevement ordinaire |
2325
|
|
|
|
2326
|
|
|
fwrite($this->file, " "); // Zone Reservee B2 |
2327
|
|
|
|
2328
|
|
|
fwrite($this->file, $this->emetteur_ics); // ICS |
2329
|
|
|
|
2330
|
|
|
// Date d'echeance C1 |
2331
|
|
|
|
2332
|
|
|
fwrite($this->file, " "); |
2333
|
|
|
fwrite($this->file, dol_print_date($this->date_echeance, "%d%m", 'gmt')); |
2334
|
|
|
fwrite($this->file, substr(dol_print_date($this->date_echeance, "%y", 'gmt'), 1)); |
2335
|
|
|
|
2336
|
|
|
// Raison Sociale C2 |
2337
|
|
|
|
2338
|
|
|
fwrite($this->file, substr($this->raison_sociale . " ", 0, 24)); |
2339
|
|
|
|
2340
|
|
|
// Reference de la remise creancier D1 sur 7 caracteres |
2341
|
|
|
|
2342
|
|
|
fwrite($this->file, substr($this->reference_remise . " ", 0, 7)); |
2343
|
|
|
|
2344
|
|
|
// Zone Reservee D1-2 |
2345
|
|
|
|
2346
|
|
|
fwrite($this->file, substr(" ", 0, 17)); |
2347
|
|
|
|
2348
|
|
|
// Zone Reservee D2 |
2349
|
|
|
|
2350
|
|
|
fwrite($this->file, substr(" ", 0, 2)); |
2351
|
|
|
fwrite($this->file, "E"); |
2352
|
|
|
fwrite($this->file, substr(" ", 0, 5)); |
2353
|
|
|
|
2354
|
|
|
// Code Guichet D3 |
2355
|
|
|
|
2356
|
|
|
fwrite($this->file, $this->emetteur_code_guichet); |
2357
|
|
|
|
2358
|
|
|
// Numero de compte D4 |
2359
|
|
|
|
2360
|
|
|
fwrite($this->file, substr("000000000000000" . $this->emetteur_numero_compte, -11)); |
2361
|
|
|
|
2362
|
|
|
// Zone Reservee E |
2363
|
|
|
|
2364
|
|
|
fwrite($this->file, substr(" ", 0, 16)); |
2365
|
|
|
|
2366
|
|
|
// Zone Reservee F |
2367
|
|
|
|
2368
|
|
|
fwrite($this->file, substr(" ", 0, 31)); |
2369
|
|
|
|
2370
|
|
|
// Code etablissement |
2371
|
|
|
|
2372
|
|
|
fwrite($this->file, $this->emetteur_code_banque); |
2373
|
|
|
|
2374
|
|
|
// Zone Reservee G |
2375
|
|
|
|
2376
|
|
|
fwrite($this->file, substr(" ", 0, 5)); |
2377
|
|
|
|
2378
|
|
|
fwrite($this->file, "\n"); |
2379
|
|
|
} |
2380
|
|
|
|
2381
|
|
|
|
2382
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
2383
|
|
|
/** |
2384
|
|
|
* Write sender of request (me). |
2385
|
|
|
* Note: The tag PmtInf is opened here but closed into caller |
2386
|
|
|
* |
2387
|
|
|
* @param Conf $configuration conf |
2388
|
|
|
* @param int $ladate Date |
2389
|
|
|
* @param int $nombre 0 or 1 |
2390
|
|
|
* @param float $total Total |
2391
|
|
|
* @param string $CrLf End of line character |
2392
|
|
|
* @param string $format FRST or RCUR or ALL |
2393
|
|
|
* @param string $type 'direct-debit' or 'bank-transfer' |
2394
|
|
|
* @param int $fk_bank_account Bank account ID the receipt is generated for. Will use the ID into the setup of module Direct Debit or Credit Transfer if 0. |
2395
|
|
|
* @return string String with SEPA Sender |
2396
|
|
|
* @see EnregEmetteur() |
2397
|
|
|
*/ |
2398
|
|
|
public function EnregEmetteurSEPA($configuration, $ladate, $nombre, $total, $CrLf = '\n', $format = 'FRST', $type = 'direct-debit', $fk_bank_account = 0) |
2399
|
|
|
{ |
2400
|
|
|
// phpcs:enable |
2401
|
|
|
|
2402
|
|
|
// Clean parameters |
2403
|
|
|
$dateTime_YMD = dol_print_date($ladate, '%Y%m%d'); |
2404
|
|
|
$dateTime_ETAD = dol_print_date($ladate, '%Y-%m-%d'); |
2405
|
|
|
$dateTime_YMDHMS = dol_print_date($ladate, '%Y-%m-%dT%H:%M:%S'); |
2406
|
|
|
|
2407
|
|
|
// Clean params |
2408
|
|
|
if (empty($fk_bank_account)) { |
2409
|
|
|
$fk_bank_account = ($type == 'bank-transfer' ? getDolGlobalInt('PAYMENTBYBANKTRANSFER_ID_BANKACCOUNT') : getDolGlobalInt('PRELEVEMENT_ID_BANKACCOUNT')); |
2410
|
|
|
} |
2411
|
|
|
|
2412
|
|
|
// Get data of bank account |
2413
|
|
|
$account = new Account($this->db); |
2414
|
|
|
if ($account->fetch($fk_bank_account) > 0) { |
2415
|
|
|
$this->emetteur_code_banque = $account->code_banque; |
2416
|
|
|
$this->emetteur_code_guichet = $account->code_guichet; |
2417
|
|
|
$this->emetteur_numero_compte = $account->number; |
2418
|
|
|
$this->emetteur_number_key = $account->cle_rib; |
2419
|
|
|
$this->sepa_xml_pti_in_ctti = (bool) $account->pti_in_ctti; |
2420
|
|
|
$this->emetteur_iban = $account->iban; |
2421
|
|
|
$this->emetteur_bic = $account->bic; |
2422
|
|
|
|
2423
|
|
|
$this->emetteur_ics = (($type == 'bank-transfer' && getDolGlobalString("SEPA_USE_IDS")) ? $account->ics_transfer : $account->ics); // Ex: PRELEVEMENT_ICS = "FR78ZZZ123456"; |
2424
|
|
|
|
2425
|
|
|
$this->raison_sociale = $account->proprio; |
|
|
|
|
2426
|
|
|
} |
2427
|
|
|
|
2428
|
|
|
// Get pending payments |
2429
|
|
|
$sql = "SELECT rowid, ref"; |
2430
|
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "prelevement_bons as pb"; |
2431
|
|
|
$sql .= " WHERE pb.rowid = " . ((int) $this->id); |
2432
|
|
|
|
2433
|
|
|
$resql = $this->db->query($sql); |
2434
|
|
|
if ($resql) { |
2435
|
|
|
$obj = $this->db->fetch_object($resql); |
2436
|
|
|
|
2437
|
|
|
$country = explode(':', $configuration->global->MAIN_INFO_SOCIETE_COUNTRY); |
2438
|
|
|
$IdBon = sprintf("%05d", $obj->rowid); |
2439
|
|
|
$RefBon = $obj->ref; |
2440
|
|
|
|
2441
|
|
|
if (!empty($configuration->global->SEPA_FORCE_TWO_DECIMAL)) { |
2442
|
|
|
$total = number_format((float) price2num($total, 'MT'), 2, ".", ""); |
2443
|
|
|
} |
2444
|
|
|
|
2445
|
|
|
if ($type != 'bank-transfer') { |
2446
|
|
|
// SEPA Paiement Information of my company for Direct Debit |
2447
|
|
|
$XML_SEPA_INFO = ''; |
2448
|
|
|
$XML_SEPA_INFO .= ' <PmtInf>' . $CrLf; |
2449
|
|
|
$XML_SEPA_INFO .= ' <PmtInfId>' . ('DD/' . $dateTime_YMD . '/ID' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf; |
2450
|
|
|
$XML_SEPA_INFO .= ' <PmtMtd>DD</PmtMtd>' . $CrLf; |
2451
|
|
|
$XML_SEPA_INFO .= ' <NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf; |
2452
|
|
|
$XML_SEPA_INFO .= ' <CtrlSum>' . $total . '</CtrlSum>' . $CrLf; |
2453
|
|
|
$XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf; |
2454
|
|
|
$XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf; |
2455
|
|
|
$XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf; |
2456
|
|
|
$XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf; |
2457
|
|
|
$XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf; |
2458
|
|
|
$XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf; |
2459
|
|
|
$XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf; |
2460
|
|
|
$XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf; |
2461
|
|
|
$XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf; |
2462
|
|
|
$XML_SEPA_INFO .= ' <ReqdColltnDt>' . $dateTime_ETAD . '</ReqdColltnDt>' . $CrLf; |
2463
|
|
|
$XML_SEPA_INFO .= ' <Cdtr>' . $CrLf; |
2464
|
|
|
$XML_SEPA_INFO .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf; |
2465
|
|
|
$XML_SEPA_INFO .= ' <PstlAdr>' . $CrLf; |
2466
|
|
|
$XML_SEPA_INFO .= ' <Ctry>' . $country[1] . '</Ctry>' . $CrLf; |
2467
|
|
|
$addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => "")); |
2468
|
|
|
$addressline2 = strtr($configuration->global->MAIN_INFO_SOCIETE_ZIP . (($configuration->global->MAIN_INFO_SOCIETE_ZIP || ' ' . $configuration->global->MAIN_INFO_SOCIETE_TOWN) ? ' ' : '') . $configuration->global->MAIN_INFO_SOCIETE_TOWN, array(chr(13) => ", ", chr(10) => "")); |
2469
|
|
|
if ($addressline1) { |
2470
|
|
|
$XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf; |
2471
|
|
|
} |
2472
|
|
|
if ($addressline2) { |
2473
|
|
|
$XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf; |
2474
|
|
|
} |
2475
|
|
|
$XML_SEPA_INFO .= ' </PstlAdr>' . $CrLf; |
2476
|
|
|
$XML_SEPA_INFO .= ' </Cdtr>' . $CrLf; |
2477
|
|
|
$XML_SEPA_INFO .= ' <CdtrAcct>' . $CrLf; |
2478
|
|
|
$XML_SEPA_INFO .= ' <Id>' . $CrLf; |
2479
|
|
|
$XML_SEPA_INFO .= ' <IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf; |
2480
|
|
|
$XML_SEPA_INFO .= ' </Id>' . $CrLf; |
2481
|
|
|
$XML_SEPA_INFO .= ' </CdtrAcct>' . $CrLf; |
2482
|
|
|
$XML_SEPA_INFO .= ' <CdtrAgt>' . $CrLf; |
2483
|
|
|
$XML_SEPA_INFO .= ' <FinInstnId>' . $CrLf; |
2484
|
|
|
$XML_SEPA_INFO .= ' <BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf; |
2485
|
|
|
$XML_SEPA_INFO .= ' </FinInstnId>' . $CrLf; |
2486
|
|
|
$XML_SEPA_INFO .= ' </CdtrAgt>' . $CrLf; |
2487
|
|
|
/* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf; |
2488
|
|
|
$XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf; |
2489
|
|
|
$XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf; |
2490
|
|
|
$XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf; |
2491
|
|
|
$XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf; |
2492
|
|
|
$XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf; |
2493
|
|
|
$XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf; |
2494
|
|
|
$XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/ |
2495
|
|
|
$XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV |
2496
|
|
|
$XML_SEPA_INFO .= ' <CdtrSchmeId>' . $CrLf; |
2497
|
|
|
$XML_SEPA_INFO .= ' <Id>' . $CrLf; |
2498
|
|
|
$XML_SEPA_INFO .= ' <PrvtId>' . $CrLf; |
2499
|
|
|
$XML_SEPA_INFO .= ' <Othr>' . $CrLf; |
2500
|
|
|
$XML_SEPA_INFO .= ' <Id>' . $this->emetteur_ics . '</Id>' . $CrLf; |
2501
|
|
|
$XML_SEPA_INFO .= ' <SchmeNm>' . $CrLf; |
2502
|
|
|
$XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>' . $CrLf; |
2503
|
|
|
$XML_SEPA_INFO .= ' </SchmeNm>' . $CrLf; |
2504
|
|
|
$XML_SEPA_INFO .= ' </Othr>' . $CrLf; |
2505
|
|
|
$XML_SEPA_INFO .= ' </PrvtId>' . $CrLf; |
2506
|
|
|
$XML_SEPA_INFO .= ' </Id>' . $CrLf; |
2507
|
|
|
$XML_SEPA_INFO .= ' </CdtrSchmeId>' . $CrLf; |
2508
|
|
|
} else { |
2509
|
|
|
// SEPA Paiement Information of my company for Credit Transfer |
2510
|
|
|
$XML_SEPA_INFO = ''; |
2511
|
|
|
$XML_SEPA_INFO .= ' <PmtInf>' . $CrLf; |
2512
|
|
|
$XML_SEPA_INFO .= ' <PmtInfId>' . ('TRF/' . $dateTime_YMD . '/ID' . $IdBon . '-' . $RefBon) . '</PmtInfId>' . $CrLf; |
2513
|
|
|
$XML_SEPA_INFO .= ' <PmtMtd>TRF</PmtMtd>' . $CrLf; |
2514
|
|
|
//$XML_SEPA_INFO .= ' <BtchBookg>False</BtchBookg>'.$CrLf; |
2515
|
|
|
$XML_SEPA_INFO .= ' <NbOfTxs>' . $nombre . '</NbOfTxs>' . $CrLf; |
2516
|
|
|
$XML_SEPA_INFO .= ' <CtrlSum>' . $total . '</CtrlSum>' . $CrLf; |
2517
|
|
|
if (!empty($this->sepa_xml_pti_in_ctti) && !empty($format)) { // @TODO Using $format (FRST ou RCUR) in a section for a Credit Transfer looks strange. |
2518
|
|
|
$XML_SEPA_INFO .= ' <PmtTpInf>' . $CrLf; |
2519
|
|
|
$XML_SEPA_INFO .= ' <SvcLvl>' . $CrLf; |
2520
|
|
|
$XML_SEPA_INFO .= ' <Cd>SEPA</Cd>' . $CrLf; |
2521
|
|
|
$XML_SEPA_INFO .= ' </SvcLvl>' . $CrLf; |
2522
|
|
|
$XML_SEPA_INFO .= ' <LclInstrm>' . $CrLf; |
2523
|
|
|
$XML_SEPA_INFO .= ' <Cd>CORE</Cd>' . $CrLf; |
2524
|
|
|
$XML_SEPA_INFO .= ' </LclInstrm>' . $CrLf; |
2525
|
|
|
$XML_SEPA_INFO .= ' <SeqTp>' . $format . '</SeqTp>' . $CrLf; |
2526
|
|
|
$XML_SEPA_INFO .= ' </PmtTpInf>' . $CrLf; |
2527
|
|
|
} |
2528
|
|
|
$XML_SEPA_INFO .= ' <ReqdExctnDt>' . dol_print_date($dateTime_ETAD, 'dayrfc') . '</ReqdExctnDt>' . $CrLf; |
2529
|
|
|
$XML_SEPA_INFO .= ' <Dbtr>' . $CrLf; |
2530
|
|
|
$XML_SEPA_INFO .= ' <Nm>' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))) . '</Nm>' . $CrLf; |
2531
|
|
|
$XML_SEPA_INFO .= ' <PstlAdr>' . $CrLf; |
2532
|
|
|
$XML_SEPA_INFO .= ' <Ctry>' . $country[1] . '</Ctry>' . $CrLf; |
2533
|
|
|
$addressline1 = strtr($configuration->global->MAIN_INFO_SOCIETE_ADDRESS, array(chr(13) => ", ", chr(10) => "")); |
2534
|
|
|
$addressline2 = strtr($configuration->global->MAIN_INFO_SOCIETE_ZIP . (($configuration->global->MAIN_INFO_SOCIETE_ZIP || ' ' . $configuration->global->MAIN_INFO_SOCIETE_TOWN) ? ' ' : '') . $configuration->global->MAIN_INFO_SOCIETE_TOWN, array(chr(13) => ", ", chr(10) => "")); |
2535
|
|
|
if ($addressline1) { |
2536
|
|
|
$XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline1), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf; |
2537
|
|
|
} |
2538
|
|
|
if ($addressline2) { |
2539
|
|
|
$XML_SEPA_INFO .= ' <AdrLine>' . dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($addressline2), ' '), 70, 'right', 'UTF-8', 1)) . '</AdrLine>' . $CrLf; |
2540
|
|
|
} |
2541
|
|
|
$XML_SEPA_INFO .= ' </PstlAdr>' . $CrLf; |
2542
|
|
|
$XML_SEPA_INFO .= ' </Dbtr>' . $CrLf; |
2543
|
|
|
$XML_SEPA_INFO .= ' <DbtrAcct>' . $CrLf; |
2544
|
|
|
$XML_SEPA_INFO .= ' <Id>' . $CrLf; |
2545
|
|
|
$XML_SEPA_INFO .= ' <IBAN>' . preg_replace('/\s/', '', $this->emetteur_iban) . '</IBAN>' . $CrLf; |
2546
|
|
|
$XML_SEPA_INFO .= ' </Id>' . $CrLf; |
2547
|
|
|
$XML_SEPA_INFO .= ' </DbtrAcct>' . $CrLf; |
2548
|
|
|
$XML_SEPA_INFO .= ' <DbtrAgt>' . $CrLf; |
2549
|
|
|
$XML_SEPA_INFO .= ' <FinInstnId>' . $CrLf; |
2550
|
|
|
$XML_SEPA_INFO .= ' <BIC>' . $this->emetteur_bic . '</BIC>' . $CrLf; |
2551
|
|
|
$XML_SEPA_INFO .= ' </FinInstnId>' . $CrLf; |
2552
|
|
|
$XML_SEPA_INFO .= ' </DbtrAgt>' . $CrLf; |
2553
|
|
|
/* $XML_SEPA_INFO .= ' <UltmtCdtr>'.$CrLf; |
2554
|
|
|
$XML_SEPA_INFO .= ' <Nm>'.dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($this->raison_sociale), ' '))).'</Nm>'.$CrLf; |
2555
|
|
|
$XML_SEPA_INFO .= ' <PstlAdr>'.$CrLf; |
2556
|
|
|
$XML_SEPA_INFO .= ' <Ctry>'.$country[1].'</Ctry>'.$CrLf; |
2557
|
|
|
$XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ADDRESS), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf; |
2558
|
|
|
$XML_SEPA_INFO .= ' <AdrLine>'.dolEscapeXML(dol_trunc(dol_string_nospecial(dol_string_unaccent($conf->global->MAIN_INFO_SOCIETE_ZIP.' '.$conf->global->MAIN_INFO_SOCIETE_TOWN), ' '), 70, 'right', 'UTF-8', 1)).'</AdrLine>'.$CrLf; |
2559
|
|
|
$XML_SEPA_INFO .= ' </PstlAdr>'.$CrLf; |
2560
|
|
|
$XML_SEPA_INFO .= ' </UltmtCdtr>'.$CrLf;*/ |
2561
|
|
|
$XML_SEPA_INFO .= ' <ChrgBr>SLEV</ChrgBr>' . $CrLf; // Field "Responsible of fees". Must be SLEV |
2562
|
|
|
/*$XML_SEPA_INFO .= ' <CdtrSchmeId>'.$CrLf; |
2563
|
|
|
$XML_SEPA_INFO .= ' <Id>'.$CrLf; |
2564
|
|
|
$XML_SEPA_INFO .= ' <PrvtId>'.$CrLf; |
2565
|
|
|
$XML_SEPA_INFO .= ' <Othr>'.$CrLf; |
2566
|
|
|
$XML_SEPA_INFO .= ' <Id>'.$this->emetteur_ics.'</Id>'.$CrLf; |
2567
|
|
|
$XML_SEPA_INFO .= ' <SchmeNm>'.$CrLf; |
2568
|
|
|
$XML_SEPA_INFO .= ' <Prtry>SEPA</Prtry>'.$CrLf; |
2569
|
|
|
$XML_SEPA_INFO .= ' </SchmeNm>'.$CrLf; |
2570
|
|
|
$XML_SEPA_INFO .= ' </Othr>'.$CrLf; |
2571
|
|
|
$XML_SEPA_INFO .= ' </PrvtId>'.$CrLf; |
2572
|
|
|
$XML_SEPA_INFO .= ' </Id>'.$CrLf; |
2573
|
|
|
$XML_SEPA_INFO .= ' </CdtrSchmeId>'.$CrLf;*/ |
2574
|
|
|
} |
2575
|
|
|
} else { |
2576
|
|
|
fwrite($this->file, 'INCORRECT EMETTEUR ' . $this->raison_sociale . $CrLf); |
2577
|
|
|
$XML_SEPA_INFO = ''; |
2578
|
|
|
} |
2579
|
|
|
return $XML_SEPA_INFO; |
2580
|
|
|
} |
2581
|
|
|
|
2582
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
2583
|
|
|
/** |
2584
|
|
|
* Write end |
2585
|
|
|
* |
2586
|
|
|
* @param int $total total amount |
2587
|
|
|
* @return void |
2588
|
|
|
*/ |
2589
|
|
|
public function EnregTotal($total) |
2590
|
|
|
{ |
2591
|
|
|
// phpcs:enable |
2592
|
|
|
fwrite($this->file, "08"); |
2593
|
|
|
fwrite($this->file, "08"); // Prelevement ordinaire |
2594
|
|
|
|
2595
|
|
|
fwrite($this->file, " "); // Zone Reservee B2 |
2596
|
|
|
|
2597
|
|
|
fwrite($this->file, $this->emetteur_ics); // ICS |
2598
|
|
|
|
2599
|
|
|
// Reserve C1 |
2600
|
|
|
|
2601
|
|
|
fwrite($this->file, substr(" ", 0, 12)); |
2602
|
|
|
|
2603
|
|
|
|
2604
|
|
|
// Raison Sociale C2 |
2605
|
|
|
|
2606
|
|
|
fwrite($this->file, substr(" ", 0, 24)); |
2607
|
|
|
|
2608
|
|
|
// D1 |
2609
|
|
|
|
2610
|
|
|
fwrite($this->file, substr(" ", 0, 24)); |
2611
|
|
|
|
2612
|
|
|
// Zone Reservee D2 |
2613
|
|
|
|
2614
|
|
|
fwrite($this->file, substr(" ", 0, 8)); |
2615
|
|
|
|
2616
|
|
|
// Code Guichet D3 |
2617
|
|
|
|
2618
|
|
|
fwrite($this->file, substr(" ", 0, 5)); |
2619
|
|
|
|
2620
|
|
|
// Numero de compte D4 |
2621
|
|
|
|
2622
|
|
|
fwrite($this->file, substr(" ", 0, 11)); |
2623
|
|
|
|
2624
|
|
|
// Zone E Montant |
2625
|
|
|
|
2626
|
|
|
$montant = ($total * 100); |
2627
|
|
|
|
2628
|
|
|
fwrite($this->file, substr("000000000000000" . $montant, -16)); |
2629
|
|
|
|
2630
|
|
|
// Zone Reservee F |
2631
|
|
|
|
2632
|
|
|
fwrite($this->file, substr(" ", 0, 31)); |
2633
|
|
|
|
2634
|
|
|
// Code etablissement |
2635
|
|
|
|
2636
|
|
|
fwrite($this->file, substr(" ", 0, 5)); |
2637
|
|
|
|
2638
|
|
|
// Zone Reservee F |
2639
|
|
|
|
2640
|
|
|
fwrite($this->file, substr(" ", 0, 5)); |
2641
|
|
|
|
2642
|
|
|
fwrite($this->file, "\n"); |
2643
|
|
|
} |
2644
|
|
|
|
2645
|
|
|
/** |
2646
|
|
|
* Return status label of object |
2647
|
|
|
* |
2648
|
|
|
* @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 |
2649
|
|
|
* @return string Label |
2650
|
|
|
*/ |
2651
|
|
|
public function getLibStatut($mode = 0) |
2652
|
|
|
{ |
2653
|
|
|
return $this->LibStatut($this->statut, $mode); |
2654
|
|
|
} |
2655
|
|
|
|
2656
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
2657
|
|
|
/** |
2658
|
|
|
* Return status label for a status |
2659
|
|
|
* |
2660
|
|
|
* @param int $status Id status |
2661
|
|
|
* @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 |
2662
|
|
|
* @return string Label |
2663
|
|
|
*/ |
2664
|
|
|
public function LibStatut($status, $mode = 0) |
2665
|
|
|
{ |
2666
|
|
|
// phpcs:enable |
2667
|
|
|
if (empty($this->labelStatus) || empty($this->labelStatusShort)) { |
2668
|
|
|
global $langs; |
2669
|
|
|
//$langs->load("mymodule"); |
2670
|
|
|
$this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting'); |
2671
|
|
|
$this->labelStatus[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans'); |
2672
|
|
|
$this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusWaiting'); |
2673
|
|
|
$this->labelStatusShort[self::STATUS_TRANSFERED] = $langs->transnoentitiesnoconv('StatusTrans'); |
2674
|
|
|
if ($this->type == 'bank-transfer') { |
2675
|
|
|
$this->labelStatus[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited'); |
2676
|
|
|
$this->labelStatusShort[self::STATUS_DEBITED] = $langs->transnoentitiesnoconv('StatusDebited'); |
2677
|
|
|
} else { |
2678
|
|
|
$this->labelStatus[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited'); |
2679
|
|
|
$this->labelStatusShort[self::STATUS_CREDITED] = $langs->transnoentitiesnoconv('StatusCredited'); |
2680
|
|
|
} |
2681
|
|
|
} |
2682
|
|
|
|
2683
|
|
|
$statusType = 'status1'; |
2684
|
|
|
if ($status == self::STATUS_TRANSFERED) { |
2685
|
|
|
$statusType = 'status3'; |
2686
|
|
|
} |
2687
|
|
|
if ($status == self::STATUS_CREDITED || $status == self::STATUS_DEBITED) { |
2688
|
|
|
$statusType = 'status6'; |
2689
|
|
|
} |
2690
|
|
|
|
2691
|
|
|
return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); |
2692
|
|
|
} |
2693
|
|
|
|
2694
|
|
|
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
2695
|
|
|
/** |
2696
|
|
|
* Load indicators for dashboard (this->nbtodo and this->nbtodolate) |
2697
|
|
|
* |
2698
|
|
|
* @param User $user Object user |
2699
|
|
|
* @param string $mode Mode 'direct_debit' or 'credit_transfer' |
2700
|
|
|
* @return WorkboardResponse|int Return integer <0 if KO, WorkboardResponse if OK |
2701
|
|
|
*/ |
2702
|
|
|
public function load_board($user, $mode) |
2703
|
|
|
{ |
2704
|
|
|
// phpcs:enable |
2705
|
|
|
if ($user->socid) { |
2706
|
|
|
return -1; // protection pour eviter appel par utilisateur externe |
2707
|
|
|
} |
2708
|
|
|
|
2709
|
|
|
/* |
2710
|
|
|
if ($mode == 'direct_debit') { |
2711
|
|
|
$sql = "SELECT b.rowid, f.datedue as datefin"; |
2712
|
|
|
$sql .= " FROM ".MAIN_DB_PREFIX."facture as f"; |
2713
|
|
|
$sql .= " WHERE f.entity IN (".getEntity('facture').")"; |
2714
|
|
|
$sql .= " AND f.total_ttc > 0"; |
2715
|
|
|
} else { |
2716
|
|
|
$sql = "SELECT b.rowid, f.datedue as datefin"; |
2717
|
|
|
$sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as f"; |
2718
|
|
|
$sql .= " WHERE f.entity IN (".getEntity('facture_fourn').")"; |
2719
|
|
|
$sql .= " AND f.total_ttc > 0"; |
2720
|
|
|
} |
2721
|
|
|
|
2722
|
|
|
$resql = $this->db->query($sql); |
2723
|
|
|
if ($resql) { |
2724
|
|
|
$langs->load("banks"); |
2725
|
|
|
$now = dol_now(); |
2726
|
|
|
|
2727
|
|
|
$response = new WorkboardResponse(); |
2728
|
|
|
if ($mode == 'direct_debit') { |
2729
|
|
|
$response->warning_delay = $conf->prelevement->warning_delay / 60 / 60 / 24; |
2730
|
|
|
$response->label = $langs->trans("PendingDirectDebitToComplete"); |
2731
|
|
|
$response->labelShort = $langs->trans("PendingDirectDebitToCompleteShort"); |
2732
|
|
|
$response->url = DOL_URL_ROOT.'/compta/prelevement/index.php?leftmenu=checks&mainmenu=bank'; |
2733
|
|
|
} else { |
2734
|
|
|
$response->warning_delay = $conf->paymentbybanktransfer->warning_delay / 60 / 60 / 24; |
2735
|
|
|
$response->label = $langs->trans("PendingCreditTransferToComplete"); |
2736
|
|
|
$response->labelShort = $langs->trans("PendingCreditTransferToCompleteShort"); |
2737
|
|
|
$response->url = DOL_URL_ROOT.'/compta/paymentbybanktransfer/index.php?leftmenu=checks&mainmenu=bank'; |
2738
|
|
|
} |
2739
|
|
|
$response->img = img_object('', "payment"); |
2740
|
|
|
|
2741
|
|
|
while ($obj = $this->db->fetch_object($resql)) { |
2742
|
|
|
$response->nbtodo++; |
2743
|
|
|
|
2744
|
|
|
if ($this->db->jdate($obj->datefin) < ($now - $conf->withdraw->warning_delay)) { |
2745
|
|
|
$response->nbtodolate++; |
2746
|
|
|
} |
2747
|
|
|
} |
2748
|
|
|
|
2749
|
|
|
$response->nbtodo = 0; |
2750
|
|
|
$response->nbtodolate = 0; |
2751
|
|
|
// Return workboard only if quantity is not 0 |
2752
|
|
|
if ($response->nbtodo) { |
2753
|
|
|
return $response; |
2754
|
|
|
} else { |
2755
|
|
|
return 0; |
2756
|
|
|
} |
2757
|
|
|
} else { |
2758
|
|
|
dol_print_error($this->db); |
2759
|
|
|
$this->error = $this->db->error(); |
2760
|
|
|
return -1; |
2761
|
|
|
} |
2762
|
|
|
*/ |
2763
|
|
|
return 0; |
2764
|
|
|
} |
2765
|
|
|
|
2766
|
|
|
/** |
2767
|
|
|
* Return clicable link of object (with eventually picto) |
2768
|
|
|
* |
2769
|
|
|
* @param string $option Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link) |
2770
|
|
|
* @param array $arraydata Array of data |
2771
|
|
|
* @return string HTML Code for Kanban thumb. |
2772
|
|
|
*/ |
2773
|
|
|
public function getKanbanView($option = '', $arraydata = null) |
2774
|
|
|
{ |
2775
|
|
|
global $langs; |
2776
|
|
|
|
2777
|
|
|
$selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']); |
2778
|
|
|
|
2779
|
|
|
$return = '<div class="box-flex-item box-flex-grow-zero">'; |
2780
|
|
|
$return .= '<div class="info-box info-box-sm">'; |
2781
|
|
|
$return .= '<span class="info-box-icon bg-infobox-action">'; |
2782
|
|
|
$return .= img_picto('', $this->picto); |
2783
|
|
|
$return .= '</span>'; |
2784
|
|
|
$return .= '<div class="info-box-content">'; |
2785
|
|
|
$return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . (method_exists($this, 'getNomUrl') ? $this->getNomUrl(1) : $this->ref) . '</span>'; |
2786
|
|
|
if ($selected >= 0) { |
2787
|
|
|
$return .= '<input id="cb' . $this->id . '" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="' . $this->id . '"' . ($selected ? ' checked="checked"' : '') . '>'; |
2788
|
|
|
} |
2789
|
|
|
if (property_exists($this, 'date_echeance')) { |
2790
|
|
|
$return .= '<br><span class="opacitymedium">' . $langs->trans("Date") . '</span> : <span class="info-box-label">' . dol_print_date($this->db->jdate($this->date_echeance), 'day') . '</span>'; |
2791
|
|
|
} |
2792
|
|
|
if (property_exists($this, 'total')) { |
2793
|
|
|
$return .= '<br><span class="opacitymedium">' . $langs->trans("Amount") . '</span> : <span class="amount">' . price($this->total) . '</span>'; |
2794
|
|
|
} |
2795
|
|
|
if (method_exists($this, 'LibStatut')) { |
2796
|
|
|
$return .= '<br><div class="info-box-status">' . $this->getLibStatut(3) . '</div>'; |
2797
|
|
|
} |
2798
|
|
|
$return .= '</div>'; |
2799
|
|
|
$return .= '</div>'; |
2800
|
|
|
$return .= '</div>'; |
2801
|
|
|
return $return; |
2802
|
|
|
} |
2803
|
|
|
|
2804
|
|
|
/** |
2805
|
|
|
* Check if is bon prelevement for salary invoice |
2806
|
|
|
* |
2807
|
|
|
* @return int 1 if OK, O if K0 |
2808
|
|
|
*/ |
2809
|
|
|
public function checkIfSalaryBonPrelevement() |
2810
|
|
|
{ |
2811
|
|
|
if (!empty($this->id)) { |
2812
|
|
|
$id = $this->id; |
2813
|
|
|
} else { |
2814
|
|
|
return 0; |
2815
|
|
|
} |
2816
|
|
|
if ($id) { |
2817
|
|
|
$sql = "SELECT COUNT(*) AS nb FROM " . MAIN_DB_PREFIX . "prelevement_lignes"; |
2818
|
|
|
$sql .= " WHERE fk_prelevement_bons = " . ((int) $id); |
2819
|
|
|
$sql .= " AND fk_soc = 0"; // fk_soc can't be NULL |
2820
|
|
|
$sql .= " AND fk_user IS NOT NULL"; |
2821
|
|
|
|
2822
|
|
|
$num = 0; |
2823
|
|
|
$resql = $this->db->query($sql); |
2824
|
|
|
if ($resql) { |
2825
|
|
|
$obj = $this->db->fetch_object($resql); |
2826
|
|
|
$num = $obj->nb; |
2827
|
|
|
} |
2828
|
|
|
if ($num > 0) { |
2829
|
|
|
return 1; |
2830
|
|
|
} |
2831
|
|
|
} else { |
2832
|
|
|
dol_print_error($this->db); |
2833
|
|
|
} |
2834
|
|
|
|
2835
|
|
|
return 0; |
2836
|
|
|
} |
2837
|
|
|
} |
2838
|
|
|
|