dolibarr  16.0.5
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 <http://www.gnu.org/licenses/>.
18  */
19 
25 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
26 
27 
32 {
36  public $element = 'intracommreport';
37 
41  public $table_element = 'intracommreport';
42 
46  public $fk_element = 'fk_intracommreport';
47 
51  public $declaration_number;
52 
57  public $ismultientitymanaged = 1;
58 
62  const TYPE_DEB = 0;
63 
67  const TYPE_DES = 1;
68 
69  public static $type = array(
70  'introduction'=>'Introduction',
71  'expedition'=>'Expédition'
72  );
73 
79  public function __construct(DoliDB $db)
80  {
81  $this->db = $db;
82  $this->exporttype = 'deb';
83  }
84 
91  public function create($user, $notrigger = 0)
92  {
93  return 1;
94  }
95 
101  public function fetch($id)
102  {
103  return 1;
104  }
105 
113  public function delete($id, $user, $notrigger = 0)
114  {
115  return 1;
116  }
117 
126  public function getXML($mode = 'O', $type = 'introduction', $period_reference = '')
127  {
128  global $conf, $mysoc;
129 
130  /**************Construction de quelques variables********************/
131  $party_id = substr(strtr($mysoc->tva_intra, array(' '=>'')), 0, 4).$mysoc->idprof2;
132  $declarant = substr($mysoc->managers, 0, 14);
133  $id_declaration = self::getDeclarationNumber($this->numero_declaration);
134  /********************************************************************/
135 
136  /**************Construction du fichier XML***************************/
137  $e = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" standalone="yes"?><INSTAT></INSTAT>');
138 
139  $enveloppe = $e->addChild('Envelope');
140  $enveloppe->addChild('envelopeId', $conf->global->INTRACOMMREPORT_NUM_AGREMENT);
141  $date_time = $enveloppe->addChild('DateTime');
142  $date_time->addChild('date', date('Y-m-d'));
143  $date_time->addChild('time', date('H:i:s'));
144  $party = $enveloppe->addChild('Party');
145  $party->addAttribute('partyType', $conf->global->INTRACOMMREPORT_TYPE_ACTEUR);
146  $party->addAttribute('partyRole', $conf->global->INTRACOMMREPORT_ROLE_ACTEUR);
147  $party->addChild('partyId', $party_id);
148  $party->addChild('partyName', $declarant);
149  $enveloppe->addChild('softwareUsed', 'Dolibarr');
150  $declaration = $enveloppe->addChild('Declaration');
151  $declaration->addChild('declarationId', $id_declaration);
152  $declaration->addChild('referencePeriod', $period_reference);
153  if ($conf->global->INTRACOMMREPORT_TYPE_ACTEUR === 'PSI') {
154  $psiId = $party_id;
155  } else {
156  $psiId = 'NA';
157  }
158  $declaration->addChild('PSIId', $psiId);
159  $function = $declaration->addChild('Function');
160  $functionCode = $function->addChild('functionCode', $mode);
161  $declaration->addChild('declarationTypeCode', $conf->global->{'INTRACOMMREPORT_NIV_OBLIGATION_'.strtoupper($type)});
162  $declaration->addChild('flowCode', ($type == 'introduction' ? 'A' : 'D'));
163  $declaration->addChild('currencyCode', $conf->global->MAIN_MONNAIE);
164  /********************************************************************/
165 
166  /**************Ajout des lignes de factures**************************/
167  $res = $this->addItemsFact($declaration, $type, $period_reference);
168  /********************************************************************/
169 
170  $this->errors = array_unique($this->errors);
171 
172  if (!empty($res)) {
173  return $e->asXML();
174  } else {
175  return 0;
176  }
177  }
178 
187  public function getXMLDes($period_year, $period_month, $type_declaration = 'expedition')
188  {
189  global $mysoc;
190 
191  $e = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" ?><fichier_des></fichier_des>');
192 
193  $declaration_des = $e->addChild('declaration_des');
194  $declaration_des->addChild('num_des', self::getDeclarationNumber($this->numero_declaration));
195  $declaration_des->addChild('num_tvaFr', $mysoc->tva_intra); // /^FR[a-Z0-9]{2}[0-9]{9}$/ // Doit faire 13 caractères
196  $declaration_des->addChild('mois_des', $period_month);
197  $declaration_des->addChild('an_des', $period_year);
198 
199  /**************Ajout des lignes de factures**************************/
200  $res = $this->addItemsFact($declaration_des, $type_declaration, $period_year.'-'.$period_month, 'des');
201  /********************************************************************/
202 
203  $this->errors = array_unique($this->errors);
204 
205  if (!empty($res)) {
206  return $e->asXML();
207  } else {
208  return 0;
209  }
210  }
211 
221  public function addItemsFact(&$declaration, $type, $period_reference, $exporttype = 'deb')
222  {
223  global $conf;
224 
225  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
226 
227  $sql = $this->getSQLFactLines($type, $period_reference, $exporttype);
228 
229  $resql = $this->db->query($sql);
230 
231  if ($resql) {
232  $i = 1;
233 
234  if ($this->db->num_rows($resql) <= 0) {
235  $this->errors[] = 'No data for this period';
236  return 0;
237  }
238 
239  if ($exporttype == 'deb' && $conf->global->INTRACOMMREPORT_CATEG_FRAISDEPORT > 0) {
240  $categ_fraisdeport = new Categorie($this->db);
241  $categ_fraisdeport->fetch($conf->global->INTRACOMMREPORT_CATEG_FRAISDEPORT);
242  $TLinesFraisDePort = array();
243  }
244 
245  while ($res = $this->db->fetch_object($resql)) {
246  if ($exporttype == 'des') {
247  $this->addItemXMlDes($declaration, $res, $i);
248  } else {
249  if (empty($res->fk_pays)) {
250  // We don't stop the loop because we want to know all the third parties who don't have an informed country
251  $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>';
252  } else {
253  if ($conf->global->INTRACOMMREPORT_CATEG_FRAISDEPORT > 0 && $categ_fraisdeport->containsObject('product', $res->id_prod)) {
254  $TLinesFraisDePort[] = $res;
255  } else {
256  $this->addItemXMl($declaration, $res, $i, '');
257  }
258  }
259  }
260 
261  $i++;
262  }
263 
264  if (!empty($TLinesFraisDePort)) {
265  $this->addItemFraisDePort($declaration, $TLinesFraisDePort, $type, $categ_fraisdeport, $i);
266  }
267 
268  if (count($this->errors) > 0) {
269  return 0;
270  }
271  }
272 
273  return 1;
274  }
275 
284  public function getSQLFactLines($type, $period_reference, $exporttype = 'deb')
285  {
286  global $mysoc, $conf;
287 
288  if ($type == 'expedition' || $exporttype == 'des') {
289  $sql = "SELECT f.ref as refinvoice, f.total_ht";
290  $table = 'facture';
291  $table_extraf = 'facture_extrafields';
292  $tabledet = 'facturedet';
293  $field_link = 'fk_facture';
294  } else { // Introduction
295  $sql = "SELECT f.ref_supplier as refinvoice, f.total_ht";
296  $table = 'facture_fourn';
297  $table_extraf = 'facture_fourn_extrafields';
298  $tabledet = 'facture_fourn_det';
299  $field_link = 'fk_facture_fourn';
300  }
301  $sql .= ", l.fk_product, l.qty
302  , p.weight, p.rowid as id_prod, p.customcode
303  , s.rowid as id_client, s.nom, s.zip, s.fk_pays, s.tva_intra
304  , c.code
305  , ext.mode_transport
306  FROM ".MAIN_DB_PREFIX.$tabledet." l
307  INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = l.".$this->db->escape($field_link).")
308  LEFT JOIN ".MAIN_DB_PREFIX.$table_extraf." ext ON (ext.fk_object = f.rowid)
309  INNER JOIN ".MAIN_DB_PREFIX."product p ON (p.rowid = l.fk_product)
310  INNER JOIN ".MAIN_DB_PREFIX."societe s ON (s.rowid = f.fk_soc)
311  LEFT JOIN ".MAIN_DB_PREFIX."c_country c ON (c.rowid = s.fk_pays)
312  WHERE f.fk_statut > 0
313  AND l.product_type = ".($exporttype == "des" ? 1 : 0)."
314  AND f.entity = ".((int) $conf->entity)."
315  AND (s.fk_pays <> ".((int) $mysoc->country_id)." OR s.fk_pays IS NULL)
316  AND f.datef BETWEEN '".$this->db->escape($period_reference)."-01' AND '".$this->db->escape($period_reference)."-".date('t')."'";
317 
318  return $sql;
319  }
320 
330  public function addItemXMl(&$declaration, &$res, $i, $code_douane_spe = '')
331  {
332  $item = $declaration->addChild('Item');
333  $item->addChild('itemNumber', $i);
334  $cn8 = $item->addChild('CN8');
335  if (empty($code_douane_spe)) {
336  $code_douane = $res->customcode;
337  } else {
338  $code_douane = $code_douane_spe;
339  }
340  $cn8->addChild('CN8Code', $code_douane);
341  $item->addChild('MSConsDestCode', $res->code); // code iso pays client
342  $item->addChild('countryOfOriginCode', substr($res->zip, 0, 2)); // code iso pays d'origine
343  $item->addChild('netMass', round($res->weight * $res->qty)); // Poids du produit
344  $item->addChild('quantityInSU', $res->qty); // Quantité de produit dans la ligne
345  $item->addChild('invoicedAmount', round($res->total_ht)); // Montant total ht de la facture (entier attendu)
346  // $item->addChild('invoicedNumber', $res->refinvoice); // Numéro facture
347  if (!empty($res->tva_intra)) {
348  $item->addChild('partnerId', $res->tva_intra);
349  }
350  $item->addChild('statisticalProcedureCode', '11');
351  $nature_of_transaction = $item->addChild('NatureOfTransaction');
352  $nature_of_transaction->addChild('natureOfTransactionACode', 1);
353  $nature_of_transaction->addChild('natureOfTransactionBCode', 1);
354  $item->addChild('modeOfTransportCode', $res->mode_transport);
355  $item->addChild('regionCode', substr($res->zip, 0, 2));
356  }
357 
366  public function addItemXMlDes($declaration, &$res, $i)
367  {
368  $item = $declaration->addChild('ligne_des');
369  $item->addChild('numlin_des', $i);
370  $item->addChild('valeur', round($res->total_ht)); // Total amount excl. tax of the invoice (whole amount expected)
371  $item->addChild('partner_des', $res->tva_intra); // Represents the foreign customer's VAT number
372  }
373 
384  public function addItemFraisDePort(&$declaration, &$TLinesFraisDePort, $type, &$categ_fraisdeport, $i)
385  {
386 
387  global $conf;
388 
389  if ($type == 'expedition') {
390  $table = 'facture';
391  $tabledet = 'facturedet';
392  $field_link = 'fk_facture';
393  $more_sql = 'f.ref';
394  } else { // Introduction
395  $table = 'facture_fourn';
396  $tabledet = 'facture_fourn_det';
397  $field_link = 'fk_facture_fourn';
398  $more_sql = 'f.ref_supplier';
399  }
400 
401  foreach ($TLinesFraisDePort as $res) {
402  $sql = "SELECT p.customcode
403  FROM ".MAIN_DB_PREFIX.$tabledet." d
404  INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = d.".$this->db->escape($field_link).")
405  INNER JOIN ".MAIN_DB_PREFIX."product p ON (p.rowid = d.fk_product)
406  WHERE d.fk_product IS NOT NULL
407  AND f.entity = ".((int) $conf->entity)."
408  AND ".$more_sql." = '".$this->db->escape($res->refinvoice)."'
409  AND d.total_ht =
410  (
411  SELECT MAX(d.total_ht)
412  FROM ".MAIN_DB_PREFIX.$tabledet." d
413  INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = d.".$this->db->escape($field_link).")
414  WHERE d.fk_product IS NOT NULL
415  AND ".$more_sql." = '".$this->db->escape($res->refinvoice)."'
416  AND d.fk_product NOT IN
417  (
418  SELECT fk_product
419  FROM ".MAIN_DB_PREFIX."categorie_product
420  WHERE fk_categorie = ".((int) $categ_fraisdeport->id)."
421  )
422  )";
423 
424  $resql = $this->db->query($sql);
425  $ress = $this->db->fetch_object($resql);
426 
427  $this->addItemXMl($declaration, $res, $i, $ress->customcode);
428 
429  $i++;
430  }
431  }
432 
438  public function getNextDeclarationNumber()
439  {
440  $sql = "SELECT MAX(numero_declaration) as max_declaration_number FROM ".MAIN_DB_PREFIX.$this->table_element;
441  $sql .= " WHERE exporttype = '".$this->db->escape($this->exporttype)."'";
442  $resql = $this->db->query($sql);
443  if ($resql) {
444  $res = $this->db->fetch_object($resql);
445  }
446 
447  return ($res->max_declaration_number + 1);
448  }
449 
456  public static function getDeclarationNumber($number)
457  {
458  return str_pad($number, 6, 0, STR_PAD_LEFT);
459  }
460 
466  public function generateXMLFile()
467  {
468  $name = $this->periode.'.xml';
469  $fname = sys_get_temp_dir().'/'.$name;
470  $f = fopen($fname, 'w+');
471  fwrite($f, $this->content_xml);
472  fclose($f);
473 
474  header('Content-Description: File Transfer');
475  header('Content-Type: application/xml');
476  header('Content-Disposition: attachment; filename="'.$name.'"');
477  header('Expires: 0');
478  header('Cache-Control: must-revalidate');
479  header('Pragma: public');
480  header('Content-Length: '.filesize($fname));
481  readfile($fname);
482  exit;
483  }
484 }
db
$conf db
API class for accounts.
Definition: inc.php:41
DoliDB
Class to manage Dolibarr database access.
Definition: DoliDB.class.php:30
IntracommReport\getXMLDes
getXMLDes($period_year, $period_month, $type_declaration='expedition')
Generate XMLDes file.
Definition: intracommreport.class.php:187
IntracommReport
Class to manage intracomm report.
Definition: intracommreport.class.php:31
IntracommReport\generateXMLFile
generateXMLFile()
Generate XML file.
Definition: intracommreport.class.php:466
IntracommReport\getDeclarationNumber
static getDeclarationNumber($number)
Verify declaration number.
Definition: intracommreport.class.php:456
IntracommReport\fetch
fetch($id)
Fonction fetch.
Definition: intracommreport.class.php:101
Categorie
Class to manage categories.
Definition: categorie.class.php:47
CommonObject
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Definition: commonobject.class.php:44
IntracommReport\getSQLFactLines
getSQLFactLines($type, $period_reference, $exporttype='deb')
Add invoice line.
Definition: intracommreport.class.php:284
IntracommReport\getXML
getXML($mode='O', $type='introduction', $period_reference='')
Generate XML file.
Definition: intracommreport.class.php:126
IntracommReport\__construct
__construct(DoliDB $db)
Constructor.
Definition: intracommreport.class.php:79
IntracommReport\getNextDeclarationNumber
getNextDeclarationNumber()
Return next reference of declaration not already used (or last reference)
Definition: intracommreport.class.php:438
IntracommReport\TYPE_DEB
const TYPE_DEB
DEB - Product.
Definition: intracommreport.class.php:62
IntracommReport\addItemXMlDes
addItemXMlDes($declaration, &$res, $i)
Add item for DES.
Definition: intracommreport.class.php:366
IntracommReport\addItemFraisDePort
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...
Definition: intracommreport.class.php:384
IntracommReport\create
create($user, $notrigger=0)
Fonction create.
Definition: intracommreport.class.php:91
IntracommReport\TYPE_DES
const TYPE_DES
DES - Service.
Definition: intracommreport.class.php:67
IntracommReport\addItemsFact
addItemsFact(&$declaration, $type, $period_reference, $exporttype='deb')
Add line from invoice.
Definition: intracommreport.class.php:221
$resql
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire)||(isModEnabled('supplier_invoice') && $user->rights->supplier_invoice->lire)) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:742
IntracommReport\addItemXMl
addItemXMl(&$declaration, &$res, $i, $code_douane_spe='')
Add item for DEB.
Definition: intracommreport.class.php:330