Passed
Push — EXTRACT_CLASSES ( 231cec )
by Rafael
70:48
created

AccountancyExport::exportFEC()   F

Complexity

Conditions 25
Paths 2392

Size

Total Lines 199
Code Lines 115

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 25
eloc 115
nc 2392
nop 4
dl 0
loc 199
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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