Passed
Pull Request — dev (#8)
by Rafael
58:47
created

AccountancyExport   F

Complexity

Total Complexity 295

Size/Duplication

Total Lines 2599
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 1433
dl 0
loc 2599
rs 0.8
c 0
b 0
f 0
wmc 295

28 Methods

Rating   Name   Duplication   Size   Complexity  
F exportFEC() 0 197 25
B getTypeConfig() 0 94 1
A exportAgiris() 0 36 4
F exportFEC2() 0 195 25
B exportiSuiteExpert() 0 49 6
A exportCiel() 0 37 4
A exportEbp() 0 31 4
B exportBob50() 0 36 6
C exportLDCompta() 0 126 12
F exportSAGE50SWISS() 0 143 24
A exportConfigurable() 0 27 4
B exportCogilog() 0 51 8
F exportQuadratus() 0 206 29
A toAnsi() 0 7 3
B exportGestimumV5() 0 37 7
A exportCoala() 0 26 3
A getMimeType() 0 12 2
A exportCegid() 0 24 3
A __construct() 0 9 3
A trunc() 0 3 1
A getFormatCode() 0 31 1
D exportGestimumV3() 0 98 21
F export() 0 256 61
B exportCharlemagne() 0 67 5
A getType() 0 53 4
F exportLDCompta10() 0 270 20
A exportOpenConcerto() 0 27 4
A exportWinfic() 0 71 5

How to fix   Complexity   

Complex Class

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

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

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

1
<?php
2
3
/*
4
 * Copyright (C) 2007-2012  Laurent Destailleur         <[email protected]>
5
 * Copyright (C) 2014       Juanjo Menent               <[email protected]>
6
 * Copyright (C) 2015       Florian Henry               <[email protected]>
7
 * Copyright (C) 2015       Raphaël Doursenaud          <[email protected]>
8
 * Copyright (C) 2016       Pierre-Henry Favre          <[email protected]>
9
 * Copyright (C) 2016-2024  Alexandre Spangaro          <[email protected]>
10
 * Copyright (C) 2022  		Lionel Vessiller            <[email protected]>
11
 * Copyright (C) 2013-2017  Olivier Geffroy             <[email protected]>
12
 * Copyright (C) 2017       Elarifr. Ari Elbaz          <[email protected]>
13
 * Copyright (C) 2017-2019  Frédéric France             <[email protected]>
14
 * Copyright (C) 2017       André Schild                <[email protected]>
15
 * Copyright (C) 2020       Guillaume Alexandre         <[email protected]>
16
 * Copyright (C) 2022		Joachim Kueter		        <[email protected]>
17
 * Copyright (C) 2022  		Progiseize         	        <[email protected]>
18
 * Copyright (C) 2024		MDW							<[email protected]>
19
 * Copyright (C) 2024       Rafael San José             <[email protected]>
20
 *
21
 * This program is free software; you can redistribute it and/or modify
22
 * it under the terms of the GNU General Public License as published by
23
 * the Free Software Foundation; either version 3 of the License, or
24
 * (at your option) any later version.
25
 *
26
 * This program is distributed in the hope that it will be useful,
27
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
 * GNU General Public License for more details.
30
 *
31
 * You should have received a copy of the GNU General Public License
32
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
33
 */
34
35
namespace Dolibarr\Code\Accountancy\Classes;
36
37
use DoliDB;
38
39
/**
40
 * \file        htdocs/accountancy/class/accountancyexport.class.php
41
 * \ingroup     Accountancy (Double entries)
42
 * \brief       Class accountancy export
43
 */
44
45
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/functions.lib.php';
46
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/functions2.lib.php';
47
48
use Dolibarr\Code\Core\Classes\HookManager;
49
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
50
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/accounting.lib.php';
51
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/date.lib.php';
52
53
/**
54
 * Manage the different format accountancy export
55
 */
56
class AccountancyExport
57
{
58
    // Types of export.
59
    public static $EXPORT_TYPE_CONFIGURABLE = 1; // CSV
60
    public static $EXPORT_TYPE_AGIRIS = 10;
61
    public static $EXPORT_TYPE_EBP = 15;
62
    public static $EXPORT_TYPE_CEGID = 20;
63
    public static $EXPORT_TYPE_COGILOG = 25;
64
    public static $EXPORT_TYPE_COALA = 30;
65
    public static $EXPORT_TYPE_BOB50 = 35;
66
    public static $EXPORT_TYPE_CIEL = 40;
67
    public static $EXPORT_TYPE_SAGE50_SWISS = 45;
68
    public static $EXPORT_TYPE_CHARLEMAGNE = 50;
69
    public static $EXPORT_TYPE_QUADRATUS = 60;
70
    public static $EXPORT_TYPE_WINFIC = 70;
71
    public static $EXPORT_TYPE_OPENCONCERTO = 100;
72
    public static $EXPORT_TYPE_LDCOMPTA = 110;
73
    public static $EXPORT_TYPE_LDCOMPTA10 = 120;
74
    public static $EXPORT_TYPE_GESTIMUMV3 = 130;
75
    public static $EXPORT_TYPE_GESTIMUMV5 = 135;
76
    public static $EXPORT_TYPE_ISUITEEXPERT = 200;
77
    // Generic FEC after that
78
    public static $EXPORT_TYPE_FEC = 1000;
79
    public static $EXPORT_TYPE_FEC2 = 1010;
80
81
    /**
82
     * @var DoliDB  Database handler
83
     */
84
    public $db;
85
86
    /**
87
     * @var string[] Error codes (or messages)
88
     */
89
    public $errors = array();
90
91
    /**
92
     * @var string  Separator
93
     */
94
    public $separator = '';
95
96
    /**
97
     * @var string  End of line
98
     */
99
    public $end_line = '';
100
101
    /**
102
     * @var array   Generated file
103
     */
104
    public $generatedfiledata = array();
105
106
107
    /**
108
     * Constructor
109
     *
110
     * @param DoliDB $db Database handler
111
     */
112
    public function __construct(DoliDB $db)
113
    {
114
        global $conf, $hookmanager;
115
116
        $this->db = $db;
117
        $this->separator = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
118
        $this->end_line = getDolGlobalString('ACCOUNTING_EXPORT_ENDLINE') ? (getDolGlobalInt('ACCOUNTING_EXPORT_ENDLINE') == 1 ? "\n" : "\r\n") : "\n";
119
120
        $hookmanager->initHooks(array('accountancyexport'));
121
    }
122
123
    /**
124
     * Array with all export type available (key + label)
125
     *
126
     * @param   int     $mode       Mode of list: 0=flat list, 1=rich list
127
     * @return                      array of type
128
     */
129
    public function getType($mode = 0)
130
    {
131
        global $langs, $hookmanager;
132
133
        $listofspecialformatexport = array(
134
            self::$EXPORT_TYPE_CEGID => $langs->trans('Modelcsv_CEGID'),
135
            self::$EXPORT_TYPE_COALA => $langs->trans('Modelcsv_COALA'),
136
            self::$EXPORT_TYPE_BOB50 => $langs->trans('Modelcsv_bob50'),
137
            self::$EXPORT_TYPE_CIEL => $langs->trans('Modelcsv_ciel'),
138
            self::$EXPORT_TYPE_QUADRATUS => $langs->trans('Modelcsv_quadratus'),
139
            self::$EXPORT_TYPE_WINFIC => $langs->trans('Modelcsv_winfic'),
140
            self::$EXPORT_TYPE_EBP => $langs->trans('Modelcsv_ebp'),
141
            self::$EXPORT_TYPE_COGILOG => $langs->trans('Modelcsv_cogilog'),
142
            self::$EXPORT_TYPE_AGIRIS => $langs->trans('Modelcsv_agiris'),
143
            self::$EXPORT_TYPE_OPENCONCERTO => $langs->trans('Modelcsv_openconcerto'),
144
            self::$EXPORT_TYPE_SAGE50_SWISS => $langs->trans('Modelcsv_Sage50_Swiss'),
145
            self::$EXPORT_TYPE_CHARLEMAGNE => $langs->trans('Modelcsv_charlemagne'),
146
            self::$EXPORT_TYPE_LDCOMPTA => $langs->trans('Modelcsv_LDCompta'),
147
            self::$EXPORT_TYPE_LDCOMPTA10 => $langs->trans('Modelcsv_LDCompta10'),
148
            self::$EXPORT_TYPE_GESTIMUMV3 => $langs->trans('Modelcsv_Gestinumv3'),
149
            self::$EXPORT_TYPE_GESTIMUMV5 => $langs->trans('Modelcsv_Gestinumv5'),
150
            self::$EXPORT_TYPE_ISUITEEXPERT => 'Export iSuite Expert',
151
        );
152
153
        $listofgenericformatexport = array(
154
            self::$EXPORT_TYPE_CONFIGURABLE => $langs->trans('Modelcsv_configurable'),
155
            self::$EXPORT_TYPE_FEC => $langs->trans('Modelcsv_FEC'),
156
            self::$EXPORT_TYPE_FEC2 => $langs->trans('Modelcsv_FEC2'),
157
        );
158
159
        if (empty($mode)) {
160
            $listofexporttypes = $listofgenericformatexport + $listofspecialformatexport;
161
            ksort($listofexporttypes, SORT_NUMERIC);
162
        } else {
163
            ksort($listofspecialformatexport, SORT_NUMERIC);
164
            $listofexporttypes = array();
165
            $i = 0;
166
            foreach ($listofgenericformatexport as $key => $val) {
167
                $i++;
168
                $listofexporttypes[$key] = array('id' => $key, 'label' => $val, 'position' => $i);
169
            }
170
            $listofexporttypes['separator_' . $i] = array('id' => 0, 'label' => '----------------', 'position' => $i, 'disabled' => 'disabled');
171
            foreach ($listofspecialformatexport as $key => $val) {
172
                $i++;
173
                $listofexporttypes[$key] = array('id' => $key, 'label' => $val, 'position' => $i);
174
            }
175
        }
176
177
        // allow modules to define export formats
178
        $parameters = array();
179
        $reshook = $hookmanager->executeHooks('getType', $parameters, $listofexporttypes);
180
181
        return $listofexporttypes;
182
    }
183
184
    /**
185
     * Return string to summarize the format (Used to generated export filename)
186
     *
187
     * @param   int     $type       Format id
188
     * @return  string              Format code
189
     */
190
    public static function getFormatCode($type)
191
    {
192
        $formatcode = array(
193
            self::$EXPORT_TYPE_CONFIGURABLE => 'csv',
194
            self::$EXPORT_TYPE_CEGID => 'cegid',
195
            self::$EXPORT_TYPE_COALA => 'coala',
196
            self::$EXPORT_TYPE_BOB50 => 'bob50',
197
            self::$EXPORT_TYPE_CIEL => 'ciel',
198
            self::$EXPORT_TYPE_QUADRATUS => 'quadratus',
199
            self::$EXPORT_TYPE_WINFIC => 'winfic',
200
            self::$EXPORT_TYPE_EBP => 'ebp',
201
            self::$EXPORT_TYPE_COGILOG => 'cogilog',
202
            self::$EXPORT_TYPE_AGIRIS => 'agiris',
203
            self::$EXPORT_TYPE_OPENCONCERTO => 'openconcerto',
204
            self::$EXPORT_TYPE_SAGE50_SWISS => 'sage50ch',
205
            self::$EXPORT_TYPE_CHARLEMAGNE => 'charlemagne',
206
            self::$EXPORT_TYPE_LDCOMPTA => 'ldcompta',
207
            self::$EXPORT_TYPE_LDCOMPTA10 => 'ldcompta10',
208
            self::$EXPORT_TYPE_GESTIMUMV3 => 'gestimumv3',
209
            self::$EXPORT_TYPE_GESTIMUMV5 => 'gestimumv5',
210
            self::$EXPORT_TYPE_FEC => 'fec',
211
            self::$EXPORT_TYPE_FEC2 => 'fec2',
212
            self::$EXPORT_TYPE_ISUITEEXPERT => 'isuiteexpert',
213
        );
214
215
        global $hookmanager;
216
        $code = $formatcode[$type];
217
        $parameters = array('type' => $type);
218
        $reshook = $hookmanager->executeHooks('getFormatCode', $parameters, $code);
219
220
        return $code;
221
    }
222
223
    /**
224
     * Array with all export type available (key + label) and parameters for config
225
     *
226
     * @return array of type
227
     */
228
    public function getTypeConfig()
229
    {
230
        global $langs;
231
232
        $exporttypes = array(
233
            'param' => array(
234
                self::$EXPORT_TYPE_CONFIGURABLE => array(
235
                    'label' => $langs->trans('Modelcsv_configurable'),
236
                    'ACCOUNTING_EXPORT_FORMAT' => getDolGlobalString('ACCOUNTING_EXPORT_FORMAT', 'txt'),
237
                    'ACCOUNTING_EXPORT_SEPARATORCSV' => getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV', ','),
238
                    'ACCOUNTING_EXPORT_ENDLINE' => getDolGlobalString('ACCOUNTING_EXPORT_ENDLINE', 1),
239
                    'ACCOUNTING_EXPORT_DATE' => getDolGlobalString('ACCOUNTING_EXPORT_DATE', '%Y-%m-%d'),
240
                ),
241
                self::$EXPORT_TYPE_CEGID => array(
242
                    'label' => $langs->trans('Modelcsv_CEGID'),
243
                ),
244
                self::$EXPORT_TYPE_COALA => array(
245
                    'label' => $langs->trans('Modelcsv_COALA'),
246
                ),
247
                self::$EXPORT_TYPE_BOB50 => array(
248
                    'label' => $langs->trans('Modelcsv_bob50'),
249
                ),
250
                self::$EXPORT_TYPE_CIEL => array(
251
                    'label' => $langs->trans('Modelcsv_ciel'),
252
                    'ACCOUNTING_EXPORT_FORMAT' => 'txt',
253
                ),
254
                self::$EXPORT_TYPE_QUADRATUS => array(
255
                    'label' => $langs->trans('Modelcsv_quadratus'),
256
                    'ACCOUNTING_EXPORT_FORMAT' => 'txt',
257
                ),
258
                self::$EXPORT_TYPE_WINFIC => array(
259
                    'label' => $langs->trans('Modelcsv_winfic'),
260
                    'ACCOUNTING_EXPORT_FORMAT' => 'txt',
261
                ),
262
                self::$EXPORT_TYPE_EBP => array(
263
                    'label' => $langs->trans('Modelcsv_ebp'),
264
                ),
265
                self::$EXPORT_TYPE_COGILOG => array(
266
                    'label' => $langs->trans('Modelcsv_cogilog'),
267
                ),
268
                self::$EXPORT_TYPE_AGIRIS => array(
269
                    'label' => $langs->trans('Modelcsv_agiris'),
270
                ),
271
                self::$EXPORT_TYPE_OPENCONCERTO => array(
272
                    'label' => $langs->trans('Modelcsv_openconcerto'),
273
                ),
274
                self::$EXPORT_TYPE_SAGE50_SWISS => array(
275
                    'label' => $langs->trans('Modelcsv_Sage50_Swiss'),
276
                ),
277
                self::$EXPORT_TYPE_CHARLEMAGNE => array(
278
                    'label' => $langs->trans('Modelcsv_charlemagne'),
279
                    'ACCOUNTING_EXPORT_FORMAT' => 'txt',
280
                ),
281
                self::$EXPORT_TYPE_LDCOMPTA => array(
282
                    'label' => $langs->trans('Modelcsv_LDCompta'),
283
                ),
284
                self::$EXPORT_TYPE_LDCOMPTA10 => array(
285
                    'label' => $langs->trans('Modelcsv_LDCompta10'),
286
                ),
287
                self::$EXPORT_TYPE_GESTIMUMV3 => array(
288
                    'label' => $langs->trans('Modelcsv_Gestinumv3'),
289
                    'ACCOUNTING_EXPORT_FORMAT' => 'txt',
290
                ),
291
                self::$EXPORT_TYPE_GESTIMUMV5 => array(
292
                    'label' => $langs->trans('Modelcsv_Gestinumv5'),
293
                    'ACCOUNTING_EXPORT_FORMAT' => 'txt',
294
                ),
295
                self::$EXPORT_TYPE_FEC => array(
296
                    'label' => $langs->trans('Modelcsv_FEC'),
297
                    'ACCOUNTING_EXPORT_FORMAT' => 'txt',
298
                ),
299
                self::$EXPORT_TYPE_FEC2 => array(
300
                    'label' => $langs->trans('Modelcsv_FEC2'),
301
                    'ACCOUNTING_EXPORT_FORMAT' => 'txt',
302
                ),
303
                self::$EXPORT_TYPE_ISUITEEXPERT => array(
304
                    'label' => 'iSuite Expert',
305
                    'ACCOUNTING_EXPORT_FORMAT' => 'csv',
306
                ),
307
            ),
308
            'cr' => array(
309
                '1' => $langs->trans("Unix"),
310
                '2' => $langs->trans("Windows")
311
            ),
312
            'format' => array(
313
                'csv' => $langs->trans("csv"),
314
                'txt' => $langs->trans("txt")
315
            ),
316
        );
317
318
        global $hookmanager;
319
        $parameters = array();
320
        $reshook = $hookmanager->executeHooks('getTypeConfig', $parameters, $exporttypes);
321
        return $exporttypes;
322
    }
323
324
325
    /**
326
     * Return the MIME type of a file
327
     *
328
     * @param   int     $formatexportset    Id of export format
329
     * @return  string                      MIME type.
330
     */
331
    public function getMimeType($formatexportset)
332
    {
333
        switch ($formatexportset) {
334
            case self::$EXPORT_TYPE_FEC:
335
                $mime = 'text/tab-separated-values';
336
                break;
337
            default:
338
                $mime = 'text/csv';
339
                break;
340
        }
341
342
        return $mime;
343
    }
344
345
    /**
346
     * Function who chose which export to use with the default config, and make the export into a file
347
     *
348
     * @param   array   $TData                      Array with data
349
     * @param   int     $formatexportset            Id of export format
350
     * @param   int     $withAttachment             [=0] Not add files
351
     *                                              or 1 to have attached in an archive (ex : Quadratus) - Force output mode to write in a file (output mode = 1)
352
     * @param   int     $downloadMode               [=0] Direct download. Deprecated. Always use value 1.
353
     *                                              or 1 to download after writing files - Forced by default when use withAttachment = 1
354
     *                                              or -1 not to download files
355
     * @param   int     $outputMode                 [=0] Print on screen. Deprecated. Always use value 1.
356
     *                                              or 1 to write in file and uses the temp directory - Forced by default when use withAttachment = 1
357
     *                                              or 2 to write in file a default export directory (accounting/export/)
358
     * @param   int     $noouput                    0=old mode. Deprecated. Always use value 1.
359
     *                                              or 1=Do not output the file on stdout with this method. This must always be done by the main page, never by a method.
360
     * @return  int                                 Return integer <0 if KO, >0 OK. The property ->generatedfile is also filled.
361
     */
362
    public function export(&$TData, $formatexportset, $withAttachment = 0, $downloadMode = 0, $outputMode = 0, $noouput = 0)
363
    {
364
        global $db, $conf, $langs;  // The tpl file use $db
365
        global $search_date_end;    // Used into /accountancy/tpl/export_journal.tpl.php
366
367
        // Define name of file to save
368
        $filename = 'general_ledger-' . $this->getFormatCode($formatexportset);
369
        $type_export = 'general_ledger';
370
371
        $completefilename = '';
372
        $exportFile = null;
373
        $exportFileName = '';
374
        $exportFilePath = '';
375
        $exportFileFullName = '';
376
        $downloadFileMimeType = '';
377
        $downloadFileFullName = '';
378
        $downloadFilePath = '';
379
        $archiveFullName = '';
380
        $archivePath = '';
381
        $archiveFileList = array();
382
        if ($withAttachment == 1) {
383
            if ($downloadMode == 0) {
384
                $downloadMode = 1; // force to download after writing all files (can't use direct download)
385
            }
386
            if ($outputMode == 0) {
387
                $outputMode = 1; // force to put files in a temp directory (can't use print on screen)
388
            }
389
390
            // PHP ZIP extension must be enabled
391
            if (!extension_loaded('zip')) {
392
                $langs->load('install');
393
                $this->errors[] = $langs->trans('ErrorPHPDoesNotSupport', 'ZIP');
394
                return -1;
395
            }
396
        }
397
398
        $mimetype = $this->getMimeType($formatexportset);
399
        if ($downloadMode == 0) {
400
            // begin to print header for direct download
401
            top_httphead($mimetype, 1);
402
        }
403
404
        include DOL_DOCUMENT_ROOT . '/accountancy/tpl/export_journal.tpl.php';
405
406
        if ($outputMode == 1 || $outputMode == 2) {
407
            if ($outputMode == 1) {
408
                // uses the temp directory by default to write files
409
                if (!empty($conf->accounting->multidir_temp[$conf->entity])) {
410
                    $outputDir = $conf->accounting->multidir_temp[$conf->entity];
411
                } else {
412
                    $outputDir = $conf->accounting->dir_temp;
413
                }
414
            } else {
415
                // uses the default export directory "accounting/export"
416
                if (!empty($conf->accounting->multidir_output[$conf->entity])) {
417
                    $outputDir = $conf->accounting->multidir_output[$conf->entity];
418
                } else {
419
                    $outputDir = $conf->accounting->dir_output;
420
                }
421
422
                // directory already created when module is enabled
423
                $outputDir .= '/export';
424
                $outputDir .= '/' . dol_sanitizePathName($formatexportset);
425
            }
426
427
            if (!dol_is_dir($outputDir)) {
428
                if (dol_mkdir($outputDir) < 0) {
429
                    $this->errors[] = $langs->trans('ErrorCanNotCreateDir', $outputDir);
430
                    return -1;
431
                }
432
            }
433
434
            if ($outputDir != '') {
435
                if (!dol_is_dir($outputDir)) {
436
                    $langs->load('errors');
437
                    $this->errors[] = $langs->trans('ErrorDirNotFound', $outputDir);
438
                    return -1;
439
                }
440
441
                if (!empty($completefilename)) {
442
                    // create export file
443
                    $exportFileFullName = $completefilename;
444
                    $exportFileBaseName = basename($exportFileFullName);
445
                    $exportFileName = pathinfo($exportFileBaseName, PATHINFO_FILENAME);
446
                    $exportFilePath = $outputDir . '/' . $exportFileFullName;
447
                    $exportFile = fopen($exportFilePath, 'w');
448
                    if (!$exportFile) {
449
                        $this->errors[] = $langs->trans('ErrorFileNotFound', $exportFilePath);
450
                        return -1;
451
                    }
452
453
                    if ($withAttachment == 1) {
454
                        $archiveFileList[0] = array(
455
                            'path' => $exportFilePath,
456
                            'name' => $exportFileFullName,
457
                        );
458
459
                        // archive name and path
460
                        $archiveFullName = $exportFileName . '.zip';
461
                        $archivePath = $outputDir . '/' . $archiveFullName;
462
                    }
463
                }
464
            }
465
        }
466
467
        // export file (print on screen or write in a file) and prepare archive list if with attachment is set to 1
468
        switch ($formatexportset) {
469
            case self::$EXPORT_TYPE_CONFIGURABLE:
470
                $this->exportConfigurable($TData, $exportFile);
471
                break;
472
            case self::$EXPORT_TYPE_CEGID:
473
                $this->exportCegid($TData, $exportFile);
474
                break;
475
            case self::$EXPORT_TYPE_COALA:
476
                $this->exportCoala($TData, $exportFile);
477
                break;
478
            case self::$EXPORT_TYPE_BOB50:
479
                $this->exportBob50($TData, $exportFile);
480
                break;
481
            case self::$EXPORT_TYPE_CIEL:
482
                $this->exportCiel($TData, $exportFile);
483
                break;
484
            case self::$EXPORT_TYPE_QUADRATUS:
485
                $archiveFileList = $this->exportQuadratus($TData, $exportFile, $archiveFileList, $withAttachment);
486
                break;
487
            case self::$EXPORT_TYPE_WINFIC:
488
                $this->exportWinfic($TData, $exportFile);
489
                break;
490
            case self::$EXPORT_TYPE_EBP:
491
                $this->exportEbp($TData, $exportFile);
492
                break;
493
            case self::$EXPORT_TYPE_COGILOG:
494
                $this->exportCogilog($TData, $exportFile);
495
                break;
496
            case self::$EXPORT_TYPE_AGIRIS:
497
                $this->exportAgiris($TData, $exportFile);
498
                break;
499
            case self::$EXPORT_TYPE_OPENCONCERTO:
500
                $this->exportOpenConcerto($TData, $exportFile);
501
                break;
502
            case self::$EXPORT_TYPE_SAGE50_SWISS:
503
                $this->exportSAGE50SWISS($TData, $exportFile);
504
                break;
505
            case self::$EXPORT_TYPE_CHARLEMAGNE:
506
                $this->exportCharlemagne($TData, $exportFile);
507
                break;
508
            case self::$EXPORT_TYPE_LDCOMPTA:
509
                $this->exportLDCompta($TData, $exportFile);
510
                break;
511
            case self::$EXPORT_TYPE_LDCOMPTA10:
512
                $this->exportLDCompta10($TData, $exportFile);
513
                break;
514
            case self::$EXPORT_TYPE_GESTIMUMV3:
515
                $this->exportGestimumV3($TData, $exportFile);
516
                break;
517
            case self::$EXPORT_TYPE_GESTIMUMV5:
518
                $this->exportGestimumV5($TData, $exportFile);
519
                break;
520
            case self::$EXPORT_TYPE_FEC:
521
                $archiveFileList = $this->exportFEC($TData, $exportFile, $archiveFileList, $withAttachment);
522
                break;
523
            case self::$EXPORT_TYPE_FEC2:
524
                $archiveFileList = $this->exportFEC2($TData, $exportFile, $archiveFileList, $withAttachment);
525
                break;
526
            case self::$EXPORT_TYPE_ISUITEEXPERT:
527
                $this->exportiSuiteExpert($TData, $exportFile);
528
                break;
529
            default:
530
                global $hookmanager;
531
                $parameters = array('format' => $formatexportset);
532
                // file contents will be created in the hooked function via print
533
                $reshook = $hookmanager->executeHooks('export', $parameters, $TData);
534
                if ($reshook != 1) {
535
                    $this->errors[] = $langs->trans('accountancy_error_modelnotfound');
536
                }
537
                break;
538
        }
539
540
541
        // Create and download export file or archive
542
        if ($outputMode == 1 || $outputMode == 2) {
543
            $error = 0;
544
545
            // close export file
546
            if ($exportFile) {
547
                fclose($exportFile);
548
            }
549
550
            if ($withAttachment == 1) {
551
                // create archive file
552
                if (!empty($archiveFullName) && !empty($archivePath) && !empty($archiveFileList)) {
553
                    // archive files
554
                    $downloadFileMimeType = 'application/zip';
555
                    $downloadFileFullName = $archiveFullName;
556
                    $downloadFilePath = $archivePath;
557
558
                    // create archive
559
                    $archive = new ZipArchive();
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Accountancy\Classes\ZipArchive was not found. Did you mean ZipArchive? If so, make sure to prefix the type with \.
Loading history...
560
                    $res = $archive->open($archivePath, ZipArchive::OVERWRITE | ZipArchive::CREATE);
561
                    if ($res !== true) {
562
                        $error++;
563
                        $this->errors[] = $langs->trans('ErrorFileNotFound', $archivePath);
564
                    }
565
                    if (!$error) {
566
                        // add files
567
                        foreach ($archiveFileList as $archiveFileArr) {
568
                            $res = $archive->addFile($archiveFileArr['path'], $archiveFileArr['name']);
569
                            if (!$res) {
570
                                $error++;
571
                                $this->errors[] = $langs->trans('ErrorArchiveAddFile', $archiveFileArr['name']);
572
                                break;
573
                            }
574
                        }
575
                    }
576
                    if (!$error) {
577
                        // close archive
578
                        $archive->close();
579
                    }
580
                }
581
            }
582
583
            if (!$error) {
584
                // download after writing files
585
                if ($downloadMode == 1) {
586
                    if ($withAttachment == 0) {
587
                        // only download exported file
588
                        if (!empty($exportFileFullName) && !empty($exportFilePath)) {
589
                            $downloadFileMimeType = $mimetype;
590
                            $downloadFileFullName = $exportFileFullName;
591
                            $downloadFilePath = $exportFilePath;
592
                        }
593
                    }
594
595
                    // download export file or archive
596
                    if (!empty($downloadFileMimeType) && !empty($downloadFileFullName) && !empty($downloadFilePath) && empty($noouput)) {
597
                        // deprecated. We must not use this anymore, but have $noouput = 1 because HTTP header must be sent
598
                        // into main page not into a method.
599
                        header('Content-Type: ' . $downloadFileMimeType);
600
                        header('Content-Disposition: attachment; filename=' . $downloadFileFullName);
601
                        header('Cache-Control: Public, must-revalidate');
602
                        header('Pragma: public');
603
                        header('Content-Length: ' . dol_filesize($downloadFilePath));
604
605
                        readfileLowMemory($downloadFilePath);
606
                    }
607
608
                    $this->generatedfiledata = array('downloadFilePath' => $downloadFilePath, 'downloadFileMimeType' => $downloadFileMimeType, 'downloadFileFullName' => $downloadFileFullName);
609
                }
610
            }
611
612
            if ($error) {
613
                return -1;
614
            }
615
        }
616
617
        return 1;
618
    }
619
620
621
    /**
622
     * Export format : CEGID
623
     *
624
     * @param   array       $objectLines            data
625
     * @param   resource    $exportFile             [=null] File resource to export or print if null
626
     * @return  void
627
     */
628
    public function exportCegid($objectLines, $exportFile = null)
629
    {
630
        $separator = ";";
631
        $end_line = "\n";
632
633
        foreach ($objectLines as $line) {
634
            $date_document = dol_print_date($line->doc_date, '%d%m%Y');
635
636
            $tab = array();
637
638
            $tab[] = $date_document;
639
            $tab[] = $line->code_journal;
640
            $tab[] = length_accountg($line->numero_compte);
641
            $tab[] = length_accounta($line->subledger_account);
642
            $tab[] = $line->sens;
643
            $tab[] = price2fec(abs($line->debit - $line->credit));
644
            $tab[] = dol_string_unaccent($line->label_operation);
645
            $tab[] = dol_string_unaccent($line->doc_ref);
646
647
            $output = implode($separator, $tab) . $end_line;
648
            if ($exportFile) {
649
                fwrite($exportFile, $output);
650
            } else {
651
                print $output;
652
            }
653
        }
654
    }
655
656
    /**
657
     * Export format : COGILOG
658
     * Last review for this format : 2022-07-12 Alexandre Spangaro ([email protected])
659
     *
660
     * @param   array       $objectLines            data
661
     * @param   resource    $exportFile             [=null] File resource to export or print if null
662
     * @return  void
663
     */
664
    public function exportCogilog($objectLines, $exportFile = null)
665
    {
666
        $separator = "\t";
667
        $end_line = "\n";
668
669
        foreach ($objectLines as $line) {
670
            $date_document = dol_print_date($line->doc_date, '%d%m%Y');
671
672
            $refInvoice = '';
673
            if ($line->doc_type == 'customer_invoice') {
674
                // Customer invoice
675
                $invoice = new Facture($this->db);
676
                $invoice->fetch($line->fk_doc);
677
678
                $refInvoice = $invoice->ref;
679
            } elseif ($line->doc_type == 'supplier_invoice') {
680
                // Supplier invoice
681
                $invoice = new FactureFournisseur($this->db);
682
                $invoice->fetch($line->fk_doc);
683
684
                $refInvoice = $invoice->ref_supplier;
685
            }
686
687
            $tab = array();
688
689
            $tab[] = $line->code_journal;
690
            $tab[] = $date_document;
691
            $tab[] = $refInvoice;
692
            if (empty($line->subledger_account)) {
693
                $tab[] = length_accountg($line->numero_compte);
694
            } else {
695
                $tab[] = length_accounta($line->subledger_account);
696
            }
697
            $tab[] = "";
698
            $tab[] = $line->label_operation;
699
            $tab[] = $date_document;
700
            if ($line->sens == 'D') {
701
                $tab[] = price($line->debit);
702
                $tab[] = "";
703
            } elseif ($line->sens == 'C') {
704
                $tab[] = "";
705
                $tab[] = price($line->credit);
706
            }
707
            $tab[] = $line->doc_ref;
708
            $tab[] = $line->label_operation;
709
710
            $output = implode($separator, $tab) . $end_line;
711
            if ($exportFile) {
712
                fwrite($exportFile, $output);
713
            } else {
714
                print $output;
715
            }
716
        }
717
    }
718
719
    /**
720
     * Export format : COALA
721
     *
722
     * @param   array       $objectLines            data
723
     * @param   resource    $exportFile             [=null] File resource to export or print if null
724
     * @return  void
725
     */
726
    public function exportCoala($objectLines, $exportFile = null)
727
    {
728
        // Coala export
729
        $separator = ";";
730
        $end_line = "\n";
731
732
        foreach ($objectLines as $line) {
733
            $date_document = dol_print_date($line->doc_date, '%d/%m/%Y');
734
735
            $tab = array();
736
737
            $tab[] = $date_document;
738
            $tab[] = $line->code_journal;
739
            $tab[] = length_accountg($line->numero_compte);
740
            $tab[] = $line->piece_num;
741
            $tab[] = $line->doc_ref;
742
            $tab[] = price($line->debit);
743
            $tab[] = price($line->credit);
744
            $tab[] = 'E';
745
            $tab[] = length_accounta($line->subledger_account);
746
747
            $output = implode($separator, $tab) . $end_line;
748
            if ($exportFile) {
749
                fwrite($exportFile, $output);
750
            } else {
751
                print $output;
752
            }
753
        }
754
    }
755
756
    /**
757
     * Export format : BOB50
758
     *
759
     * @param   array       $objectLines            data
760
     * @param   resource    $exportFile             [=null] File resource to export or print if null
761
     * @return  void
762
     */
763
    public function exportBob50($objectLines, $exportFile = null)
764
    {
765
        // Bob50
766
        $separator = ";";
767
        $end_line = "\n";
768
769
        foreach ($objectLines as $line) {
770
            $date_document = dol_print_date($line->doc_date, '%d/%m/%Y');
771
772
            $tab = array();
773
774
            $tab[] = $line->piece_num;
775
            $tab[] = $date_document;
776
777
            if (empty($line->subledger_account)) {
778
                $tab[] = 'G';
779
                $tab[] = length_accountg($line->numero_compte);
780
            } else {
781
                if (substr($line->numero_compte, 0, 3) == '411') {
782
                    $tab[] = 'C';
783
                }
784
                if (substr($line->numero_compte, 0, 3) == '401') {
785
                    $tab[] = 'F';
786
                }
787
                $tab[] = length_accounta($line->subledger_account);
788
            }
789
790
            $tab[] = price($line->debit);
791
            $tab[] = price($line->credit);
792
            $tab[] = dol_trunc($line->label_operation, 32);
793
794
            $output = implode($separator, $tab) . $end_line;
795
            if ($exportFile) {
796
                fwrite($exportFile, $output);
797
            } else {
798
                print $output;
799
            }
800
        }
801
    }
802
803
    /**
804
     * Export format : CIEL (Format XIMPORT)
805
     * Format since 2003 compatible CIEL version > 2002 / Sage50
806
     * Last review for this format : 2021-09-13 Alexandre Spangaro ([email protected])
807
     *
808
     * Help : https://sage50c.online-help.sage.fr/aide-technique/
809
     * In sage software | Use menu : "Exchange" > "Importing entries..."
810
     *
811
     * If you want to force filename to "XIMPORT.TXT" for automatically import file present in a directory :
812
     * use constant ACCOUNTING_EXPORT_XIMPORT_FORCE_FILENAME
813
     *
814
     * @param   array       $objectLines            data
815
     * @param   resource    $exportFile             [=null] File resource to export or print if null
816
     * @return  void
817
     */
818
    public function exportCiel($objectLines, $exportFile = null)
819
    {
820
        $end_line = "\r\n";
821
822
        $i = 1;
823
824
        foreach ($objectLines as $line) {
825
            $code_compta = length_accountg($line->numero_compte);
826
            if (!empty($line->subledger_account)) {
827
                $code_compta = length_accounta($line->subledger_account);
828
            }
829
830
            $date_document = dol_print_date($line->doc_date, '%Y%m%d');
831
            $date_echeance = dol_print_date($line->date_lim_reglement, '%Y%m%d');
832
833
            $tab = array();
834
835
            $tab[] = str_pad($line->piece_num, 5);
836
            $tab[] = str_pad(self::trunc($line->code_journal, 2), 2);
837
            $tab[] = str_pad($date_document, 8, ' ', STR_PAD_LEFT);
838
            $tab[] = str_pad($date_echeance, 8, ' ', STR_PAD_LEFT);
839
            $tab[] = str_pad(self::trunc($line->doc_ref, 12), 12);
840
            $tab[] = str_pad(self::trunc($code_compta, 11), 11);
841
            $tab[] = str_pad(self::trunc(dol_string_unaccent($line->doc_ref) . dol_string_unaccent($line->label_operation), 25), 25);
842
            $tab[] = str_pad(price2fec(abs($line->debit - $line->credit)), 13, ' ', STR_PAD_LEFT);
843
            $tab[] = str_pad($line->sens, 1);
844
            $tab[] = str_repeat(' ', 18); // Analytical accounting - Not managed in Dolibarr
845
            $tab[] = str_pad(self::trunc(dol_string_unaccent($line->label_operation), 34), 34);
846
            $tab[] = 'O2003'; // 0 = EUR | 2003 = Format Ciel
847
848
            $output = implode($tab) . $end_line;
849
            if ($exportFile) {
850
                fwrite($exportFile, $output);
851
            } else {
852
                print $output;
853
            }
854
            $i++;
855
        }
856
    }
857
858
    /**
859
     * Export format : Quadratus (Format ASCII)
860
     * Format since 2015 compatible QuadraCOMPTA
861
     * Last review for this format : 2023/10/12 Alexandre Spangaro ([email protected])
862
     *
863
     * Information on format: https://docplayer.fr/20769649-Fichier-d-entree-ascii-dans-quadracompta.html
864
     * Help to import in Quadra: https://wiki.dolibarr.org/index.php?title=Module_Comptabilit%C3%A9_en_Partie_Double#Import_vers_CEGID_Quadra
865
     * In QuadraCompta | Use menu : "Outils" > "Suivi des dossiers" > "Import ASCII(Compta)"
866
     *
867
     * @param   array       $objectLines            data
868
     * @param   resource    $exportFile             [=null] File resource to export or print if null
869
     * @param   array       $archiveFileList        [=array()] Archive file list : array of ['path', 'name']
870
     * @param   int         $withAttachment         [=0] Not add files or 1 to have attached in an archive
871
     * @return  array       Archive file list : array of ['path', 'name']
872
     */
873
    public function exportQuadratus($objectLines, $exportFile = null, $archiveFileList = array(), $withAttachment = 0)
874
    {
875
        global $conf, $db;
876
877
        $end_line = "\r\n";
878
879
        // We should use dol_now function not time however this is wrong date to transfer in accounting
880
        foreach ($objectLines as $line) {
881
            // Clean some data
882
            $line->doc_ref = dol_string_unaccent($line->doc_ref);
883
884
            $line->label_operation = str_replace(array("\t", "\n", "\r"), " ", $line->label_operation);
885
            $line->label_operation = str_replace(array("- ", "…", "..."), "", $line->label_operation);
886
            $line->label_operation = dol_string_unaccent($line->label_operation);
887
888
            $line->numero_compte = dol_string_unaccent($line->numero_compte);
889
            $line->label_compte = dol_string_unaccent($line->label_compte);
890
            $line->subledger_account = dol_string_unaccent($line->subledger_account);
891
892
            $line->subledger_label = str_replace(array("- ", "…", "..."), "", $line->subledger_label);
893
            $line->subledger_label = dol_string_unaccent($line->subledger_label);
894
895
            $code_compta = $line->numero_compte;
896
            if (!empty($line->subledger_account)) {
897
                $code_compta = $line->subledger_account;
898
            }
899
900
            $tab = array();
901
902
            if (!empty($line->subledger_account)) {
903
                $tab['type_ligne'] = 'C';
904
                $tab['num_compte'] = str_pad(self::trunc($line->subledger_account, 8), 8);
905
                $tab['lib_compte'] = str_pad(self::trunc($line->subledger_label, 30), 30);
906
907
                if ($line->doc_type == 'customer_invoice') {
908
                    $tab['lib_alpha'] = strtoupper(str_pad('C' . self::trunc(dol_string_unaccent($line->subledger_label), 6), 7));
909
                    $tab['filler'] = str_repeat(' ', 52);
910
                    $tab['coll_compte'] = str_pad(self::trunc(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER'), 8), 8);
911
                } elseif ($line->doc_type == 'supplier_invoice') {
912
                    $tab['lib_alpha'] = strtoupper(str_pad('F' . self::trunc(dol_string_unaccent($line->subledger_label), 6), 7));
913
                    $tab['filler'] = str_repeat(' ', 52);
914
                    $tab['coll_compte'] = str_pad(self::trunc(getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER'), 8), 8);
915
                } else {
916
                    $tab['filler'] = str_repeat(' ', 59);
917
                    $tab['coll_compte'] = str_pad(' ', 8);
918
                }
919
920
                $tab['filler2'] = str_repeat(' ', 110);
921
                $tab['Maj'] = 2; // Partial update (alpha key, label, address, collectif, RIB)
922
923
                if ($line->doc_type == 'customer_invoice') {
924
                    $tab['type_compte'] = 'C';
925
                } elseif ($line->doc_type == 'supplier_invoice') {
926
                    $tab['type_compte'] = 'F';
927
                } else {
928
                    $tab['type_compte'] = 'G';
929
                }
930
931
                $tab['filler3'] = str_repeat(' ', 235);
932
933
                $tab['end_line'] = $end_line;
934
935
                if ($exportFile) {
936
                    fwrite($exportFile, implode($tab));
937
                } else {
938
                    print implode($tab);
939
                }
940
            }
941
942
            $tab = array();
943
            $tab['type_ligne'] = 'M';
944
            $tab['num_compte'] = str_pad(self::trunc($code_compta, 8), 8);
945
            $tab['code_journal'] = str_pad(self::trunc($line->code_journal, 2), 2);
946
            $tab['folio'] = '000';
947
948
            // We use invoice date $line->doc_date not $date_ecriture which is the transfer date
949
            // maybe we should set an option for customer who prefer to keep in accounting software the tranfert date instead of invoice date ?
950
            //$tab['date_ecriture'] = $date_ecriture;
951
            $tab['date_ecriture'] = dol_print_date($line->doc_date, '%d%m%y');
952
            $tab['filler'] = ' ';
953
            $tab['libelle_ecriture'] = str_pad(self::trunc($line->doc_ref . ' ' . $line->label_operation, 20), 20);
954
955
            // Credit invoice - invert sens
956
            /*
957
            if ($line->montant < 0) {
958
                if ($line->sens == 'C') {
959
                    $tab['sens'] = 'D';
960
                } else {
961
                    $tab['sens'] = 'C';
962
                }
963
                $tab['signe_montant'] = '-';
964
            } else {
965
                $tab['sens'] = $line->sens; // C or D
966
                $tab['signe_montant'] = '+';
967
            }*/
968
            $tab['sens'] = $line->sens; // C or D
969
            $tab['signe_montant'] = '+';
970
971
            // The amount must be in centimes without decimal points.
972
            $tab['montant'] = str_pad((string) abs(($line->debit - $line->credit) * 100), 12, '0', STR_PAD_LEFT);
973
            $tab['contrepartie'] = str_repeat(' ', 8);
974
975
            // Force date format : %d%m%y
976
            if (!empty($line->date_lim_reglement)) {
977
                $tab['date_echeance'] = dol_print_date($line->date_lim_reglement, '%d%m%y'); // Format must be ddmmyy
978
            } else {
979
                $tab['date_echeance'] = '000000';
980
            }
981
982
            // Please keep quadra named field lettrage(2) + codestat(3) instead of fake lettrage(5)
983
            // $tab['lettrage'] = str_repeat(' ', 5);
984
            $tab['lettrage'] = str_repeat(' ', 2);
985
            $tab['codestat'] = str_repeat(' ', 3);
986
            $tab['num_piece'] = str_pad(self::trunc($line->piece_num, 5), 5);
987
988
            // Keep correct quadra named field instead of anon filler
989
            // $tab['filler2'] = str_repeat(' ', 20);
990
            $tab['affaire'] = str_repeat(' ', 10);
991
            $tab['quantity1'] = str_repeat(' ', 10);
992
            $tab['num_piece2'] = str_pad(self::trunc($line->piece_num, 8), 8);
993
            $tab['devis'] = str_pad($conf->currency, 3);
994
            $tab['code_journal2'] = str_pad(self::trunc($line->code_journal, 3), 3);
995
            $tab['filler3'] = str_repeat(' ', 3);
996
997
            // Keep correct quadra named field instead of anon filler libelle_ecriture2 is 30 char not 32 !!!!
998
            // as we use utf8, we must remove accent to have only one ascii char instead of utf8 2 chars for specials that report wrong line size that will exceed import format spec
999
            // TODO: we should filter more than only accent to avoid wrong line size
1000
            // TODO: remove invoice number doc_ref in label,
1001
            // TODO: we should offer an option for customer to build the label using invoice number / name / date in accounting software
1002
            //$tab['libelle_ecriture2'] = str_pad(self::trunc($line->doc_ref . ' ' . $line->label_operation, 30), 30);
1003
            $tab['libelle_ecriture2'] = str_pad(self::trunc($line->label_operation, 30), 30);
1004
            $tab['codetva'] = str_repeat(' ', 2);
1005
1006
            // We need to keep the 10 latest number of invoices doc_ref not the beginning part that is the useless almost same part
1007
            // $tab['num_piece3'] = str_pad(self::trunc($line->piece_num, 10), 10);
1008
            $tab['num_piece3'] = substr(self::trunc($line->doc_ref, 20), -10);
1009
            $tab['reserved'] = str_repeat(' ', 10); // position 159
1010
            $tab['currency_amount'] = str_repeat(' ', 13); // position 169
1011
            // get document file
1012
            $attachmentFileName = '';
1013
            if ($withAttachment == 1) {
1014
                $attachmentFileKey = trim($line->piece_num);
1015
1016
                if (!isset($archiveFileList[$attachmentFileKey])) {
1017
                    $objectDirPath = '';
1018
                    $objectFileName = dol_sanitizeFileName($line->doc_ref);
1019
                    if ($line->doc_type == 'customer_invoice') {
1020
                        $objectDirPath = !empty($conf->invoice->multidir_output[$conf->entity]) ? $conf->invoice->multidir_output[$conf->entity] : $conf->invoice->dir_output;
1021
                    } elseif ($line->doc_type == 'expense_report') {
1022
                        $objectDirPath = !empty($conf->expensereport->multidir_output[$conf->entity]) ? $conf->expensereport->multidir_output[$conf->entity] : $conf->expensereport->dir_output;
1023
                    } elseif ($line->doc_type == 'supplier_invoice') {
1024
                        $invoice = new FactureFournisseur($this->db);
1025
                        $invoice->fetch($line->fk_doc);
1026
                        $objectDirPath = !empty($conf->fournisseur->facture->multidir_output[$conf->entity]) ? $conf->fournisseur->facture->multidir_output[$conf->entity] : $conf->fournisseur->facture->dir_output;
1027
                        $objectDirPath .= '/' . rtrim(get_exdir($invoice->id, 2, 0, 0, $invoice, 'invoice_supplier'), '/');
1028
                    }
1029
                    $arrayofinclusion = array();
1030
                    // If it is a supplier invoice, we want to use last uploaded file
1031
                    $arrayofinclusion[] = '^' . preg_quote($objectFileName, '/') . (($line->doc_type == 'supplier_invoice') ? '.+' : '') . '\.pdf$';
1032
                    $fileFoundList = dol_dir_list($objectDirPath . '/' . $objectFileName, 'files', 0, implode('|', $arrayofinclusion), '(\.meta|_preview.*\.png)$', 'date', SORT_DESC, 0, true);
1033
                    if (!empty($fileFoundList)) {
1034
                        $attachmentFileNameTrunc = str_pad(self::trunc($line->piece_num, 8), 8, '0', STR_PAD_LEFT);
1035
                        foreach ($fileFoundList as $fileFound) {
1036
                            if (strstr($fileFound['name'], $objectFileName)) {
1037
                                // skip native invoice pdfs (canelle)
1038
                                // We want to retrieve an attachment representative of the supplier invoice, not a fake document generated by Dolibarr.
1039
                                if ($line->doc_type == 'supplier_invoice') {
1040
                                    if ($fileFound['name'] === $objectFileName . '.pdf') {
1041
                                        continue;
1042
                                    }
1043
                                } elseif ($fileFound['name'] !== $objectFileName . '.pdf') {
1044
                                    continue;
1045
                                }
1046
                                $fileFoundPath = $objectDirPath . '/' . $objectFileName . '/' . $fileFound['name'];
1047
                                if (file_exists($fileFoundPath)) {
1048
                                    $archiveFileList[$attachmentFileKey] = array(
1049
                                        'path' => $fileFoundPath,
1050
                                        'name' => $attachmentFileNameTrunc . '.pdf',
1051
                                    );
1052
                                    break;
1053
                                }
1054
                            }
1055
                        }
1056
                    }
1057
                }
1058
1059
                if (isset($archiveFileList[$attachmentFileKey])) {
1060
                    $attachmentFileName = $archiveFileList[$attachmentFileKey]['name'];
1061
                }
1062
            }
1063
            if (dol_strlen($attachmentFileName) == 12) {
1064
                $tab['attachment'] = $attachmentFileName; // position 182
1065
            } else {
1066
                $tab['attachment'] = str_repeat(' ', 12); // position 182
1067
            }
1068
            $tab['filler4'] = str_repeat(' ', 38);
1069
            $tab['end_line'] = $end_line;
1070
1071
            if ($exportFile) {
1072
                fwrite($exportFile, implode($tab));
1073
            } else {
1074
                print implode($tab);
1075
            }
1076
        }
1077
1078
        return $archiveFileList;
1079
    }
1080
1081
    /**
1082
     * Export format : WinFic - eWinfic - WinSis Compta
1083
     * Last review for this format : 2022-11-01 Alexandre Spangaro ([email protected])
1084
     *
1085
     * Help : https://wiki.gestan.fr/lib/exe/fetch.php?media=wiki:v15:compta:accountancy-format_winfic-ewinfic-winsiscompta.pdf
1086
     *
1087
     * @param   array       $objectLines            data
1088
     * @param   resource    $exportFile             [=null] File resource to export or print if null
1089
     * @return  void
1090
     */
1091
    public function exportWinfic($objectLines, $exportFile = null)
1092
    {
1093
        global $conf;
1094
1095
        $end_line = "\r\n";
1096
        $index = 1;
1097
1098
        // Warning ! When truncation is necessary, no dot because 3 dots = three characters. The columns are shifted
1099
1100
        foreach ($objectLines as $line) {
1101
            $code_compta = $line->numero_compte;
1102
            if (!empty($line->subledger_account)) {
1103
                $code_compta = $line->subledger_account;
1104
            }
1105
1106
            $tab = array();
1107
            //$tab['type_ligne'] = 'M';
1108
            $tab['code_journal'] = str_pad(dol_trunc($line->code_journal, 2, 'right', 'UTF-8', 1), 2);
1109
1110
            //We use invoice date $line->doc_date not $date_ecriture which is the transfer date
1111
            //maybe we should set an option for customer who prefer to keep in accounting software the tranfert date instead of invoice date ?
1112
            //$tab['date_ecriture'] = $date_ecriture;
1113
            $tab['date_operation'] = dol_print_date($line->doc_date, '%d%m%Y');
1114
1115
            $tab['folio'] = '     1';
1116
1117
            $tab['num_ecriture'] = str_pad(dol_trunc($index, 6, 'right', 'UTF-8', 1), 6, ' ', STR_PAD_LEFT);
1118
1119
            $tab['jour_ecriture'] = dol_print_date($line->doc_date, '%d%m%y');
1120
1121
            $tab['num_compte'] = str_pad(dol_trunc($code_compta, 6, 'right', 'UTF-8', 1), 6, '0');
1122
1123
            if ($line->sens == 'D') {
1124
                $tab['montant_debit']  = str_pad(number_format($line->debit, 2, ',', ''), 13, ' ', STR_PAD_LEFT);
1125
1126
                $tab['montant_crebit'] = str_pad(number_format(0, 2, ',', ''), 13, ' ', STR_PAD_LEFT);
1127
            } else {
1128
                $tab['montant_debit']  = str_pad(number_format(0, 2, ',', ''), 13, ' ', STR_PAD_LEFT);
1129
1130
                $tab['montant_crebit'] = str_pad(number_format($line->credit, 2, ',', ''), 13, ' ', STR_PAD_LEFT);
1131
            }
1132
1133
            $tab['libelle_ecriture'] = str_pad(dol_trunc(dol_string_unaccent($line->doc_ref) . ' ' . dol_string_unaccent($line->label_operation), 30, 'right', 'UTF-8', 1), 30);
1134
1135
            $tab['lettrage'] = str_repeat(dol_trunc($line->lettering_code, 2, 'left', 'UTF-8', 1), 2);
1136
1137
            $tab['code_piece'] = str_pad(dol_trunc($line->piece_num, 5, 'left', 'UTF-8', 1), 5, ' ', STR_PAD_LEFT);
1138
1139
            $tab['code_stat'] = str_repeat(' ', 4);
1140
1141
            if (!empty($line->date_lim_reglement)) {
1142
                $tab['date_echeance'] = dol_print_date($line->date_lim_reglement, '%d%m%Y');
1143
            } else {
1144
                $tab['date_echeance'] = dol_print_date($line->doc_date, '%d%m%Y');
1145
            }
1146
1147
            $tab['monnaie'] = '1';
1148
1149
            $tab['filler'] = ' ';
1150
1151
            $tab['ind_compteur'] = ' ';
1152
1153
            $tab['quantite'] = '0,000000000';
1154
1155
            $tab['code_pointage'] = str_repeat(' ', 2);
1156
1157
            $tab['end_line'] = $end_line;
1158
1159
            print implode('|', $tab);
1160
1161
            $index++;
1162
        }
1163
    }
1164
1165
1166
    /**
1167
     * Export format : EBP
1168
     *
1169
     * @param   array       $objectLines            data
1170
     * @param   resource    $exportFile             [=null] File resource to export or print if null
1171
     * @return  void
1172
     */
1173
    public function exportEbp($objectLines, $exportFile = null)
1174
    {
1175
        $separator = ',';
1176
        $end_line = "\n";
1177
1178
        foreach ($objectLines as $line) {
1179
            $date_document = dol_print_date($line->doc_date, '%d%m%Y');
1180
1181
            $tab = array();
1182
1183
            $tab[] = $line->id;
1184
            $tab[] = $date_document;
1185
            $tab[] = $line->code_journal;
1186
            if (empty($line->subledger_account)) {
1187
                $tab[] = $line->numero_compte;
1188
            } else {
1189
                $tab[] = $line->subledger_account;
1190
            }
1191
            //$tab[] = substr(length_accountg($line->numero_compte), 0, 2) . $separator;
1192
            $tab[] = '"' . dol_trunc($line->label_operation, 40, 'right', 'UTF-8', 1) . '"';
1193
            $tab[] = '"' . dol_trunc($line->piece_num, 15, 'right', 'UTF-8', 1) . '"';
1194
            $tab[] = price2num(abs($line->debit - $line->credit));
1195
            $tab[] = $line->sens;
1196
            $tab[] = $date_document;
1197
            //print 'EUR';
1198
1199
            $output = implode($separator, $tab) . $end_line;
1200
            if ($exportFile) {
1201
                fwrite($exportFile, $output);
1202
            } else {
1203
                print $output;
1204
            }
1205
        }
1206
    }
1207
1208
1209
    /**
1210
     * Export format : Agiris Isacompta
1211
     *
1212
     * @param   array       $objectLines            data
1213
     * @param   resource    $exportFile             [=null] File resource to export or print if null
1214
     * @return  void
1215
     */
1216
    public function exportAgiris($objectLines, $exportFile = null)
1217
    {
1218
        $separator = ';';
1219
        $end_line = "\n";
1220
1221
        foreach ($objectLines as $line) {
1222
            $date_document = dol_print_date($line->doc_date, '%d%m%Y');
1223
1224
            $tab = array();
1225
1226
            $tab[] = $line->piece_num;
1227
            $tab[] = self::toAnsi($line->label_operation);
1228
            $tab[] = $date_document;
1229
            $tab[] = self::toAnsi($line->label_operation);
1230
1231
            if (empty($line->subledger_account)) {
1232
                $tab[] = length_accountg($line->numero_compte);
1233
                $tab[] = self::toAnsi($line->label_compte);
1234
            } else {
1235
                $tab[] = length_accounta($line->subledger_account);
1236
                $tab[] = self::toAnsi($line->subledger_label);
1237
            }
1238
1239
            $tab[] = self::toAnsi($line->doc_ref);
1240
            $tab[] = price($line->debit);
1241
            $tab[] = price($line->credit);
1242
            $tab[] = price(abs($line->debit - $line->credit));
1243
            $tab[] = $line->sens;
1244
            $tab[] = $line->lettering_code;
1245
            $tab[] = $line->code_journal;
1246
1247
            $output = implode($separator, $tab) . $end_line;
1248
            if ($exportFile) {
1249
                fwrite($exportFile, $output);
1250
            } else {
1251
                print $output;
1252
            }
1253
        }
1254
    }
1255
1256
    /**
1257
     * Export format : OpenConcerto
1258
     *
1259
     * @param   array       $objectLines            data
1260
     * @param   resource    $exportFile             [=null] File resource to export or print if null
1261
     * @return  void
1262
     */
1263
    public function exportOpenConcerto($objectLines, $exportFile = null)
1264
    {
1265
        $separator = ';';
1266
        $end_line = "\n";
1267
1268
        foreach ($objectLines as $line) {
1269
            $date_document = dol_print_date($line->doc_date, '%d/%m/%Y');
1270
1271
            $tab = array();
1272
1273
            $tab[] = $date_document;
1274
            $tab[] = $line->code_journal;
1275
            if (empty($line->subledger_account)) {
1276
                $tab[] = length_accountg($line->numero_compte);
1277
            } else {
1278
                $tab[] = length_accounta($line->subledger_account);
1279
            }
1280
            $tab[] = $line->doc_ref;
1281
            $tab[] = $line->label_operation;
1282
            $tab[] = price($line->debit);
1283
            $tab[] = price($line->credit);
1284
1285
            $output = implode($separator, $tab) . $end_line;
1286
            if ($exportFile) {
1287
                fwrite($exportFile, $output);
1288
            } else {
1289
                print $output;
1290
            }
1291
        }
1292
    }
1293
1294
    /**
1295
     * Export format : Configurable CSV
1296
     *
1297
     * @param   array       $objectLines            data
1298
     * @param   resource    $exportFile             [=null] File resource to export or print if null
1299
     * @return  void
1300
     */
1301
    public function exportConfigurable($objectLines, $exportFile = null)
1302
    {
1303
        global $conf;
1304
1305
        $separator = $this->separator;
1306
1307
        foreach ($objectLines as $line) {
1308
            $date_document = dol_print_date($line->doc_date, getDolGlobalString('ACCOUNTING_EXPORT_DATE'));
1309
1310
            $tab = array();
1311
            // export configurable
1312
            $tab[] = $line->piece_num;
1313
            $tab[] = $date_document;
1314
            $tab[] = $line->doc_ref;
1315
            $tab[] = preg_match('/' . $separator . '/', $line->label_operation) ? "'" . $line->label_operation . "'" : $line->label_operation;
1316
            $tab[] = length_accountg($line->numero_compte);
1317
            $tab[] = length_accounta($line->subledger_account);
1318
            $tab[] = price2num($line->debit);
1319
            $tab[] = price2num($line->credit);
1320
            $tab[] = price2num($line->debit - $line->credit);
1321
            $tab[] = $line->code_journal;
1322
1323
            $output = implode($separator, $tab) . $this->end_line;
1324
            if ($exportFile) {
1325
                fwrite($exportFile, $output);
1326
            } else {
1327
                print $output;
1328
            }
1329
        }
1330
    }
1331
1332
    /**
1333
     * Export format : FEC
1334
     * Last review for this format : 2023/10/12 Alexandre Spangaro ([email protected])
1335
     *
1336
     * Help to import in your software: https://wiki.dolibarr.org/index.php?title=Module_Comptabilit%C3%A9_en_Partie_Double#Exports_avec_fichiers_sources
1337
     *
1338
     * @param   array       $objectLines            data
1339
     * @param   resource    $exportFile             [=null] File resource to export or print if null
1340
     * @param   array       $archiveFileList        [=array()] Archive file list : array of ['path', 'name']
1341
     * @param   int         $withAttachment         [=0] Not add files or 1 to have attached in an archive
1342
     * @return  array       Archive file list : array of ['path', 'name']
1343
     */
1344
    public function exportFEC($objectLines, $exportFile = null, $archiveFileList = array(), $withAttachment = 0)
1345
    {
1346
        global $conf, $langs;
1347
1348
        $separator = "\t";
1349
        $end_line = "\r\n";
1350
1351
        $tab = array();
1352
        $tab[] = "JournalCode";
1353
        $tab[] = "JournalLib";
1354
        $tab[] = "EcritureNum";
1355
        $tab[] = "EcritureDate";
1356
        $tab[] = "CompteNum";
1357
        $tab[] = "CompteLib";
1358
        $tab[] = "CompAuxNum";
1359
        $tab[] = "CompAuxLib";
1360
        $tab[] = "PieceRef";
1361
        $tab[] = "PieceDate";
1362
        $tab[] = "EcritureLib";
1363
        $tab[] = "Debit";
1364
        $tab[] = "Credit";
1365
        $tab[] = "EcritureLet";
1366
        $tab[] = "DateLet";
1367
        $tab[] = "ValidDate";
1368
        $tab[] = "Montantdevise";
1369
        $tab[] = "Idevise";
1370
        $tab[] = "DateLimitReglmt";
1371
        $tab[] = "NumFacture";
1372
        $tab[] = "FichierFacture";
1373
1374
        $output = implode($separator, $tab) . $end_line;
1375
        if ($exportFile) {
1376
            fwrite($exportFile, $output);
1377
        } else {
1378
            print $output;
1379
        }
1380
1381
        foreach ($objectLines as $line) {
1382
            if ($line->debit == 0 && $line->credit == 0) {
1383
                //var_dump($line->id);
1384
                //unset($array[$line]);
1385
            } else {
1386
                $date_creation = dol_print_date($line->date_creation, '%Y%m%d');
1387
                $date_document = dol_print_date($line->doc_date, '%Y%m%d');
1388
                $date_lettering = dol_print_date($line->date_lettering, '%Y%m%d');
1389
                $date_validation = dol_print_date($line->date_validation, '%Y%m%d');
1390
                $date_limit_payment = dol_print_date($line->date_lim_reglement, '%Y%m%d');
1391
1392
                $refInvoice = '';
1393
                if ($line->doc_type == 'customer_invoice') {
1394
                    // Customer invoice
1395
                    $invoice = new Facture($this->db);
1396
                    $invoice->fetch($line->fk_doc);
1397
1398
                    $refInvoice = $invoice->ref;
1399
                } elseif ($line->doc_type == 'supplier_invoice') {
1400
                    // Supplier invoice
1401
                    $invoice = new FactureFournisseur($this->db);
1402
                    $invoice->fetch($line->fk_doc);
1403
1404
                    $refInvoice = $invoice->ref_supplier;
1405
                }
1406
1407
                $tab = array();
1408
1409
                // FEC:JournalCode
1410
                $tab[] = $line->code_journal;
1411
1412
                // FEC:JournalLib
1413
                $labeljournal = dol_string_unaccent($langs->transnoentities($line->journal_label));
1414
                $labeljournal = dol_string_nospecial($labeljournal, ' ');
1415
                $tab[] = $labeljournal;
1416
1417
                // FEC:EcritureNum
1418
                $tab[] = $line->piece_num;
1419
1420
                // FEC:EcritureDate
1421
                $tab[] = $date_document;
1422
1423
                // FEC:CompteNum
1424
                $tab[] = length_accountg($line->numero_compte);
1425
1426
                // FEC:CompteLib
1427
                $tab[] = dol_string_unaccent($line->label_compte);
1428
1429
                // FEC:CompAuxNum
1430
                $tab[] = length_accounta($line->subledger_account);
1431
1432
                // FEC:CompAuxLib
1433
                $tab[] = dol_string_unaccent($line->subledger_label);
1434
1435
                // FEC:PieceRef
1436
                $tab[] = $line->doc_ref;
1437
1438
                // FEC:PieceDate
1439
                $tab[] = dol_string_unaccent($date_creation);
1440
1441
                // FEC:EcritureLib
1442
                // Clean label operation to prevent problem on export with tab separator & other character
1443
                $line->label_operation = str_replace(array("\t", "\n", "\r"), " ", $line->label_operation);
1444
                $line->label_operation = str_replace(array("..."), "", $line->label_operation);
1445
                $tab[] = dol_string_unaccent($line->label_operation);
1446
1447
                // FEC:Debit
1448
                $tab[] = price2fec($line->debit);
1449
1450
                // FEC:Credit
1451
                $tab[] = price2fec($line->credit);
1452
1453
                // FEC:EcritureLet
1454
                $tab[] = $line->lettering_code;
1455
1456
                // FEC:DateLet
1457
                $tab[] = $date_lettering;
1458
1459
                // FEC:ValidDate
1460
                $tab[] = $date_validation;
1461
1462
                // FEC:Montantdevise
1463
                $tab[] = $line->multicurrency_amount;
1464
1465
                // FEC:Idevise
1466
                $tab[] = $line->multicurrency_code;
1467
1468
                // FEC_suppl:DateLimitReglmt
1469
                $tab[] = $date_limit_payment;
1470
1471
                // FEC_suppl:NumFacture
1472
                // Clean ref invoice to prevent problem on export with tab separator & other character
1473
                $refInvoice = str_replace(array("\t", "\n", "\r"), " ", $refInvoice);
1474
                $tab[] = dol_trunc(self::toAnsi($refInvoice), 17, 'right', 'UTF-8', 1);
1475
1476
                // FEC_suppl:FichierFacture
1477
                // get document file
1478
                $attachmentFileName = '';
1479
                if ($withAttachment == 1) {
1480
                    $attachmentFileKey = trim($line->piece_num);
1481
1482
                    if (!isset($archiveFileList[$attachmentFileKey])) {
1483
                        $objectDirPath = '';
1484
                        $objectFileName = dol_sanitizeFileName($line->doc_ref);
1485
                        if ($line->doc_type == 'customer_invoice') {
1486
                            $objectDirPath = !empty($conf->invoice->multidir_output[$conf->entity]) ? $conf->invoice->multidir_output[$conf->entity] : $conf->invoice->dir_output;
1487
                        } elseif ($line->doc_type == 'expense_report') {
1488
                            $objectDirPath = !empty($conf->expensereport->multidir_output[$conf->entity]) ? $conf->expensereport->multidir_output[$conf->entity] : $conf->expensereport->dir_output;
1489
                        } elseif ($line->doc_type == 'supplier_invoice') {
1490
                            $objectDirPath = !empty($conf->fournisseur->facture->multidir_output[$conf->entity]) ? $conf->fournisseur->facture->multidir_output[$conf->entity] : $conf->fournisseur->facture->dir_output;
1491
                            $objectDirPath .= '/' . rtrim(get_exdir($invoice->id, 2, 0, 0, $invoice, 'invoice_supplier'), '/');
1492
                        }
1493
                        $arrayofinclusion = array();
1494
                        // If it is a supplier invoice, we want to use last uploaded file
1495
                        $arrayofinclusion[] = '^' . preg_quote($objectFileName, '/') . (($line->doc_type == 'supplier_invoice') ? '.+' : '') . '\.pdf$';
1496
                        $fileFoundList = dol_dir_list($objectDirPath . '/' . $objectFileName, 'files', 0, implode('|', $arrayofinclusion), '(\.meta|_preview.*\.png)$', 'date', SORT_DESC, 0, true);
1497
                        if (!empty($fileFoundList)) {
1498
                            $attachmentFileNameTrunc = $line->doc_ref;
1499
                            foreach ($fileFoundList as $fileFound) {
1500
                                if (strstr($fileFound['name'], $objectFileName)) {
1501
                                    // skip native invoice pdfs (canelle)
1502
                                    // We want to retrieve an attachment representative of the supplier invoice, not a fake document generated by Dolibarr.
1503
                                    if ($line->doc_type == 'supplier_invoice') {
1504
                                        if ($fileFound['name'] === $objectFileName . '.pdf') {
1505
                                            continue;
1506
                                        }
1507
                                    } elseif ($fileFound['name'] !== $objectFileName . '.pdf') {
1508
                                        continue;
1509
                                    }
1510
                                    $fileFoundPath = $objectDirPath . '/' . $objectFileName . '/' . $fileFound['name'];
1511
                                    if (file_exists($fileFoundPath)) {
1512
                                        $archiveFileList[$attachmentFileKey] = array(
1513
                                            'path' => $fileFoundPath,
1514
                                            'name' => $attachmentFileNameTrunc . '.pdf',
1515
                                        );
1516
                                        break;
1517
                                    }
1518
                                }
1519
                            }
1520
                        }
1521
                    }
1522
1523
                    if (isset($archiveFileList[$attachmentFileKey])) {
1524
                        $attachmentFileName = $archiveFileList[$attachmentFileKey]['name'];
1525
                    }
1526
                }
1527
1528
                $tab[] = $attachmentFileName;
1529
1530
                $output = implode($separator, $tab) . $end_line;
1531
1532
                if ($exportFile) {
1533
                    fwrite($exportFile, $output);
1534
                } else {
1535
                    print $output;
1536
                }
1537
            }
1538
        }
1539
1540
        return $archiveFileList;
1541
    }
1542
1543
    /**
1544
     * Export format : FEC2
1545
     * Last review for this format : 2023/10/12 Alexandre Spangaro ([email protected])
1546
     *
1547
     * Help to import in your software: https://wiki.dolibarr.org/index.php?title=Module_Comptabilit%C3%A9_en_Partie_Double#Exports_avec_fichiers_sources
1548
     *
1549
     * @param   array       $objectLines            data
1550
     * @param   resource    $exportFile             [=null] File resource to export or print if null
1551
     * @param   array       $archiveFileList        [=array()] Archive file list : array of ['path', 'name']
1552
     * @param   int         $withAttachment         [=0] Not add files or 1 to have attached in an archive
1553
     * @return  array       Archive file list : array of ['path', 'name']
1554
     */
1555
    public function exportFEC2($objectLines, $exportFile = null, $archiveFileList = array(), $withAttachment = 0)
1556
    {
1557
        global $conf, $langs;
1558
1559
        $separator = "\t";
1560
        $end_line = "\r\n";
1561
1562
        $tab = array();
1563
        $tab[] = "JournalCode";
1564
        $tab[] = "JournalLib";
1565
        $tab[] = "EcritureNum";
1566
        $tab[] = "EcritureDate";
1567
        $tab[] = "CompteNum";
1568
        $tab[] = "CompteLib";
1569
        $tab[] = "CompAuxNum";
1570
        $tab[] = "CompAuxLib";
1571
        $tab[] = "PieceRef";
1572
        $tab[] = "PieceDate";
1573
        $tab[] = "EcritureLib";
1574
        $tab[] = "Debit";
1575
        $tab[] = "Credit";
1576
        $tab[] = "EcritureLet";
1577
        $tab[] = "DateLet";
1578
        $tab[] = "ValidDate";
1579
        $tab[] = "Montantdevise";
1580
        $tab[] = "Idevise";
1581
        $tab[] = "DateLimitReglmt";
1582
        $tab[] = "NumFacture";
1583
        $tab[] = "FichierFacture";
1584
1585
        $output = implode($separator, $tab) . $end_line;
1586
        if ($exportFile) {
1587
            fwrite($exportFile, $output);
1588
        } else {
1589
            print $output;
1590
        }
1591
1592
        foreach ($objectLines as $line) {
1593
            if ($line->debit == 0 && $line->credit == 0) {
1594
                //unset($array[$line]);
1595
            } else {
1596
                $date_creation = dol_print_date($line->date_creation, '%Y%m%d');
1597
                $date_document = dol_print_date($line->doc_date, '%Y%m%d');
1598
                $date_lettering = dol_print_date($line->date_lettering, '%Y%m%d');
1599
                $date_validation = dol_print_date($line->date_validation, '%Y%m%d');
1600
                $date_limit_payment = dol_print_date($line->date_lim_reglement, '%Y%m%d');
1601
1602
                $refInvoice = '';
1603
                if ($line->doc_type == 'customer_invoice') {
1604
                    // Customer invoice
1605
                    $invoice = new Facture($this->db);
1606
                    $invoice->fetch($line->fk_doc);
1607
1608
                    $refInvoice = $invoice->ref;
1609
                } elseif ($line->doc_type == 'supplier_invoice') {
1610
                    // Supplier invoice
1611
                    $invoice = new FactureFournisseur($this->db);
1612
                    $invoice->fetch($line->fk_doc);
1613
1614
                    $refInvoice = $invoice->ref_supplier;
1615
                }
1616
1617
                $tab = array();
1618
1619
                // FEC:JournalCode
1620
                $tab[] = $line->code_journal;
1621
1622
                // FEC:JournalLib
1623
                $labeljournal = dol_string_unaccent($langs->transnoentities($line->journal_label));
1624
                $labeljournal = dol_string_nospecial($labeljournal, ' ');
1625
                $tab[] = $labeljournal;
1626
1627
                // FEC:EcritureNum
1628
                $tab[] = $line->piece_num;
1629
1630
                // FEC:EcritureDate
1631
                $tab[] = $date_creation;
1632
1633
                // FEC:CompteNum
1634
                $tab[] = length_accountg($line->numero_compte);
1635
1636
                // FEC:CompteLib
1637
                $tab[] = dol_string_unaccent($line->label_compte);
1638
1639
                // FEC:CompAuxNum
1640
                $tab[] = length_accounta($line->subledger_account);
1641
1642
                // FEC:CompAuxLib
1643
                $tab[] = dol_string_unaccent($line->subledger_label);
1644
1645
                // FEC:PieceRef
1646
                $tab[] = $line->doc_ref;
1647
1648
                // FEC:PieceDate
1649
                $tab[] = $date_document;
1650
1651
                // FEC:EcritureLib
1652
                // Clean label operation to prevent problem on export with tab separator & other character
1653
                $line->label_operation = str_replace(array("\t", "\n", "\r"), " ", $line->label_operation);
1654
                $line->label_operation = str_replace(array("..."), "", $line->label_operation);
1655
                $tab[] = dol_string_unaccent($line->label_operation);
1656
1657
                // FEC:Debit
1658
                $tab[] = price2fec($line->debit);
1659
1660
                // FEC:Credit
1661
                $tab[] = price2fec($line->credit);
1662
1663
                // FEC:EcritureLet
1664
                $tab[] = $line->lettering_code;
1665
1666
                // FEC:DateLet
1667
                $tab[] = $date_lettering;
1668
1669
                // FEC:ValidDate
1670
                $tab[] = $date_validation;
1671
1672
                // FEC:Montantdevise
1673
                $tab[] = $line->multicurrency_amount;
1674
1675
                // FEC:Idevise
1676
                $tab[] = $line->multicurrency_code;
1677
1678
                // FEC_suppl:DateLimitReglmt
1679
                $tab[] = $date_limit_payment;
1680
1681
                // FEC_suppl:NumFacture
1682
                // Clean ref invoice to prevent problem on export with tab separator & other character
1683
                $refInvoice = str_replace(array("\t", "\n", "\r"), " ", $refInvoice);
1684
                $tab[] = dol_trunc(self::toAnsi($refInvoice), 17, 'right', 'UTF-8', 1);
1685
1686
                // FEC_suppl:FichierFacture
1687
                // get document file
1688
                $attachmentFileName = '';
1689
                if ($withAttachment == 1) {
1690
                    $attachmentFileKey = trim($line->piece_num);
1691
1692
                    if (!isset($archiveFileList[$attachmentFileKey])) {
1693
                        $objectDirPath = '';
1694
                        $objectFileName = dol_sanitizeFileName($line->doc_ref);
1695
                        if ($line->doc_type == 'customer_invoice') {
1696
                            $objectDirPath = !empty($conf->invoice->multidir_output[$conf->entity]) ? $conf->invoice->multidir_output[$conf->entity] : $conf->invoice->dir_output;
1697
                        } elseif ($line->doc_type == 'expense_report') {
1698
                            $objectDirPath = !empty($conf->expensereport->multidir_output[$conf->entity]) ? $conf->expensereport->multidir_output[$conf->entity] : $conf->expensereport->dir_output;
1699
                        } elseif ($line->doc_type == 'supplier_invoice') {
1700
                            $objectDirPath = !empty($conf->fournisseur->facture->multidir_output[$conf->entity]) ? $conf->fournisseur->facture->multidir_output[$conf->entity] : $conf->fournisseur->facture->dir_output;
1701
                            $objectDirPath .= '/' . rtrim(get_exdir($invoice->id, 2, 0, 0, $invoice, 'invoice_supplier'), '/');
1702
                        }
1703
                        $arrayofinclusion = array();
1704
                        // If it is a supplier invoice, we want to use last uploaded file
1705
                        $arrayofinclusion[] = '^' . preg_quote($objectFileName, '/') . (($line->doc_type == 'supplier_invoice') ? '.+' : '') . '\.pdf$';
1706
                        $fileFoundList = dol_dir_list($objectDirPath . '/' . $objectFileName, 'files', 0, implode('|', $arrayofinclusion), '(\.meta|_preview.*\.png)$', 'date', SORT_DESC, 0, true);
1707
                        if (!empty($fileFoundList)) {
1708
                            $attachmentFileNameTrunc = $line->doc_ref;
1709
                            foreach ($fileFoundList as $fileFound) {
1710
                                if (strstr($fileFound['name'], $objectFileName)) {
1711
                                    // skip native invoice pdfs (canelle)
1712
                                    // We want to retrieve an attachment representative of the supplier invoice, not a fake document generated by Dolibarr.
1713
                                    if ($line->doc_type == 'supplier_invoice') {
1714
                                        if ($fileFound['name'] === $objectFileName . '.pdf') {
1715
                                            continue;
1716
                                        }
1717
                                    } elseif ($fileFound['name'] !== $objectFileName . '.pdf') {
1718
                                        continue;
1719
                                    }
1720
                                    $fileFoundPath = $objectDirPath . '/' . $objectFileName . '/' . $fileFound['name'];
1721
                                    if (file_exists($fileFoundPath)) {
1722
                                        $archiveFileList[$attachmentFileKey] = array(
1723
                                            'path' => $fileFoundPath,
1724
                                            'name' => $attachmentFileNameTrunc . '.pdf',
1725
                                        );
1726
                                        break;
1727
                                    }
1728
                                }
1729
                            }
1730
                        }
1731
                    }
1732
1733
                    if (isset($archiveFileList[$attachmentFileKey])) {
1734
                        $attachmentFileName = $archiveFileList[$attachmentFileKey]['name'];
1735
                    }
1736
                }
1737
1738
                $tab[] = $attachmentFileName;
1739
1740
                $output = implode($separator, $tab) . $end_line;
1741
                if ($exportFile) {
1742
                    fwrite($exportFile, $output);
1743
                } else {
1744
                    print $output;
1745
                }
1746
            }
1747
        }
1748
1749
        return $archiveFileList;
1750
    }
1751
1752
    /**
1753
     * Export format : SAGE50SWISS
1754
     *
1755
     * https://onlinehelp.sageschweiz.ch/default.aspx?tabid=19984
1756
     * http://media.topal.ch/Public/Schnittstellen/TAF/Specification/Sage50-TAF-format.pdf
1757
     *
1758
     * @param   array       $objectLines            data
1759
     * @param   resource    $exportFile             [=null] File resource to export or print if null
1760
     * @return  void
1761
     */
1762
    public function exportSAGE50SWISS($objectLines, $exportFile = null)
1763
    {
1764
        // SAGE50SWISS
1765
        $separator = ',';
1766
        $end_line = "\r\n";
1767
1768
        // Print header line
1769
        $tab = array();
1770
1771
        $tab[] = "Blg";
1772
        $tab[] = "Datum";
1773
        $tab[] = "Kto";
1774
        $tab[] = "S/H";
1775
        $tab[] = "Grp";
1776
        $tab[] = "GKto";
1777
        $tab[] = "SId";
1778
        $tab[] = "SIdx";
1779
        $tab[] = "KIdx";
1780
        $tab[] = "BTyp";
1781
        $tab[] = "MTyp";
1782
        $tab[] = "Code";
1783
        $tab[] = "Netto";
1784
        $tab[] = "Steuer";
1785
        $tab[] = "FW-Betrag";
1786
        $tab[] = "Tx1";
1787
        $tab[] = "Tx2";
1788
        $tab[] = "PkKey";
1789
        $tab[] = "OpId";
1790
        $tab[] = "Flag";
1791
1792
        $output = implode($separator, $tab) . $end_line;
1793
        if ($exportFile) {
1794
            fwrite($exportFile, $output);
1795
        } else {
1796
            print $output;
1797
        }
1798
1799
        $thisPieceNum = "";
1800
        $thisPieceAccountNr = "";
1801
        $aSize = count($objectLines);
1802
        foreach ($objectLines as $aIndex => $line) {
1803
            $sammelBuchung = false;
1804
            if ($aIndex - 2 >= 0 && $objectLines[$aIndex - 2]->piece_num == $line->piece_num) {
1805
                $sammelBuchung = true;
1806
            } elseif ($aIndex + 2 < $aSize && $objectLines[$aIndex + 2]->piece_num == $line->piece_num) {
1807
                $sammelBuchung = true;
1808
            } elseif (
1809
                $aIndex + 1 < $aSize
1810
                    && $objectLines[$aIndex + 1]->piece_num == $line->piece_num
1811
                    && $aIndex - 1 < $aSize
1812
                    && $objectLines[$aIndex - 1]->piece_num == $line->piece_num
1813
            ) {
1814
                $sammelBuchung = true;
1815
            }
1816
1817
            $tab = array();
1818
1819
            //Blg
1820
            $tab[] = $line->piece_num;
1821
1822
            // Datum
1823
            $date_document = dol_print_date($line->doc_date, '%d.%m.%Y');
1824
            $tab[] = $date_document;
1825
1826
            // Kto
1827
            $tab[] = length_accountg($line->numero_compte);
1828
            // S/H
1829
            if ($line->sens == 'D') {
1830
                $tab[] = 'S';
1831
            } else {
1832
                $tab[] = 'H';
1833
            }
1834
            // Grp
1835
            $tab[] = self::trunc($line->code_journal, 1);
1836
            // GKto
1837
            if (empty($line->code_tiers)) {
1838
                if ($line->piece_num == $thisPieceNum) {
1839
                    $tab[] = length_accounta($thisPieceAccountNr);
1840
                } else {
1841
                    $tab[] = "div";
1842
                }
1843
            } else {
1844
                $tab[] = length_accounta($line->code_tiers);
1845
            }
1846
            // SId
1847
            $tab[] = $this->separator;
1848
            // SIdx
1849
            $tab[] = "0";
1850
            // KIdx
1851
            $tab[] = "0";
1852
            // BTyp
1853
            $tab[] = "0";
1854
1855
            // MTyp 1=Fibu Einzelbuchung 2=Sammebuchung
1856
            if ($sammelBuchung) {
1857
                $tab[] = "2";
1858
            } else {
1859
                $tab[] = "1";
1860
            }
1861
            // Code
1862
            $tab[] = '""';
1863
            // Netto
1864
            $tab[] = abs($line->debit - $line->credit);
1865
            // Steuer
1866
            $tab[] = "0.00";
1867
            // FW-Betrag
1868
            $tab[] = "0.00";
1869
            // Tx1
1870
            $line1 = self::toAnsi($line->label_compte, 29);
1871
            if ($line1 == "LIQ" || $line1 == "LIQ Beleg ok" || strlen($line1) <= 3) {
1872
                $line1 = "";
1873
            }
1874
            $line2 = self::toAnsi($line->doc_ref, 29);
1875
            if (strlen($line1) == 0) {
1876
                $line1 = $line2;
1877
                $line2 = "";
1878
            }
1879
            if (strlen($line1) > 0 && strlen($line2) > 0 && (strlen($line1) + strlen($line2)) < 27) {
1880
                $line1 = $line1 . ' / ' . $line2;
1881
                $line2 = "";
1882
            }
1883
1884
            $tab[] = '"' . self::toAnsi($line1) . '"';
1885
            // Tx2
1886
            $tab[] = '"' . self::toAnsi($line2) . '"';
1887
            //PkKey
1888
            $tab[] = "0";
1889
            //OpId
1890
            $tab[] = $this->separator;
1891
1892
            // Flag
1893
            $tab[] = "0";
1894
1895
            $output = implode($separator, $tab) . $end_line;
1896
            if ($exportFile) {
1897
                fwrite($exportFile, $output);
1898
            } else {
1899
                print $output;
1900
            }
1901
1902
            if ($line->piece_num !== $thisPieceNum) {
1903
                $thisPieceNum = $line->piece_num;
1904
                $thisPieceAccountNr = $line->numero_compte;
1905
            }
1906
        }
1907
    }
1908
1909
    /**
1910
     * Export format : LD Compta version 9
1911
     * http://www.ldsysteme.fr/fileadmin/telechargement/np/ldcompta/Documentation/IntCptW9.pdf
1912
     *
1913
     * @param   array       $objectLines            data
1914
     * @param   resource    $exportFile             [=null] File resource to export or print if null
1915
     * @return  void
1916
     */
1917
    public function exportLDCompta($objectLines, $exportFile = null)
1918
    {
1919
        $separator = ';';
1920
        $end_line = "\r\n";
1921
1922
        foreach ($objectLines as $line) {
1923
            $date_document = dol_print_date($line->doc_date, '%Y%m%d');
1924
            $date_creation = dol_print_date($line->date_creation, '%Y%m%d');
1925
            $date_lim_reglement = dol_print_date($line->date_lim_reglement, '%Y%m%d');
1926
1927
            $tab = array();
1928
1929
            // TYPE
1930
            $type_enregistrement = 'E'; // For write movement
1931
            $tab[] = $type_enregistrement;
1932
            // JNAL
1933
            $tab[] = substr($line->code_journal, 0, 2);
1934
            // NECR
1935
            $tab[] = $line->id;
1936
            // NPIE
1937
            $tab[] = $line->piece_num;
1938
            // DATP
1939
            $tab[] = $date_document;
1940
            // LIBE
1941
            $tab[] = $line->label_operation;
1942
            // DATH
1943
            $tab[] = $date_lim_reglement;
1944
            // CNPI
1945
            if ($line->doc_type == 'supplier_invoice') {
1946
                if (($line->debit - $line->credit) > 0) {
1947
                    $nature_piece = 'AF';
1948
                } else {
1949
                    $nature_piece = 'FF';
1950
                }
1951
            } elseif ($line->doc_type == 'customer_invoice') {
1952
                if (($line->debit - $line->credit) < 0) {
1953
                    $nature_piece = 'AC';
1954
                } else {
1955
                    $nature_piece = 'FC';
1956
                }
1957
            } else {
1958
                $nature_piece = '';
1959
            }
1960
            $tab[] = $nature_piece;
1961
            // RACI
1962
            //          if (!empty($line->subledger_account)) {
1963
            //              if ($line->doc_type == 'supplier_invoice') {
1964
            //                  $racine_subledger_account = '40';
1965
            //              } elseif ($line->doc_type == 'customer_invoice') {
1966
            //                  $racine_subledger_account = '41';
1967
            //              } else {
1968
            //                  $racine_subledger_account = '';
1969
            //              }
1970
            //          } else {
1971
            $racine_subledger_account = ''; // for records of type E leave this field blank
1972
            //          }
1973
1974
            $tab[] = $racine_subledger_account; // deprecated CPTG & CPTA use instead
1975
            // MONT
1976
            $tab[] = price(abs($line->debit - $line->credit), 0, '', 1, 2, 2);
1977
            // CODC
1978
            $tab[] = $line->sens;
1979
            // CPTG
1980
            $tab[] = length_accountg($line->numero_compte);
1981
            // DATE
1982
            $tab[] = $date_creation;
1983
            // CLET
1984
            $tab[] = $line->lettering_code;
1985
            // DATL
1986
            $tab[] = $line->date_lettering;
1987
            // CPTA
1988
            if (!empty($line->subledger_account)) {
1989
                $tab[] = length_accounta($line->subledger_account);
1990
            } else {
1991
                $tab[] = "";
1992
            }
1993
            // C.N.A.T
1994
            if ($line->doc_type == 'supplier_invoice' && !empty($line->subledger_account)) {
1995
                $tab[] = 'F';
1996
            } elseif ($line->doc_type == 'customer_invoice' && !empty($line->subledger_account)) {
1997
                $tab[] = 'C';
1998
            } else {
1999
                $tab[] = "";
2000
            }
2001
            // SECT
2002
            $tab[] = "";
2003
            // CTRE
2004
            $tab[] = "";
2005
            // NORL
2006
            $tab[] = "";
2007
            // DATV
2008
            $tab[] = "";
2009
            // REFD
2010
            $tab[] = $line->doc_ref;
2011
            // CODH
2012
            $tab[] = "";
2013
            // NSEQ
2014
            $tab[] = "";
2015
            // MTDV
2016
            $tab[] = '0';
2017
            // CODV
2018
            $tab[] = "";
2019
            // TXDV
2020
            $tab[] = '0';
2021
            // MOPM
2022
            $tab[] = "";
2023
            // BONP
2024
            $tab[] =  "";
2025
            // BQAF
2026
            $tab[] = "";
2027
            // ECES
2028
            $tab[] = "";
2029
            // TXTL
2030
            $tab[] = "";
2031
            // ECRM
2032
            $tab[] = "";
2033
            // DATK
2034
            $tab[] = "";
2035
            // HEUK
2036
            $tab[] = "";
2037
2038
            $output = implode($separator, $tab) . $end_line;
2039
            if ($exportFile) {
2040
                fwrite($exportFile, $output);
2041
            } else {
2042
                print $output;
2043
            }
2044
        }
2045
    }
2046
2047
    /**
2048
     * Export format : LD Compta version 10 & higher
2049
     * Last review for this format : 08-15-2021 Alexandre Spangaro ([email protected])
2050
     *
2051
     * Help : http://www.ldsysteme.fr/fileadmin/telechargement/np/ldcompta/Documentation/IntCptW10.pdf
2052
     *
2053
     * @param   array       $objectLines            data
2054
     * @param   resource    $exportFile             [=null] File resource to export or print if null
2055
     * @return  void
2056
     */
2057
    public function exportLDCompta10($objectLines, $exportFile = null)
2058
    {
2059
        require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/company.lib.php';
2060
2061
        $separator = ';';
2062
        $end_line = "\r\n";
2063
        $last_codeinvoice = '';
2064
2065
        foreach ($objectLines as $line) {
2066
            // TYPE C
2067
            if ($last_codeinvoice != $line->doc_ref) {
2068
                //recherche societe en fonction de son code client
2069
                $sql = "SELECT code_client, fk_forme_juridique, nom, address, zip, town, fk_pays, phone, siret FROM " . MAIN_DB_PREFIX . "societe";
2070
                $sql .= " WHERE code_client = '" . $this->db->escape($line->thirdparty_code) . "'";
2071
                $resql = $this->db->query($sql);
2072
2073
                if ($resql && $this->db->num_rows($resql) > 0) {
2074
                    $soc = $this->db->fetch_object($resql);
2075
2076
                    $address = array('', '', '');
2077
                    if (strpos($soc->address, "\n") !== false) {
2078
                        $address = explode("\n", $soc->address);
2079
                        if (is_array($address) && count($address) > 0) {
2080
                            foreach ($address as $key => $data) {
2081
                                $address[$key] = str_replace(array("\t", "\n", "\r"), "", $data);
2082
                                $address[$key] = dol_trunc($address[$key], 40, 'right', 'UTF-8', 1);
2083
                            }
2084
                        }
2085
                    } else {
2086
                        $address[0] = substr(str_replace(array("\t", "\r"), " ", $soc->address), 0, 40);
2087
                        $address[1] = substr(str_replace(array("\t", "\r"), " ", $soc->address), 41, 40);
2088
                        $address[2] = substr(str_replace(array("\t", "\r"), " ", $soc->address), 82, 40);
2089
                    }
2090
2091
                    $tab = array();
2092
2093
                    $type_enregistrement = 'C';
2094
                    //TYPE
2095
                    $tab[] = $type_enregistrement;
2096
                    //NOCL
2097
                    $tab[] = $soc->code_client;
2098
                    //NMCM
2099
                    $tab[] = "";
2100
                    //LIBI
2101
                    $tab[] = "";
2102
                    //TITR
2103
                    $tab[] = "";
2104
                    //RSSO
2105
                    $tab[] = $soc->nom;
2106
                    //CAD1
2107
                    $tab[] = $address[0];
2108
                    //CAD2
2109
                    $tab[] = $address[1];
2110
                    //CAD3
2111
                    $tab[] = $address[2];
2112
                    //COPO
2113
                    $tab[] = $soc->zip;
2114
                    //BUDI
2115
                    $tab[] = substr($soc->town, 0, 40);
2116
                    //CPAY
2117
                    $tab[] = "";
2118
                    //PAYS
2119
                    $tab[] = substr(getCountry($soc->fk_pays), 0, 40);
2120
                    //NTEL
2121
                    $tab[] = $soc->phone;
2122
                    //TLEX
2123
                    $tab[] = "";
2124
                    //TLPO
2125
                    $tab[] = "";
2126
                    //TLCY
2127
                    $tab[] = "";
2128
                    //NINT
2129
                    $tab[] = "";
2130
                    //COMM
2131
                    $tab[] = "";
2132
                    //SIRE
2133
                    $tab[] = str_replace(" ", "", $soc->siret);
2134
                    //RIBP
2135
                    $tab[] = "";
2136
                    //DOBQ
2137
                    $tab[] = "";
2138
                    //IBBQ
2139
                    $tab[] = "";
2140
                    //COBQ
2141
                    $tab[] = "";
2142
                    //GUBQ
2143
                    $tab[] = "";
2144
                    //CPBQ
2145
                    $tab[] = "";
2146
                    //CLBQ
2147
                    $tab[] = "";
2148
                    //BIBQ
2149
                    $tab[] = "";
2150
                    //MOPM
2151
                    $tab[] = "";
2152
                    //DJPM
2153
                    $tab[] = "";
2154
                    //DMPM
2155
                    $tab[] = "";
2156
                    //REFM
2157
                    $tab[] = "";
2158
                    //SLVA
2159
                    $tab[] = "";
2160
                    //PLCR
2161
                    $tab[] = "";
2162
                    //ECFI
2163
                    $tab[] = "";
2164
                    //CREP
2165
                    $tab[] = "";
2166
                    //NREP
2167
                    $tab[] = "";
2168
                    //TREP
2169
                    $tab[] = "";
2170
                    //MREP
2171
                    $tab[] = "";
2172
                    //GRRE
2173
                    $tab[] = "";
2174
                    //LTTA
2175
                    $tab[] = "";
2176
                    //CACT
2177
                    $tab[] = "";
2178
                    //CODV
2179
                    $tab[] = "";
2180
                    //GRTR
2181
                    $tab[] = "";
2182
                    //NOFP
2183
                    $tab[] = "";
2184
                    //BQAF
2185
                    $tab[] = "";
2186
                    //BONP
2187
                    $tab[] = "";
2188
                    //CESC
2189
                    $tab[] = "";
2190
2191
                    $output = implode($separator, $tab) . $end_line;
2192
                    if ($exportFile) {
2193
                        fwrite($exportFile, $output);
2194
                    } else {
2195
                        print $output;
2196
                    }
2197
                }
2198
            }
2199
2200
            $tab = array();
2201
2202
            $date_document = dol_print_date($line->doc_date, '%Y%m%d');
2203
            $date_creation = dol_print_date($line->date_creation, '%Y%m%d');
2204
            $date_lim_reglement = dol_print_date($line->date_lim_reglement, '%Y%m%d');
2205
2206
            // TYPE E
2207
            $type_enregistrement = 'E'; // For write movement
2208
            $tab[] = $type_enregistrement;
2209
            // JNAL
2210
            $tab[] = substr($line->code_journal, 0, 2);
2211
            // NECR
2212
            $tab[] = $line->id;
2213
            // NPIE
2214
            $tab[] = $line->piece_num;
2215
            // DATP
2216
            $tab[] = $date_document;
2217
            // LIBE
2218
            $tab[] = dol_trunc($line->label_operation, 25, 'right', 'UTF-8', 1);
2219
            // DATH
2220
            $tab[] = $date_lim_reglement;
2221
            // CNPI
2222
            if ($line->doc_type == 'supplier_invoice') {
2223
                if (($line->amount) < 0) {      // Currently, only the sign of amount allows to know the type of invoice (standard or credit note). Other solution is to analyse debit/credit/role of account. TODO Add column doc_type_long or make amount mandatory with rule on sign.
2224
                    $nature_piece = 'AF';
2225
                } else {
2226
                    $nature_piece = 'FF';
2227
                }
2228
            } elseif ($line->doc_type == 'customer_invoice') {
2229
                if (($line->amount) < 0) {
2230
                    $nature_piece = 'AC';       // Currently, only the sign of amount allows to know the type of invoice (standard or credit note). Other solution is to analyse debit/credit/role of account. TODO Add column doc_type_long or make amount mandatory with rule on sign.
2231
                } else {
2232
                    $nature_piece = 'FC';
2233
                }
2234
            } else {
2235
                $nature_piece = '';
2236
            }
2237
            $tab[] = $nature_piece;
2238
            // RACI
2239
            //          if (!empty($line->subledger_account)) {
2240
            //              if ($line->doc_type == 'supplier_invoice') {
2241
            //                  $racine_subledger_account = '40';
2242
            //              } elseif ($line->doc_type == 'customer_invoice') {
2243
            //                  $racine_subledger_account = '41';
2244
            //              } else {
2245
            //                  $racine_subledger_account = '';
2246
            //              }
2247
            //          } else {
2248
            $racine_subledger_account = ''; // for records of type E leave this field blank
2249
            //          }
2250
2251
            $tab[] = $racine_subledger_account; // deprecated CPTG & CPTA use instead
2252
            // MONT
2253
            $tab[] = price(abs($line->debit - $line->credit), 0, '', 1, 2);
2254
            // CODC
2255
            $tab[] = $line->sens;
2256
            // CPTG
2257
            $tab[] = length_accountg($line->numero_compte);
2258
            // DATE
2259
            $tab[] = $date_document;
2260
            // CLET
2261
            $tab[] = $line->lettering_code;
2262
            // DATL
2263
            $tab[] = $line->date_lettering;
2264
            // CPTA
2265
            if (!empty($line->subledger_account)) {
2266
                $tab[] = length_accounta($line->subledger_account);
2267
            } else {
2268
                $tab[] = "";
2269
            }
2270
            // C.N.A.T
2271
            if ($line->doc_type == 'supplier_invoice' && !empty($line->subledger_account)) {
2272
                $tab[] = 'F';
2273
            } elseif ($line->doc_type == 'customer_invoice' && !empty($line->subledger_account)) {
2274
                $tab[] = 'C';
2275
            } else {
2276
                $tab[] = "";
2277
            }
2278
            // CTRE
2279
            $tab[] = "";
2280
            // NORL
2281
            $tab[] = "";
2282
            // DATV
2283
            $tab[] = "";
2284
            // REFD
2285
            $tab[] = $line->doc_ref;
2286
            // NECA
2287
            $tab[] = '0';
2288
            // CSEC
2289
            $tab[] = "";
2290
            // CAFF
2291
            $tab[] = "";
2292
            // CDES
2293
            $tab[] = "";
2294
            // QTUE
2295
            $tab[] = "";
2296
            // MTDV
2297
            $tab[] = '0';
2298
            // CODV
2299
            $tab[] = "";
2300
            // TXDV
2301
            $tab[] = '0';
2302
            // MOPM
2303
            $tab[] = "";
2304
            // BONP
2305
            $tab[] = "";
2306
            // BQAF
2307
            $tab[] = "";
2308
            // ECES
2309
            $tab[] = "";
2310
            // TXTL
2311
            $tab[] = "";
2312
            // ECRM
2313
            $tab[] = "";
2314
            // DATK
2315
            $tab[] = "";
2316
            // HEUK
2317
            $tab[] = "";
2318
2319
            $output = implode($separator, $tab) . $end_line;
2320
            if ($exportFile) {
2321
                fwrite($exportFile, $output);
2322
            } else {
2323
                print $output;
2324
            }
2325
2326
            $last_codeinvoice = $line->doc_ref;
2327
        }
2328
    }
2329
2330
    /**
2331
     * Export format : Charlemagne
2332
     *
2333
     * @param   array       $objectLines            data
2334
     * @param   resource    $exportFile             [=null] File resource to export or print if null
2335
     * @return  void
2336
     */
2337
    public function exportCharlemagne($objectLines, $exportFile = null)
2338
    {
2339
        global $langs;
2340
        $langs->load('compta');
2341
2342
        $separator = "\t";
2343
        $end_line = "\n";
2344
2345
        $tab = array();
2346
2347
        $tab[] = $langs->transnoentitiesnoconv('Date');
2348
        $tab[] = self::trunc($langs->transnoentitiesnoconv('Journal'), 6);
2349
        $tab[] = self::trunc($langs->transnoentitiesnoconv('Account'), 15);
2350
        $tab[] = self::trunc($langs->transnoentitiesnoconv('LabelAccount'), 60);
2351
        $tab[] = self::trunc($langs->transnoentitiesnoconv('Piece'), 20);
2352
        $tab[] = self::trunc($langs->transnoentitiesnoconv('LabelOperation'), 60);
2353
        $tab[] = $langs->transnoentitiesnoconv('Amount');
2354
        $tab[] = 'S';
2355
        $tab[] = self::trunc($langs->transnoentitiesnoconv('Analytic') . ' 1', 15);
2356
        $tab[] = self::trunc($langs->transnoentitiesnoconv('AnalyticLabel') . ' 1', 60);
2357
        $tab[] = self::trunc($langs->transnoentitiesnoconv('Analytic') . ' 2', 15);
2358
        $tab[] = self::trunc($langs->transnoentitiesnoconv('AnalyticLabel') . ' 2', 60);
2359
        $tab[] = self::trunc($langs->transnoentitiesnoconv('Analytic') . ' 3', 15);
2360
        $tab[] = self::trunc($langs->transnoentitiesnoconv('AnalyticLabel') . ' 3', 60);
2361
2362
        $output = implode($separator, $tab) . $end_line;
2363
        if ($exportFile) {
2364
            fwrite($exportFile, $output);
2365
        } else {
2366
            print $output;
2367
        }
2368
2369
        foreach ($objectLines as $line) {
2370
            $date_document = dol_print_date($line->doc_date, '%Y%m%d');
2371
2372
            $tab = array();
2373
2374
            $tab[] = $date_document; //Date
2375
2376
            $tab[] = self::trunc($line->code_journal, 6); //Journal code
2377
2378
            if (!empty($line->subledger_account)) {
2379
                $account = $line->subledger_account;
2380
            } else {
2381
                $account = $line->numero_compte;
2382
            }
2383
            $tab[] = self::trunc($account, 15); //Account number
2384
2385
            $tab[] = self::trunc($line->label_compte, 60); //Account label
2386
            $tab[] = self::trunc($line->doc_ref, 20); //Piece
2387
            // Clean label operation to prevent problem on export with tab separator & other character
2388
            $line->label_operation = str_replace(array("\t", "\n", "\r"), " ", $line->label_operation);
2389
            $tab[] = self::trunc($line->label_operation, 60); //Operation label
2390
            $tab[] = price(abs($line->debit - $line->credit)); //Amount
2391
            $tab[] = $line->sens; //Direction
2392
            $tab[] = ""; //Analytic
2393
            $tab[] = ""; //Analytic
2394
            $tab[] = ""; //Analytic
2395
            $tab[] = ""; //Analytic
2396
            $tab[] = ""; //Analytic
2397
            $tab[] = ""; //Analytic
2398
2399
            $output = implode($separator, $tab) . $end_line;
2400
            if ($exportFile) {
2401
                fwrite($exportFile, $output);
2402
            } else {
2403
                print $output;
2404
            }
2405
        }
2406
    }
2407
2408
    /**
2409
     * Export format : Gestimum V3
2410
     *
2411
     * @param   array       $objectLines            data
2412
     * @param   resource    $exportFile             [=null] File resource to export or print if null
2413
     * @return  void
2414
     */
2415
    public function exportGestimumV3($objectLines, $exportFile = null)
2416
    {
2417
        global $langs;
2418
2419
        $separator = ',';
2420
        $end_line = "\r\n";
2421
2422
        $invoices_infos = array();
2423
        $supplier_invoices_infos = array();
2424
        foreach ($objectLines as $line) {
2425
            if ($line->debit == 0 && $line->credit == 0) {
2426
                //unset($array[$line]);
2427
            } else {
2428
                $date_document = dol_print_date($line->doc_date, '%d/%m/%Y');
2429
                $date_echeance = dol_print_date($line->date_lim_reglement, '%Y%m%d');
2430
2431
                $invoice_ref = $line->doc_ref;
2432
                $company_name = "";
2433
2434
                if (($line->doc_type == 'customer_invoice' || $line->doc_type == 'supplier_invoice') && $line->fk_doc > 0) {
2435
                    if (
2436
                        ($line->doc_type == 'customer_invoice' && !isset($invoices_infos[$line->fk_doc])) ||
2437
                        ($line->doc_type == 'supplier_invoice' && !isset($supplier_invoices_infos[$line->fk_doc]))
2438
                    ) {
2439
                        if ($line->doc_type == 'customer_invoice') {
2440
                            // Get new customer invoice ref and company name
2441
                            $sql = 'SELECT f.ref, s.nom FROM ' . MAIN_DB_PREFIX . 'facture as f';
2442
                            $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'societe AS s ON f.fk_soc = s.rowid';
2443
                            $sql .= ' WHERE f.rowid = ' . ((int) $line->fk_doc);
2444
                            $resql = $this->db->query($sql);
2445
                            if ($resql) {
2446
                                if ($obj = $this->db->fetch_object($resql)) {
2447
                                    // Save invoice infos
2448
                                    $invoices_infos[$line->fk_doc] = array('ref' => $obj->ref, 'company_name' => $obj->nom);
2449
                                    $invoice_ref = $obj->ref;
2450
                                    $company_name = $obj->nom;
2451
                                }
2452
                            }
2453
                        } else {
2454
                            // Get new supplier invoice ref and company name
2455
                            $sql = 'SELECT ff.ref, s.nom FROM ' . MAIN_DB_PREFIX . 'facture_fourn as ff';
2456
                            $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'societe AS s ON ff.fk_soc = s.rowid';
2457
                            $sql .= ' WHERE ff.rowid = ' . ((int) $line->fk_doc);
2458
                            $resql = $this->db->query($sql);
2459
                            if ($resql) {
2460
                                if ($obj = $this->db->fetch_object($resql)) {
2461
                                    // Save invoice infos
2462
                                    $supplier_invoices_infos[$line->fk_doc] = array('ref' => $obj->ref, 'company_name' => $obj->nom);
2463
                                    $invoice_ref = $obj->ref;
2464
                                    $company_name = $obj->nom;
2465
                                }
2466
                            }
2467
                        }
2468
                    } elseif ($line->doc_type == 'customer_invoice') {
2469
                        // Retrieve invoice infos
2470
                        $invoice_ref = $invoices_infos[$line->fk_doc]['ref'];
2471
                        $company_name = $invoices_infos[$line->fk_doc]['company_name'];
2472
                    } else {
2473
                        // Retrieve invoice infos
2474
                        $invoice_ref = $supplier_invoices_infos[$line->fk_doc]['ref'];
2475
                        $company_name = $supplier_invoices_infos[$line->fk_doc]['company_name'];
2476
                    }
2477
                }
2478
2479
                $tab = array();
2480
2481
                $tab[] = $line->id;
2482
                $tab[] = $date_document;
2483
                $tab[] = substr($line->code_journal, 0, 4);
2484
2485
                if ((substr($line->numero_compte, 0, 3) == '411') || (substr($line->numero_compte, 0, 3) == '401')) {
2486
                    $tab[] = length_accountg($line->subledger_account);
2487
                } else {
2488
                    $tab[] = substr(length_accountg($line->numero_compte), 0, 15);
2489
                }
2490
                //Libellé Auto
2491
                $tab[] = "";
2492
                //print '"'.dol_trunc(str_replace('"', '', $line->label_operation),40,'right','UTF-8',1).'"';
2493
                //Libellé manual
2494
                $tab[] = dol_trunc(str_replace('"', '', $invoice_ref . (!empty($company_name) ? ' - ' : '') . $company_name), 40, 'right', 'UTF-8', 1);
2495
                //Numéro de pièce
2496
                $tab[] = dol_trunc(str_replace('"', '', $line->piece_num), 10, 'right', 'UTF-8', 1);
2497
                //Devise
2498
                $tab[] = 'EUR';
2499
                //Amount
2500
                $tab[] = price2num(abs($line->debit - $line->credit));
2501
                //Sens
2502
                $tab[] = $line->sens;
2503
                //Code lettrage
2504
                $tab[] = "";
2505
                //Date Echéance
2506
                $tab[] = $date_echeance;
2507
2508
                $output = implode($separator, $tab) . $end_line;
2509
                if ($exportFile) {
2510
                    fwrite($exportFile, $output);
2511
                } else {
2512
                    print $output;
2513
                }
2514
            }
2515
        }
2516
    }
2517
2518
    /**
2519
     * Export format : Gestimum V5
2520
     *
2521
     * @param   array       $objectLines            data
2522
     * @param   resource    $exportFile             [=null] File resource to export or print if null
2523
     * @return  void
2524
     */
2525
    public function exportGestimumV5($objectLines, $exportFile = null)
2526
    {
2527
        $separator = ',';
2528
        $end_line = "\r\n";
2529
2530
        foreach ($objectLines as $line) {
2531
            if ($line->debit == 0 && $line->credit == 0) {
2532
                //unset($array[$line]);
2533
            } else {
2534
                $date_document = dol_print_date($line->doc_date, '%d%m%Y');
2535
2536
                $tab = array();
2537
2538
                $tab[] = $line->id;
2539
                $tab[] = $date_document;
2540
                $tab[] = substr($line->code_journal, 0, 4);
2541
                if ((substr($line->numero_compte, 0, 3) == '411') || (substr($line->numero_compte, 0, 3) == '401')) {   // TODO No hard code value
2542
                    $tab[] = length_accountg($line->subledger_account);
2543
                } else {
2544
                    $tab[] = substr(length_accountg($line->numero_compte), 0, 15);
2545
                }
2546
                $tab[] = "";
2547
                $tab[] = '"' . dol_trunc(str_replace('"', '', $line->label_operation), 40, 'right', 'UTF-8', 1) . '"';
2548
                $tab[] = '"' . dol_trunc(str_replace('"', '', $line->doc_ref), 40, 'right', 'UTF-8', 1) . '"';
2549
                $tab[] = '"' . dol_trunc(str_replace('"', '', $line->piece_num), 10, 'right', 'UTF-8', 1) . '"';
2550
                $tab[] = price2num(abs($line->debit - $line->credit));
2551
                $tab[] = $line->sens;
2552
                $tab[] = $date_document;
2553
                $tab[] = "";
2554
                $tab[] = "";
2555
                $tab[] = 'EUR';
2556
2557
                $output = implode($separator, $tab) . $end_line;
2558
                if ($exportFile) {
2559
                    fwrite($exportFile, $output);
2560
                } else {
2561
                    print $output;
2562
                }
2563
            }
2564
        }
2565
    }
2566
2567
    /**
2568
    * Export format : iSuite Expert
2569
    *
2570
    * by OpenSolus [https://opensolus.fr]
2571
    *
2572
     * @param   array       $objectLines            data
2573
     * @param   resource    $exportFile             [=null] File resource to export or print if null
2574
     * @return  void
2575
    */
2576
    public function exportiSuiteExpert($objectLines, $exportFile = null)
2577
    {
2578
        $separator = ';';
2579
        $end_line = "\r\n";
2580
2581
2582
        foreach ($objectLines as $line) {
2583
            $tab = array();
2584
2585
            $date = dol_print_date($line->doc_date, '%d/%m/%Y');
2586
2587
            $tab[] = $line->piece_num;
2588
            $tab[] = $date;
2589
            $tab[] = substr($date, 6, 4);
2590
            $tab[] = substr($date, 3, 2);
2591
            $tab[] = substr($date, 0, 2);
2592
            $tab[] = $line->doc_ref;
2593
            //Conversion de chaine UTF8 en Latin9
2594
            $tab[] = mb_convert_encoding(str_replace(' - Compte auxiliaire', '', $line->label_operation), "Windows-1252", 'UTF-8');
2595
2596
            //Calcul de la longueur des numéros de comptes
2597
            $taille_numero = strlen(length_accountg($line->numero_compte));
2598
2599
            //Création du numéro de client et fournisseur générique
2600
            $numero_cpt_client = '411';
2601
            $numero_cpt_fourn = '401';
2602
            for ($i = 1; $i <= ($taille_numero - 3); $i++) {
2603
                $numero_cpt_client .= '0';
2604
                $numero_cpt_fourn .= '0';
2605
            }
2606
2607
            //Création des comptes auxiliaire des clients et fournisseur
2608
            if (length_accountg($line->numero_compte) == $numero_cpt_client || length_accountg($line->numero_compte) == $numero_cpt_fourn) {
2609
                $tab[] = rtrim(length_accounta($line->subledger_account), "0");
2610
            } else {
2611
                $tab[] = length_accountg($line->numero_compte);
2612
            }
2613
            $nom_client = explode(" - ", $line->label_operation);
2614
            $tab[] = mb_convert_encoding($nom_client[0], "Windows-1252", 'UTF-8');
2615
            $tab[] = price($line->debit);
2616
            $tab[] = price($line->credit);
2617
            $tab[] = price($line->montant);
2618
            $tab[] = $line->code_journal;
2619
2620
            $output = implode($separator, $tab) . $end_line;
2621
            if ($exportFile) {
2622
                fwrite($exportFile, $output);
2623
            } else {
2624
                print $output;
2625
            }
2626
        }
2627
    }
2628
2629
    /**
2630
     * trunc
2631
     *
2632
     * @param string    $str    String
2633
     * @param integer   $size   Data to trunc
2634
     * @return string
2635
     */
2636
    public static function trunc($str, $size)
2637
    {
2638
        return dol_trunc($str, $size, 'right', 'UTF-8', 1);
2639
    }
2640
2641
    /**
2642
     * toAnsi
2643
     *
2644
     * @param string    $str        Original string to encode and optionally truncate
2645
     * @param integer   $size       Truncate string after $size characters
2646
     * @return string               String encoded in Windows-1251 charset
2647
     */
2648
    public static function toAnsi($str, $size = -1)
2649
    {
2650
        $retVal = dol_string_nohtmltag($str, 1, 'Windows-1251');
2651
        if ($retVal >= 0 && $size >= 0) {
2652
            $retVal = dol_substr($retVal, 0, $size, 'Windows-1251');
2653
        }
2654
        return $retVal;
2655
    }
2656
}
2657