dolibarr 19.0.3
intracommreport.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2015 ATM Consulting <support@atm-consulting.fr>
3 * Copyright (C) 2019-2020 Open-DSI <support@open-dsi.fr>
4 * Copyright (C) 2020 Frédéric France <frederic.france@netlogic.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
27require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
28
29
34{
38 public $element = 'intracommreport';
39
43 public $table_element = 'intracommreport';
44
48 public $fk_element = 'fk_intracommreport';
49
54 public $ismultientitymanaged = 1;
55
56 public $picto = 'intracommreport';
57
58
59 public $label; // ref ???
60
61 public $period;
62
63 public $declaration;
64
68 public $declaration_number;
69
70 public $exporttype; // deb or des
71 public $type_declaration; // 'introduction' or 'expedition'
72 public $numero_declaration;
73
74
78 const TYPE_DEB = 0;
79
83 const TYPE_DES = 1;
84
85 public static $type = array(
86 'introduction'=>'Introduction',
87 'expedition'=>'Expédition'
88 );
89
90
96 public function __construct(DoliDB $db)
97 {
98 $this->db = $db;
99 $this->exporttype = 'deb';
100 }
101
109 public function create($user, $notrigger = 0)
110 {
111 return 1;
112 }
113
120 public function fetch($id)
121 {
122 return 1;
123 }
124
133 public function delete($id, $user, $notrigger = 0)
134 {
135 return 1;
136 }
137
146 public function getXML($mode = 'O', $type = 'introduction', $period_reference = '')
147 {
148 global $conf, $mysoc;
149
150 /**************Construction de quelques variables********************/
151 $party_id = substr(strtr($mysoc->tva_intra, array(' '=>'')), 0, 4).$mysoc->idprof2;
152 $declarant = substr($mysoc->managers, 0, 14);
153 $id_declaration = self::getDeclarationNumber($this->numero_declaration);
154 /********************************************************************/
155
156 /**************Construction du fichier XML***************************/
157 $e = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" standalone="yes"?><INSTAT></INSTAT>');
158
159 $enveloppe = $e->addChild('Envelope');
160 $enveloppe->addChild('envelopeId', $conf->global->INTRACOMMREPORT_NUM_AGREMENT);
161 $date_time = $enveloppe->addChild('DateTime');
162 $date_time->addChild('date', date('Y-m-d'));
163 $date_time->addChild('time', date('H:i:s'));
164 $party = $enveloppe->addChild('Party');
165 $party->addAttribute('partyType', $conf->global->INTRACOMMREPORT_TYPE_ACTEUR);
166 $party->addAttribute('partyRole', $conf->global->INTRACOMMREPORT_ROLE_ACTEUR);
167 $party->addChild('partyId', $party_id);
168 $party->addChild('partyName', $declarant);
169 $enveloppe->addChild('softwareUsed', 'Dolibarr');
170 $declaration = $enveloppe->addChild('Declaration');
171 $declaration->addChild('declarationId', $id_declaration);
172 $declaration->addChild('referencePeriod', $period_reference);
173 if ($conf->global->INTRACOMMREPORT_TYPE_ACTEUR === 'PSI') {
174 $psiId = $party_id;
175 } else {
176 $psiId = 'NA';
177 }
178 $declaration->addChild('PSIId', $psiId);
179 $function = $declaration->addChild('Function');
180 $functionCode = $function->addChild('functionCode', $mode);
181 $declaration->addChild('declarationTypeCode', getDolGlobalString('INTRACOMMREPORT_NIV_OBLIGATION_'.strtoupper($type)));
182 $declaration->addChild('flowCode', ($type == 'introduction' ? 'A' : 'D'));
183 $declaration->addChild('currencyCode', $conf->global->MAIN_MONNAIE);
184 /********************************************************************/
185
186 /**************Ajout des lignes de factures**************************/
187 $res = $this->addItemsFact($declaration, $type, $period_reference);
188 /********************************************************************/
189
190 $this->errors = array_unique($this->errors);
191
192 if (!empty($res)) {
193 return $e->asXML();
194 } else {
195 return 0;
196 }
197 }
198
207 public function getXMLDes($period_year, $period_month, $type_declaration = 'expedition')
208 {
209 global $mysoc;
210
211 $e = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" ?><fichier_des></fichier_des>');
212
213 $declaration_des = $e->addChild('declaration_des');
214 $declaration_des->addChild('num_des', self::getDeclarationNumber($this->numero_declaration));
215 $declaration_des->addChild('num_tvaFr', $mysoc->tva_intra); // /^FR[a-Z0-9]{2}[0-9]{9}$/ // Doit faire 13 caractères
216 $declaration_des->addChild('mois_des', $period_month);
217 $declaration_des->addChild('an_des', $period_year);
218
219 // Add invoice lines
220 $res = $this->addItemsFact($declaration_des, $type_declaration, $period_year.'-'.$period_month, 'des');
221
222 $this->errors = array_unique($this->errors);
223
224 if (!empty($res)) {
225 return $e->asXML();
226 } else {
227 return 0;
228 }
229 }
230
240 public function addItemsFact(&$declaration, $type, $period_reference, $exporttype = 'deb')
241 {
242 global $conf;
243
244 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
245
246 $sql = $this->getSQLFactLines($type, $period_reference, $exporttype);
247
248 $resql = $this->db->query($sql);
249
250 if ($resql) {
251 $i = 1;
252
253 if ($this->db->num_rows($resql) <= 0) {
254 $this->errors[] = 'No data for this period';
255 return 0;
256 }
257
258 if ($exporttype == 'deb' && getDolGlobalInt('INTRACOMMREPORT_CATEG_FRAISDEPORT') > 0) {
259 $categ_fraisdeport = new Categorie($this->db);
260 $categ_fraisdeport->fetch($conf->global->INTRACOMMREPORT_CATEG_FRAISDEPORT);
261 $TLinesFraisDePort = array();
262 }
263
264 while ($res = $this->db->fetch_object($resql)) {
265 if ($exporttype == 'des') {
266 $this->addItemXMlDes($declaration, $res, $i);
267 } else {
268 if (empty($res->fk_pays)) {
269 // We don't stop the loop because we want to know all the third parties who don't have an informed country
270 $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>';
271 } else {
272 if (getDolGlobalInt('INTRACOMMREPORT_CATEG_FRAISDEPORT') > 0 && $categ_fraisdeport->containsObject('product', $res->id_prod)) {
273 $TLinesFraisDePort[] = $res;
274 } else {
275 $this->addItemXMl($declaration, $res, $i, '');
276 }
277 }
278 }
279
280 $i++;
281 }
282
283 if (!empty($TLinesFraisDePort)) {
284 $this->addItemFraisDePort($declaration, $TLinesFraisDePort, $type, $categ_fraisdeport, $i);
285 }
286
287 if (count($this->errors) > 0) {
288 return 0;
289 }
290 }
291
292 return 1;
293 }
294
303 public function getSQLFactLines($type, $period_reference, $exporttype = 'deb')
304 {
305 global $mysoc, $conf;
306
307 if ($type == 'expedition' || $exporttype == 'des') {
308 $sql = "SELECT f.ref as refinvoice, f.total_ht";
309 $table = 'facture';
310 $table_extraf = 'facture_extrafields';
311 $tabledet = 'facturedet';
312 $field_link = 'fk_facture';
313 } else { // Introduction
314 $sql = "SELECT f.ref_supplier as refinvoice, f.total_ht";
315 $table = 'facture_fourn';
316 $table_extraf = 'facture_fourn_extrafields';
317 $tabledet = 'facture_fourn_det';
318 $field_link = 'fk_facture_fourn';
319 }
320 $sql .= ", l.fk_product, l.qty
321 , p.weight, p.rowid as id_prod, p.customcode
322 , s.rowid as id_client, s.nom, s.zip, s.fk_pays, s.tva_intra
323 , c.code
324 , ext.mode_transport
325 FROM ".MAIN_DB_PREFIX.$tabledet." l
326 INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = l.".$this->db->escape($field_link).")
327 LEFT JOIN ".MAIN_DB_PREFIX.$table_extraf." ext ON (ext.fk_object = f.rowid)
328 INNER JOIN ".MAIN_DB_PREFIX."product p ON (p.rowid = l.fk_product)
329 INNER JOIN ".MAIN_DB_PREFIX."societe s ON (s.rowid = f.fk_soc)
330 LEFT JOIN ".MAIN_DB_PREFIX."c_country c ON (c.rowid = s.fk_pays)
331 WHERE f.fk_statut > 0
332 AND l.product_type = ".($exporttype == "des" ? 1 : 0)."
333 AND f.entity = ".((int) $conf->entity)."
334 AND (s.fk_pays <> ".((int) $mysoc->country_id)." OR s.fk_pays IS NULL)
335 AND f.datef BETWEEN '".$this->db->escape($period_reference)."-01' AND '".$this->db->escape($period_reference)."-".date('t')."'";
336
337 return $sql;
338 }
339
349 public function addItemXMl(&$declaration, &$res, $i, $code_douane_spe = '')
350 {
351 $item = $declaration->addChild('Item');
352 $item->addChild('itemNumber', $i);
353 $cn8 = $item->addChild('CN8');
354 if (empty($code_douane_spe)) {
355 $code_douane = $res->customcode;
356 } else {
357 $code_douane = $code_douane_spe;
358 }
359 $cn8->addChild('CN8Code', $code_douane);
360 $item->addChild('MSConsDestCode', $res->code); // code iso pays client
361 $item->addChild('countryOfOriginCode', substr($res->zip, 0, 2)); // code iso pays d'origine
362 $item->addChild('netMass', round($res->weight * $res->qty)); // Poids du produit
363 $item->addChild('quantityInSU', $res->qty); // Quantité de produit dans la ligne
364 $item->addChild('invoicedAmount', round($res->total_ht)); // Montant total ht de la facture (entier attendu)
365 // $item->addChild('invoicedNumber', $res->refinvoice); // Numéro facture
366 if (!empty($res->tva_intra)) {
367 $item->addChild('partnerId', $res->tva_intra);
368 }
369 $item->addChild('statisticalProcedureCode', '11');
370 $nature_of_transaction = $item->addChild('NatureOfTransaction');
371 $nature_of_transaction->addChild('natureOfTransactionACode', 1);
372 $nature_of_transaction->addChild('natureOfTransactionBCode', 1);
373 $item->addChild('modeOfTransportCode', $res->mode_transport);
374 $item->addChild('regionCode', substr($res->zip, 0, 2));
375 }
376
385 public function addItemXMlDes($declaration, &$res, $i)
386 {
387 $item = $declaration->addChild('ligne_des');
388 $item->addChild('numlin_des', $i);
389 $item->addChild('valeur', round($res->total_ht)); // Total amount excl. tax of the invoice (whole amount expected)
390 $item->addChild('partner_des', $res->tva_intra); // Represents the foreign customer's VAT number
391 }
392
403 public function addItemFraisDePort(&$declaration, &$TLinesFraisDePort, $type, &$categ_fraisdeport, $i)
404 {
405 global $conf;
406
407 if ($type == 'expedition') {
408 $table = 'facture';
409 $tabledet = 'facturedet';
410 $field_link = 'fk_facture';
411 $more_sql = 'f.ref';
412 } else { // Introduction
413 $table = 'facture_fourn';
414 $tabledet = 'facture_fourn_det';
415 $field_link = 'fk_facture_fourn';
416 $more_sql = 'f.ref_supplier';
417 }
418
419 foreach ($TLinesFraisDePort as $res) {
420 $sql = "SELECT p.customcode
421 FROM ".MAIN_DB_PREFIX.$tabledet." d
422 INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = d.".$this->db->escape($field_link).")
423 INNER JOIN ".MAIN_DB_PREFIX."product p ON (p.rowid = d.fk_product)
424 WHERE d.fk_product IS NOT NULL
425 AND f.entity = ".((int) $conf->entity)."
426 AND ".$more_sql." = '".$this->db->escape($res->refinvoice)."'
427 AND d.total_ht =
428 (
429 SELECT MAX(d.total_ht)
430 FROM ".MAIN_DB_PREFIX.$tabledet." d
431 INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = d.".$this->db->escape($field_link).")
432 WHERE d.fk_product IS NOT NULL
433 AND ".$more_sql." = '".$this->db->escape($res->refinvoice)."'
434 AND d.fk_product NOT IN
435 (
436 SELECT fk_product
437 FROM ".MAIN_DB_PREFIX."categorie_product
438 WHERE fk_categorie = ".((int) $categ_fraisdeport->id)."
439 )
440 )";
441
442 $resql = $this->db->query($sql);
443 $ress = $this->db->fetch_object($resql);
444
445 $this->addItemXMl($declaration, $res, $i, $ress->customcode);
446
447 $i++;
448 }
449 }
450
456 public function getNextDeclarationNumber()
457 {
458 $sql = "SELECT MAX(numero_declaration) as max_declaration_number";
459 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element;
460 $sql .= " WHERE exporttype = '".$this->db->escape($this->exporttype)."'";
461 $resql = $this->db->query($sql);
462 if ($resql) {
463 $res = $this->db->fetch_object($resql);
464 }
465
466 return ($res->max_declaration_number + 1);
467 }
468
475 public static function getDeclarationNumber($number)
476 {
477 return str_pad($number, 6, 0, STR_PAD_LEFT);
478 }
479
486 public function generateXMLFile($content_xml)
487 {
488 $name = $this->period.'.xml';
489
490 // TODO Must be stored into a dolibarr temp directory
491 $fname = sys_get_temp_dir().'/'.$name;
492
493 $f = fopen($fname, 'w+');
494 fwrite($f, $content_xml);
495 fclose($f);
496
497 header('Content-Description: File Transfer');
498 header('Content-Type: application/xml');
499 header('Content-Disposition: attachment; filename="'.$name.'"');
500 header('Expires: 0');
501 header('Cache-Control: must-revalidate');
502 header('Pragma: public');
503 header('Content-Length: '.filesize($fname));
504
505 readfile($fname);
506 exit;
507 }
508}
Class to manage categories.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Class to manage Dolibarr database access.
Class to manage intracomm report.
static getDeclarationNumber($number)
Verify declaration number.
addItemsFact(&$declaration, $type, $period_reference, $exporttype='deb')
Add line from invoice.
fetch($id)
Function fetch.
const TYPE_DEB
DEB - Product.
const TYPE_DES
DES - Service.
__construct(DoliDB $db)
Constructor.
addItemXMl(&$declaration, &$res, $i, $code_douane_spe='')
Add item for DEB.
getXML($mode='O', $type='introduction', $period_reference='')
Generate XML file.
addItemXMlDes($declaration, &$res, $i)
Add item for DES.
addItemFraisDePort(&$declaration, &$TLinesFraisDePort, $type, &$categ_fraisdeport, $i)
This function adds an item by retrieving the customs code of the product with the highest amount in t...
getNextDeclarationNumber()
Return next reference of declaration not already used (or last reference)
getSQLFactLines($type, $period_reference, $exporttype='deb')
Add invoice line.
generateXMLFile($content_xml)
Generate XML file.
create($user, $notrigger=0)
Function create.
getXMLDes($period_year, $period_month, $type_declaration='expedition')
Generate XMLDes file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.