dolibarr  19.0.0-dev
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 
27 require_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 $type_declaration; // deb or des
71 
72 
76  const TYPE_DEB = 0;
77 
81  const TYPE_DES = 1;
82 
83  public static $type = array(
84  'introduction'=>'Introduction',
85  'expedition'=>'Expédition'
86  );
87 
88 
94  public function __construct(DoliDB $db)
95  {
96  $this->db = $db;
97  $this->exporttype = 'deb';
98  }
99 
107  public function create($user, $notrigger = 0)
108  {
109  return 1;
110  }
111 
118  public function fetch($id)
119  {
120  return 1;
121  }
122 
131  public function delete($id, $user, $notrigger = 0)
132  {
133  return 1;
134  }
135 
144  public function getXML($mode = 'O', $type = 'introduction', $period_reference = '')
145  {
146  global $conf, $mysoc;
147 
148  /**************Construction de quelques variables********************/
149  $party_id = substr(strtr($mysoc->tva_intra, array(' '=>'')), 0, 4).$mysoc->idprof2;
150  $declarant = substr($mysoc->managers, 0, 14);
151  $id_declaration = self::getDeclarationNumber($this->numero_declaration);
152  /********************************************************************/
153 
154  /**************Construction du fichier XML***************************/
155  $e = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" standalone="yes"?><INSTAT></INSTAT>');
156 
157  $enveloppe = $e->addChild('Envelope');
158  $enveloppe->addChild('envelopeId', $conf->global->INTRACOMMREPORT_NUM_AGREMENT);
159  $date_time = $enveloppe->addChild('DateTime');
160  $date_time->addChild('date', date('Y-m-d'));
161  $date_time->addChild('time', date('H:i:s'));
162  $party = $enveloppe->addChild('Party');
163  $party->addAttribute('partyType', $conf->global->INTRACOMMREPORT_TYPE_ACTEUR);
164  $party->addAttribute('partyRole', $conf->global->INTRACOMMREPORT_ROLE_ACTEUR);
165  $party->addChild('partyId', $party_id);
166  $party->addChild('partyName', $declarant);
167  $enveloppe->addChild('softwareUsed', 'Dolibarr');
168  $declaration = $enveloppe->addChild('Declaration');
169  $declaration->addChild('declarationId', $id_declaration);
170  $declaration->addChild('referencePeriod', $period_reference);
171  if ($conf->global->INTRACOMMREPORT_TYPE_ACTEUR === 'PSI') {
172  $psiId = $party_id;
173  } else {
174  $psiId = 'NA';
175  }
176  $declaration->addChild('PSIId', $psiId);
177  $function = $declaration->addChild('Function');
178  $functionCode = $function->addChild('functionCode', $mode);
179  $declaration->addChild('declarationTypeCode', getDolGlobalString('INTRACOMMREPORT_NIV_OBLIGATION_'.strtoupper($type)));
180  $declaration->addChild('flowCode', ($type == 'introduction' ? 'A' : 'D'));
181  $declaration->addChild('currencyCode', $conf->global->MAIN_MONNAIE);
182  /********************************************************************/
183 
184  /**************Ajout des lignes de factures**************************/
185  $res = $this->addItemsFact($declaration, $type, $period_reference);
186  /********************************************************************/
187 
188  $this->errors = array_unique($this->errors);
189 
190  if (!empty($res)) {
191  return $e->asXML();
192  } else {
193  return 0;
194  }
195  }
196 
205  public function getXMLDes($period_year, $period_month, $type_declaration = 'expedition')
206  {
207  global $mysoc;
208 
209  $e = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" ?><fichier_des></fichier_des>');
210 
211  $declaration_des = $e->addChild('declaration_des');
212  $declaration_des->addChild('num_des', self::getDeclarationNumber($this->numero_declaration));
213  $declaration_des->addChild('num_tvaFr', $mysoc->tva_intra); // /^FR[a-Z0-9]{2}[0-9]{9}$/ // Doit faire 13 caractères
214  $declaration_des->addChild('mois_des', $period_month);
215  $declaration_des->addChild('an_des', $period_year);
216 
217  /**************Ajout des lignes de factures**************************/
218  $res = $this->addItemsFact($declaration_des, $type_declaration, $period_year.'-'.$period_month, 'des');
219  /********************************************************************/
220 
221  $this->errors = array_unique($this->errors);
222 
223  if (!empty($res)) {
224  return $e->asXML();
225  } else {
226  return 0;
227  }
228  }
229 
239  public function addItemsFact(&$declaration, $type, $period_reference, $exporttype = 'deb')
240  {
241  global $conf;
242 
243  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
244 
245  $sql = $this->getSQLFactLines($type, $period_reference, $exporttype);
246 
247  $resql = $this->db->query($sql);
248 
249  if ($resql) {
250  $i = 1;
251 
252  if ($this->db->num_rows($resql) <= 0) {
253  $this->errors[] = 'No data for this period';
254  return 0;
255  }
256 
257  if ($exporttype == 'deb' && $conf->global->INTRACOMMREPORT_CATEG_FRAISDEPORT > 0) {
258  $categ_fraisdeport = new Categorie($this->db);
259  $categ_fraisdeport->fetch($conf->global->INTRACOMMREPORT_CATEG_FRAISDEPORT);
260  $TLinesFraisDePort = array();
261  }
262 
263  while ($res = $this->db->fetch_object($resql)) {
264  if ($exporttype == 'des') {
265  $this->addItemXMlDes($declaration, $res, $i);
266  } else {
267  if (empty($res->fk_pays)) {
268  // We don't stop the loop because we want to know all the third parties who don't have an informed country
269  $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>';
270  } else {
271  if ($conf->global->INTRACOMMREPORT_CATEG_FRAISDEPORT > 0 && $categ_fraisdeport->containsObject('product', $res->id_prod)) {
272  $TLinesFraisDePort[] = $res;
273  } else {
274  $this->addItemXMl($declaration, $res, $i, '');
275  }
276  }
277  }
278 
279  $i++;
280  }
281 
282  if (!empty($TLinesFraisDePort)) {
283  $this->addItemFraisDePort($declaration, $TLinesFraisDePort, $type, $categ_fraisdeport, $i);
284  }
285 
286  if (count($this->errors) > 0) {
287  return 0;
288  }
289  }
290 
291  return 1;
292  }
293 
302  public function getSQLFactLines($type, $period_reference, $exporttype = 'deb')
303  {
304  global $mysoc, $conf;
305 
306  if ($type == 'expedition' || $exporttype == 'des') {
307  $sql = "SELECT f.ref as refinvoice, f.total_ht";
308  $table = 'facture';
309  $table_extraf = 'facture_extrafields';
310  $tabledet = 'facturedet';
311  $field_link = 'fk_facture';
312  } else { // Introduction
313  $sql = "SELECT f.ref_supplier as refinvoice, f.total_ht";
314  $table = 'facture_fourn';
315  $table_extraf = 'facture_fourn_extrafields';
316  $tabledet = 'facture_fourn_det';
317  $field_link = 'fk_facture_fourn';
318  }
319  $sql .= ", l.fk_product, l.qty
320  , p.weight, p.rowid as id_prod, p.customcode
321  , s.rowid as id_client, s.nom, s.zip, s.fk_pays, s.tva_intra
322  , c.code
323  , ext.mode_transport
324  FROM ".MAIN_DB_PREFIX.$tabledet." l
325  INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = l.".$this->db->escape($field_link).")
326  LEFT JOIN ".MAIN_DB_PREFIX.$table_extraf." ext ON (ext.fk_object = f.rowid)
327  INNER JOIN ".MAIN_DB_PREFIX."product p ON (p.rowid = l.fk_product)
328  INNER JOIN ".MAIN_DB_PREFIX."societe s ON (s.rowid = f.fk_soc)
329  LEFT JOIN ".MAIN_DB_PREFIX."c_country c ON (c.rowid = s.fk_pays)
330  WHERE f.fk_statut > 0
331  AND l.product_type = ".($exporttype == "des" ? 1 : 0)."
332  AND f.entity = ".((int) $conf->entity)."
333  AND (s.fk_pays <> ".((int) $mysoc->country_id)." OR s.fk_pays IS NULL)
334  AND f.datef BETWEEN '".$this->db->escape($period_reference)."-01' AND '".$this->db->escape($period_reference)."-".date('t')."'";
335 
336  return $sql;
337  }
338 
348  public function addItemXMl(&$declaration, &$res, $i, $code_douane_spe = '')
349  {
350  $item = $declaration->addChild('Item');
351  $item->addChild('itemNumber', $i);
352  $cn8 = $item->addChild('CN8');
353  if (empty($code_douane_spe)) {
354  $code_douane = $res->customcode;
355  } else {
356  $code_douane = $code_douane_spe;
357  }
358  $cn8->addChild('CN8Code', $code_douane);
359  $item->addChild('MSConsDestCode', $res->code); // code iso pays client
360  $item->addChild('countryOfOriginCode', substr($res->zip, 0, 2)); // code iso pays d'origine
361  $item->addChild('netMass', round($res->weight * $res->qty)); // Poids du produit
362  $item->addChild('quantityInSU', $res->qty); // Quantité de produit dans la ligne
363  $item->addChild('invoicedAmount', round($res->total_ht)); // Montant total ht de la facture (entier attendu)
364  // $item->addChild('invoicedNumber', $res->refinvoice); // Numéro facture
365  if (!empty($res->tva_intra)) {
366  $item->addChild('partnerId', $res->tva_intra);
367  }
368  $item->addChild('statisticalProcedureCode', '11');
369  $nature_of_transaction = $item->addChild('NatureOfTransaction');
370  $nature_of_transaction->addChild('natureOfTransactionACode', 1);
371  $nature_of_transaction->addChild('natureOfTransactionBCode', 1);
372  $item->addChild('modeOfTransportCode', $res->mode_transport);
373  $item->addChild('regionCode', substr($res->zip, 0, 2));
374  }
375 
384  public function addItemXMlDes($declaration, &$res, $i)
385  {
386  $item = $declaration->addChild('ligne_des');
387  $item->addChild('numlin_des', $i);
388  $item->addChild('valeur', round($res->total_ht)); // Total amount excl. tax of the invoice (whole amount expected)
389  $item->addChild('partner_des', $res->tva_intra); // Represents the foreign customer's VAT number
390  }
391 
402  public function addItemFraisDePort(&$declaration, &$TLinesFraisDePort, $type, &$categ_fraisdeport, $i)
403  {
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 FROM ".MAIN_DB_PREFIX.$this->table_element;
459  $sql .= " WHERE exporttype = '".$this->db->escape($this->exporttype)."'";
460  $resql = $this->db->query($sql);
461  if ($resql) {
462  $res = $this->db->fetch_object($resql);
463  }
464 
465  return ($res->max_declaration_number + 1);
466  }
467 
474  public static function getDeclarationNumber($number)
475  {
476  return str_pad($number, 6, 0, STR_PAD_LEFT);
477  }
478 
484  public function generateXMLFile()
485  {
486  $name = $this->periode.'.xml';
487  $fname = sys_get_temp_dir().'/'.$name;
488  $f = fopen($fname, 'w+');
489  fwrite($f, $this->content_xml);
490  fclose($f);
491 
492  header('Content-Description: File Transfer');
493  header('Content-Type: application/xml');
494  header('Content-Disposition: attachment; filename="'.$name.'"');
495  header('Expires: 0');
496  header('Cache-Control: must-revalidate');
497  header('Pragma: public');
498  header('Content-Length: '.filesize($fname));
499  readfile($fname);
500  exit;
501  }
502 }
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.
generateXMLFile()
Generate XML file.
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.
create($user, $notrigger=0)
Function create.
getXMLDes($period_year, $period_month, $type_declaration='expedition')
Generate XMLDes file.
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.