Passed
Branch develop (ad461a)
by
unknown
27:24
created

IntracommReport::addItemsFact()   C

Complexity

Conditions 12
Paths 10

Size

Total Lines 48
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 12
eloc 27
nc 10
nop 4
dl 0
loc 48
rs 6.9666
c 3
b 0
f 0

How to fix   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
/* Copyright (C) 2015       ATM Consulting          <[email protected]>
3
 * Copyright (C) 2019-2020  Open-DSI                <[email protected]>
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
/**
20
 *  \file       htdocs/intracommreport/class/intracommreport.class.php
21
 *  \ingroup    Intracomm report
22
 *  \brief      File of class to manage intracomm report
23
 */
24
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
25
26
/**
27
 * Class to manage intracomm report
28
 */
29
class IntracommReport extends CommonObject
30
{
31
    /**
32
     * @var string ID to identify managed object
33
     */
34
    public $element='intracommreport';
35
36
    /**
37
     * @var string Name of table without prefix where object is stored
38
     */
39
    public $table_element='intracommreport';
40
41
    /**
42
     * @var int Field with ID of parent key if this field has a parent
43
     */
44
    public $fk_element='fk_intracommreport';
45
46
    /**
47
     * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
48
     * @var int
49
     */
50
    public $ismultientitymanaged = 1;
51
52
    /**
53
     * DEB - Product
54
     */
55
    const TYPE_DEB = 0;
56
57
    /**
58
     * DES - Service
59
     */
60
    const TYPE_DES = 1;
61
62
	static $type = array(
63
	    'introduction'=>'Introduction'
64
		,'expedition'=>'Expédition'
65
    );
66
67
    /**
68
     * Constructor
69
     *
70
     * @param DoliDB $db Database handle
71
     */
72
    public function __construct(DoliDB $db)
73
    {
74
        $this->db = $db;
75
		$this->exporttype = 'deb';
76
	}
77
78
	/**
79
	 * Generate XML file
80
	 *
81
	 * @param int		$mode 				O for create, R for regenerate (Look always 0 ment toujours 0 within the framework of XML exchanges according to documentation)
82
	 * @param string	$type 				Declaration type by default - introduction or expedition (always 'expedition' for Des)
83
	 * @param string	$period_reference	Period of reference
84
	 * @return void
85
	 */
86
	public function getXML($mode = 'O', $type = 'introduction', $period_reference = '')
87
	{
88
89
		global $conf, $mysoc;
90
91
		/**************Construction de quelques variables********************/
92
		$party_id = substr(strtr($mysoc->tva_intra, array(' '=>'')), 0, 4).$mysoc->idprof2;
93
		$declarant = substr($mysoc->managers, 0, 14);
94
		$id_declaration = self::getNumeroDeclaration($this->numero_declaration);
0 ignored issues
show
Bug Best Practice introduced by
The property numero_declaration does not exist on IntracommReport. Did you maybe forget to declare it?
Loading history...
Bug introduced by
The method getNumeroDeclaration() does not exist on IntracommReport. ( Ignorable by Annotation )

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

94
		/** @scrutinizer ignore-call */ 
95
  $id_declaration = self::getNumeroDeclaration($this->numero_declaration);

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

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

Loading history...
95
		/********************************************************************/
96
97
		/**************Construction du fichier XML***************************/
98
		$e = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" standalone="yes"?><INSTAT></INSTAT>');
99
100
		$enveloppe = $e->addChild('Envelope');
101
		$enveloppe->addChild('envelopeId', $conf->global->INTRACOMMREPORT_NUM_AGREMENT);
102
		$date_time = $enveloppe->addChild('DateTime');
103
		$date_time->addChild('date', date('Y-m-d'));
104
		$date_time->addChild('time', date('H:i:s'));
105
		$party = $enveloppe->addChild('Party');
106
		$party->addAttribute('partType', $conf->global->INTRACOMMREPORT_TYPE_ACTEUR);
107
		$party->addAttribute('partyRole', $conf->global->INTRACOMMREPORT_ROLE_ACTEUR);
108
		$party->addChild('partyId', $party_id);
109
		$party->addChild('partyName', $declarant);
110
		$enveloppe->addChild('softwareUsed', 'Dolibarr');
111
		$declaration = $enveloppe->addChild('Declaration');
112
		$declaration->addChild('declarationId', $id_declaration);
113
		$declaration->addChild('referencePeriod', $period_reference);
114
		if ($conf->global->INTRACOMMREPORT_TYPE_ACTEUR === 'PSI') $psiId = $party_id;
115
		else $psiId = 'NA';
116
		$declaration->addChild('PSIId', $psiId);
117
		$function = $declaration->addChild('Function');
118
		$functionCode = $function->addChild('functionCode', $mode);
119
		$declaration->addChild('declarationTypeCode', $conf->global->{'INTRACOMMREPORT_NIV_OBLIGATION_'.strtoupper($type)});
120
		$declaration->addChild('flowCode', ($type == 'introduction' ? 'A' : 'D'));
121
		$declaration->addChild('currencyCode', $conf->global->MAIN_MONNAIE);
122
		/********************************************************************/
123
124
		/**************Ajout des lignes de factures**************************/
125
		$res = self::addItemsFact($declaration, $type, $period_reference);
126
		/********************************************************************/
127
128
		$this->errors = array_unique($this->errors);
129
130
		if (!empty($res)) return $e->asXML();
131
		else return 0;
132
	}
133
134
	/**
135
	 * Generate XMLDes file
136
	 *
137
	 * @param int		$period_year		Year of declaration
138
	 * @param int		$period_month		Month of declaration
139
	 * @param string	$type_declaration	Declaration type by default - introduction or expedition (always 'expedition' for Des)
140
	 * @return void
141
	 */
142
	public function getXMLDes($period_year, $period_month, $type_declaration = 'expedition')
143
	{
144
		global $mysoc;
145
146
		$e = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" ?><fichier_des></fichier_des>');
147
148
		$declaration_des = $e->addChild('declaration_des');
149
		$declaration_des->addChild('num_des', self::getDeclarationNumber($this->numero_declaration));
0 ignored issues
show
Bug Best Practice introduced by
The property numero_declaration does not exist on IntracommReport. Did you maybe forget to declare it?
Loading history...
150
		$declaration_des->addChild('num_tvaFr', $mysoc->tva_intra); // /^FR[a-Z0-9]{2}[0-9]{9}$/  // Doit faire 13 caractères
151
		$declaration_des->addChild('mois_des', $period_month);
152
		$declaration_des->addChild('an_des', $period_year);
153
154
		/**************Ajout des lignes de factures**************************/
155
		$res = self::addItemsFact($declaration_des, $type_declaration, $period_year.'-'.$period_month, 'des');
156
		/********************************************************************/
157
158
		$this->errors = array_unique($this->errors);
159
160
		if (!empty($res)) return $e->asXML();
161
		else return 0;
162
	}
163
164
	/**
165
	 *  Add line from invoice
166
	 *
167
	 *  @param      int		$declaration		Reference declaration
168
	 *  @param      string	$type				Declaration type by default - introduction or expedition (always 'expedition' for Des)
169
	 *  @param      int		$period_reference	Reference period
170
	 *  @param      string	$exporttype	    	deb=DEB, des=DES
171
	 *  @return     int       			  		<0 if KO, >0 if OK
172
	 */
173
	public function addItemsFact(&$declaration, $type, $period_reference, $exporttype = 'deb')
174
	{
175
		global $conf;
176
177
		require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
178
179
		$sql = $this->getSQLFactLines($type, $period_reference, $exporttype);
180
181
		$resql = $this->db->query($sql);
182
183
		if ($resql) {
184
			$i=1;
185
186
			if (empty($resql->num_rows)) {
187
				$this->errors[] = 'No data for this period';
188
				return 0;
189
			}
190
191
			if ($exporttype == 'deb' && $conf->global->INTRACOMMREPORT_CATEG_FRAISDEPORT > 0) {
192
				$categ_fraisdeport = new Categorie();
193
				$categ_fraisdeport->fetch($conf->global->INTRACOMMREPORT_CATEG_FRAISDEPORT);
194
				$TLinesFraisDePort = array();
195
			}
196
197
			while ($res = $this->db->fetch_object($resql)) {
198
				if ($exporttype == 'des')
199
				{
200
					$this->addItemXMlDes($declaration, $res, $i);
201
				} else {
202
					if (empty($res->fk_pays)) {
203
						// We don't stop the loop because we want to know all the third parties who don't have an informed country
204
						$this->errors[] = 'Country not filled in for the third party <a href="'.dol_buildpath('/societe/soc.php', 1).'?socid='.$res->id_client.'">'.$res->nom.'</a>';
205
					} else {
206
						if ($conf->global->INTRACOMMREPORT_CATEG_FRAISDEPORT > 0 && $categ_fraisdeport->containsObject('product', $res->id_prod)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $categ_fraisdeport does not seem to be defined for all execution paths leading up to this point.
Loading history...
207
							$TLinesFraisDePort[] = $res;
208
						} else $this->addItemXMl($declaration, $res, $i, '');
209
					}
210
				}
211
212
				$i++;
213
			}
214
215
			if (!empty($TLinesFraisDePort)) $this->addItemFraisDePort($declaration, $TLinesFraisDePort, $type, $categ_fraisdeport, $i);
216
217
			if (count($this->errors) > 0) return 0;
218
		}
219
220
		return 1;
221
	}
222
223
	/**
224
	 *  Add invoice line
225
	 *
226
	 *  @param      string	$type				Declaration type by default - introduction or expedition (always 'expedition' for Des)
227
	 *  @param      int		$period_reference	Reference declaration
228
	 *  @param      string	$exporttype	    	deb=DEB, des=DES
229
	 *  @return     int       			  		<0 if KO, >0 if OK
230
	 */
231
	public function getSQLFactLines($type, $period_reference, $exporttype = 'deb')
232
	{
233
		global $mysoc, $conf;
234
235
		if ($type=='expedition' || $exporttype=='des') {
236
			$sql = 'SELECT f.facnumber, f.total as total_ht';
237
			$table = 'facture';
238
			$table_extraf = 'facture_extrafields';
239
			$tabledet = 'facturedet';
240
			$field_link = 'fk_facture';
241
		}
242
		else { // Introduction
243
			$sql = 'SELECT f.ref_supplier as facnumber, f.total_ht';
244
			$table = 'facture_fourn';
245
			$table_extraf = 'facture_fourn_extrafields';
246
			$tabledet = 'facture_fourn_det';
247
			$field_link = 'fk_facture_fourn';
248
		}
249
		$sql.= ', l.fk_product, l.qty
250
				, p.weight, p.rowid as id_prod, p.customcode
251
				, s.rowid as id_client, s.nom, s.zip, s.fk_pays, s.tva_intra
252
				, c.code
253
				, ext.mode_transport
254
				FROM '.MAIN_DB_PREFIX.$tabledet.' l
255
				INNER JOIN '.MAIN_DB_PREFIX.$table.' f ON (f.rowid = l.'.$field_link.')
256
				LEFT JOIN '.MAIN_DB_PREFIX.$table_extraf.' ext ON (ext.fk_object = f.rowid)
257
				INNER JOIN '.MAIN_DB_PREFIX.'product p ON (p.rowid = l.fk_product)
258
				INNER JOIN '.MAIN_DB_PREFIX.'societe s ON (s.rowid = f.fk_soc)
259
				LEFT JOIN '.MAIN_DB_PREFIX.'c_country c ON (c.rowid = s.fk_pays)
260
				WHERE f.fk_statut > 0
261
				AND l.product_type = '.($exporttype == 'des' ? 1 : 0).'
262
				AND f.entity = '.$conf->entity.'
263
				AND (s.fk_pays <> '.$mysoc->country_id.' OR s.fk_pays IS NULL)
264
				AND f.datef BETWEEN "'.$period_reference.'-01" AND "'.$period_reference.'-'.date('t').'"';
265
266
		return $sql;
267
	}
268
269
	/**
270
	 *	Add item for DEB
271
	 *
272
	 * 	@param      int		$declaration		Reference declaration
273
	 * 	@param      int		$res				Result of request SQL
274
	 *  @param      int		$i					Line Id
275
	 * 	@param      string	$code_douane_spe	Specific customs authorities code
276
	 *  @return     void
277
	 */
278
	public function addItemXMl(&$declaration, &$res, $i, $code_douane_spe = '')
279
	{
280
		$item = $declaration->addChild('Item');
0 ignored issues
show
Bug introduced by
The method addChild() does not exist on integer. ( Ignorable by Annotation )

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

280
		/** @scrutinizer ignore-call */ 
281
  $item = $declaration->addChild('Item');

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

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

Loading history...
281
		$item->addChild('ItemNumber', $i);
282
		$cn8 = $item->addChild('CN8');
283
		if (empty($code_douane_spe)) $code_douane = $res->customcode;
0 ignored issues
show
Bug introduced by
The property customcode does not exist on integer.
Loading history...
284
		else $code_douane = $code_douane_spe;
285
		$cn8->addChild('CN8Code', $code_douane);
286
		if (!empty($res->tva_intra)) $item->addChild('partnerId', $res->tva_intra);
0 ignored issues
show
Bug introduced by
The property tva_intra does not exist on integer.
Loading history...
287
		$item->addChild('MSConsDestCode', $res->code); // code iso pays client
0 ignored issues
show
Bug introduced by
The property code does not exist on integer.
Loading history...
288
		$item->addChild('netMass', $res->weight * $res->qty); // Poids du produit
0 ignored issues
show
Bug introduced by
The property qty does not exist on integer.
Loading history...
Bug introduced by
The property weight does not exist on integer.
Loading history...
289
		$item->addChild('quantityInSU', $res->qty); // Quantité de produit dans la ligne
290
		$item->addChild('invoicedAmount', round($res->total_ht)); // Montant total ht de la facture (entier attendu)
0 ignored issues
show
Bug introduced by
The property total_ht does not exist on integer.
Loading history...
291
		$item->addChild('invoicedNumber', $res->facnumber); // Numéro facture
0 ignored issues
show
Bug introduced by
The property facnumber does not exist on integer.
Loading history...
292
		$item->addChild('statisticalProcedureCode', '11');
293
		$nature_of_transaction = $item->addChild('NatureOfTransaction');
294
		$nature_of_transaction->addChild('natureOfTransactionACode', 1);
295
		$nature_of_transaction->addChild('natureOfTransactionBCode', 1);
296
		$item->addChild('modeOfTransportCode', $res->mode_transport);
0 ignored issues
show
Bug introduced by
The property mode_transport does not exist on integer.
Loading history...
297
		$item->addChild('regionCode', substr($res->zip, 0, 2));
0 ignored issues
show
Bug introduced by
The property zip does not exist on integer.
Loading history...
298
	}
299
300
	/**
301
	 *	Add item for DES
302
	 *
303
	 * 	@param      int		$declaration		Reference declaration
304
	 * 	@param      int		$res				Result of request SQL
305
	 *  @param      int		$i					Line Id
306
	 *  @return     void
307
	 */
308
	public function addItemXMlDes($declaration, &$res, $i)
309
	{
310
		$item = $declaration->addChild('ligne_des');
311
		$item->addChild('numlin_des', $i);
312
		$item->addChild('valeur', round($res->total_ht)); // Total amount excl. tax of the invoice (whole amount expected)
0 ignored issues
show
Bug introduced by
The property total_ht does not exist on integer.
Loading history...
313
		$item->addChild('partner_des', $res->tva_intra); // Represents the foreign customer's VAT number
0 ignored issues
show
Bug introduced by
The property tva_intra does not exist on integer.
Loading history...
314
	}
315
316
	/**
317
	 *	This function adds an item by retrieving the customs code of the product with the highest amount in the invoice
318
	 *
319
	 * 	@param      int		$declaration		Reference declaration
320
	 * 	@param      int		$TLinesFraisDePort	Data of shipping costs line
321
	 *  @param      string	$type				Declaration type by default - introduction or expedition (always 'expedition' for Des)
322
	 *  @param      int		$categ_fraisdeport	Id of category of shipping costs
323
	 *  @param      int		$i					Line Id
324
	 *  @return     void
325
	 */
326
	public function addItemFraisDePort(&$declaration, &$TLinesFraisDePort, $type, &$categ_fraisdeport, $i)
327
	{
328
329
		global $conf;
330
331
		if ($type=='expedition') {
332
			$table = 'facture';
333
			$tabledet = 'facturedet';
334
			$field_link = 'fk_facture';
335
			$more_sql = 'f.facnumber';
336
		} else { // Introduction
337
			$table = 'facture_fourn';
338
			$tabledet = 'facture_fourn_det';
339
			$field_link = 'fk_facture_fourn';
340
			$more_sql = 'f.ref_supplier';
341
		}
342
343
		foreach ($TLinesFraisDePort as $res) {
0 ignored issues
show
Bug introduced by
The expression $TLinesFraisDePort of type integer is not traversable.
Loading history...
344
			$sql = 'SELECT p.customcode
345
					FROM '.MAIN_DB_PREFIX.$tabledet.' d
346
					INNER JOIN '.MAIN_DB_PREFIX.$table.' f ON (f.rowid = d.'.$field_link.')
347
					INNER JOIN '.MAIN_DB_PREFIX.'product p ON (p.rowid = d.fk_product)
348
					WHERE d.fk_product IS NOT NULL
349
					AND f.entity = '.$conf->entity.'
350
					AND '.$more_sql.' = "'.$res->facnumber.'"
351
					AND d.total_ht =
352
					(
353
						SELECT MAX(d.total_ht)
354
						FROM '.MAIN_DB_PREFIX.$tabledet.' d
355
						INNER JOIN '.MAIN_DB_PREFIX.$table.' f ON (f.rowid = d.'.$field_link.')
356
						WHERE d.fk_product IS NOT NULL
357
						AND '.$more_sql.' = "'.$res->facnumber.'"
358
						AND d.fk_product NOT IN
359
						(
360
							SELECT fk_product
361
							FROM '.MAIN_DB_PREFIX.'categorie_product
362
							WHERE fk_categorie = '.$categ_fraisdeport->id.'
0 ignored issues
show
Bug introduced by
The property id does not exist on integer.
Loading history...
363
						)
364
					)';
365
366
			$resql = $this->db->query($sql);
367
			$ress = $this->db->fetch_object($resql);
368
369
			$this->addItemXMl($declaration, $res, $i, $ress->customcode);
370
371
			$i++;
372
		}
373
	}
374
375
	/**
376
	 *	Return next reference of declaration not already used (or last reference)
377
	 *
378
	 *	@return    string					free ref or last ref
379
	 */
380
	public function getNextDeclarationNumber()
381
	{
382
		$resql = $this->db->query('SELECT MAX(numero_declaration) as max_numero_declaration FROM '.$this->get_table().' WHERE exporttype="'.$this->exporttype.'"');
0 ignored issues
show
Bug introduced by
The method get_table() does not exist on IntracommReport. ( Ignorable by Annotation )

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

382
		$resql = $this->db->query('SELECT MAX(numero_declaration) as max_numero_declaration FROM '.$this->/** @scrutinizer ignore-call */ get_table().' WHERE exporttype="'.$this->exporttype.'"');

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

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

Loading history...
383
		if ($resql) $res = $this->db->fetch_object($resql);
384
385
		return ($res->max_numero_declaration + 1);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $res does not seem to be defined for all execution paths leading up to this point.
Loading history...
386
	}
387
388
	/**
389
	 *	Verify declaration number. Positive integer of a maximum of 6 characters recommended by the documentation
390
	 *
391
	 *	@param     	int		$number		Number to verify / convert
392
	 *	@return		int 				Number
393
	 */
394
	public static function getDeclarationNumber($number)
395
	{
396
		return str_pad($number, 6, 0, STR_PAD_LEFT);
397
	}
398
399
	/**
400
	 *	Generate XML file
401
	 *
402
	 *	@return		void
403
	 */
404
	public function generateXMLFile()
405
	{
406
407
		$name = $this->periode.'.xml';
0 ignored issues
show
Bug Best Practice introduced by
The property periode does not exist on IntracommReport. Did you maybe forget to declare it?
Loading history...
408
		$fname = sys_get_temp_dir().'/'.$name;
409
		$f = fopen($fname, 'w+');
410
		fwrite($f, $this->content_xml);
0 ignored issues
show
Bug introduced by
The property content_xml does not exist on IntracommReport. Did you mean context?
Loading history...
411
		fclose($f);
412
413
		header('Content-Description: File Transfer');
414
	    header('Content-Type: application/xml');
415
	    header('Content-Disposition: attachment; filename="'.$name.'"');
416
	    header('Expires: 0');
417
	    header('Cache-Control: must-revalidate');
418
	    header('Pragma: public');
419
	    header('Content-Length: ' . filesize($fname));
420
	    readfile($fname);
421
		exit;
422
	}
423
}
424