diff --git a/include/XMLDocument/Error_Message.php b/include/XMLDocument/Error_Message.php index d9ecb08a2..45e9487b7 100644 --- a/include/XMLDocument/Error_Message.php +++ b/include/XMLDocument/Error_Message.php @@ -85,7 +85,8 @@ class Error_Message , 'MY_STREET' => _("Adresse de la société") , 'MY_CITY' => _("Ville") , 'MY_TVA' => _("Numéro de TVA") - + // , 'SIREN'=> 'SIREN' + // , 'SIRET'=> 'SIRET' ); $this->a_message_customer = array( 'name' => _("Nom") diff --git a/include/XMLDocument/FacturX.php b/include/XMLDocument/FacturX.php index 48e68fa52..08ea2d52b 100644 --- a/include/XMLDocument/FacturX.php +++ b/include/XMLDocument/FacturX.php @@ -19,15 +19,25 @@ namespace Noalyss\XMLDocument; */ // Copyright Author Dany De Bontridder danydb@aevalys.eu 22/10/23 -use \Kinulab\Facturx\CrossIndustryInvoice as KINU_FX1; -use \Atgp\FacturX as FX_ATGP; +use horstoeko\zugferd\codelists\ZugferdCountryCodes; +use horstoeko\zugferd\codelists\ZugferdCurrencyCodes; +use horstoeko\zugferd\codelists\ZugferdElectronicAddressScheme; +use horstoeko\zugferd\codelists\ZugferdInvoiceType; +use horstoeko\zugferd\codelists\ZugferdReferenceCodeQualifiers; +use horstoeko\zugferd\codelists\ZugferdUnitCodes; +use horstoeko\zugferd\codelists\ZugferdVatCategoryCodes; +use horstoeko\zugferd\codelists\ZugferdVatTypeCodes; +use horstoeko\zugferd\ZugferdDocumentBuilder; +use horstoeko\zugferd\ZugferdProfiles; + /** * @file * @brief answer to an inplace object */ class FacturX extends XMLInvoice { - const EXTRA_PARAMETER = ["INVOICE_EMAIL_COMPANY" + const EXTRA_PARAMETER = [ + "INVOICE_EMAIL_COMPANY" , 'INVOICE_CONTACT_NAME' , 'COMPANY_LEGAL_ENTITY' , 'COMPANY_LEGAL_REGISTRATION' @@ -40,38 +50,54 @@ class FacturX extends XMLInvoice , 'MY_CITY' , 'MY_COUNTRY_CODE' , 'MY_TVA' - ,'SIREN' - ,'SIRET' + // ,'SIREN' + // ,'SIRET' ]; protected $pdf_filename; function build_data($jr_id): array { - $result = parent::build_data($jr_id); - - - $customer=new \Fiche($this->cn,$result['customer']['card_id']); - $result['customer']['siren']=$customer->get_attribute(ATTR_DEF_SIREN); - $result['customer']['siret']=$customer->get_attribute(ATTR_DEF_SIRET); - return $result; + $this->data=parent::build_data($jr_id); + return $this->data; } /** * @brief check that mandatory info are saved in the DB * @param $a_error (array) array of errors, empty if nothing found */ - function check_company_data(&$a_error) { - echo "not implemented"; - return true; + function check_company_data() + { + $a_error=array(); + $company = $this->load_noalyss_parameter(); + foreach (FacturX::EXTRA_PARAMETER as $item) { + if (!isset($company[$item]) || trim($company[$item]) == '') { + $a_error[]=$item; + } + } + return $a_error; } /** * @brief check that mandatory info are saved in the DB for customer * @param $customer_id (int) card of the customer FICHE.F_ID * @param $a_error (array) array of errors, empty if nothing found */ - function check_customer_data($customer_id,&$a_error){ - echo "not implemented"; - return true; + function check_customer_data($customer_id){ + $a_error=array(); + $a_needed=[ATTR_DEF_NAME=>'name' + ,ATTR_DEF_ADRESS=>'street' + ,ATTR_DEF_POSTCODE=>'postalzone' + ,ATTR_DEF_CITY=>'city' + ,ATTR_DEF_COUNTRY_CODE=>'country' + ,ATTR_DEF_NUMTVA=>'customer_id' + ,ATTR_DEF_PEPPOLID=>'endpoint_id' + ]; + foreach ($a_needed as $item=>$value) { + if ( $this->data['customer'][$value]=="") { + $a_error[]=$value; + } + } + + return $a_error; } /** @@ -83,53 +109,81 @@ class FacturX extends XMLInvoice function make_xml($jr_id) { $this->data = $this->build_data($jr_id); - $invoice= new KINU_FX1\CrossIndustryInvoice(KINU_FX1\CrossIndustryInvoice::PROFILE_BASIC_WL); - $invoice->setInvoiceNumber($this->data['id']); - $invoice->setInvoiceType(KINU_FX1\CrossIndustryInvoice::INVOICE_TYPE_COMMERCIAL_INVOICE); - $invoice->setIssueDate(\DateTime::createFromFormat( 'Y-m-d',$this->data['issue_date'])); - - if ( $this->data['due_date'] !="") { - $invoice->setDueDate(\DateTime::createFromFormat( 'Y-m-d',$this->data['due_date'])); - }else { - $due_date=\DateTime::createFromFormat( 'Y-m-d',$this->data['issue_date']); - $due_date->modify('+ 30 days'); - $invoice->setDueDate($due_date); - - } - $supplier=new KINU_FX1\LegalEntity(); $company = $this->load_noalyss_parameter(); - $supplier->setName($company['MY_NAME']); - $supplier->setSiren($company['SIREN']); - $supplier->setSiret($company['SIRET']); - //$supplier->setSiren('999999'); - $supplier->setVatIdentifier($company['MY_TVA']); - $supplier_addres=new KINU_FX1\Address(); - $supplier_addres->setCityName($company['MY_CITY']) - ->setCountryId($company['MY_COUNTRY_CODE']) - ->setCityName($company['MY_CITY']) - ->setLines($company['MY_STREET']); - $supplier->setAddress($supplier_addres); - $invoice->setPaymentInstruction(null); - $invoice->setPaymentMeansCode(0); - $invoice->setSeller($supplier); - $invoice->setBuyer(new KINU_FX1\LegalEntity); - $buyer=$invoice->getBuyer(); - $buyer->setName($this->data['customer']['name']); - $buyer->setSiren($this->data['customer']['siren']); - $buyer->setSiret($this->data['customer']['siret']); - $buyer->setVatIdentifier($this->data['customer']['customer_id']); - $buyer->setAddress(new KINU_FX1\Address()); - $address=$buyer->getAddress(); - $address->setLines($this->data['customer']['street']) - ->setCityName($this->data['customer']['city']) - ->setZipCode($this->data['customer']['postalzone']) - ->setCountryId($this->data['customer']['country']); + // var_dump($this->data); + $documentBuilder = ZugferdDocumentBuilder::createNew(ZugferdProfiles::PROFILE_XRECHNUNG_3); + $documentBuilder->setDocumentInformation( + $this->data['id'] + ,"380" + ,\DateTime::createFromFormat( 'Y-m-d',$this->data["issue_date"]) + , $this->data['currency'] + ); - $invoice->setCurrencyCode('EUR'); + $documentBuilder->addDocumentPaymentTerm( + sprintf("IBAN %s",$company['COMPANY_BANK_IBAN']) + ,\DateTime::createFromFormat( 'Y-m-d',$this->data["due_date"]) + , $this->data['info']['communication'] + ); + //------------------------------------------------ + // SELLER + //------------------------------------------------ + $documentBuilder->setDocumentSeller($company['MY_NAME'], ); + $documentBuilder->addDocumentSellerGlobalId($company['SIREN'], '0009'); + $documentBuilder->addDocumentSellerTaxNumber($company['MY_TVA']); + $documentBuilder->addDocumentSellerVATRegistrationNumber($company['MY_TVA']); + $documentBuilder->setDocumentSellerAddress( + $company['MY_STREET'] + , '', '' + , $company['MY_POSTCODE'] + , $company['MY_CITY'] + ,$company['MY_COUNTRY_CODE']); + + $documentBuilder->setDocumentSellerCommunication(ZugferdElectronicAddressScheme::UNECE3155_EM + , $company["INVOICE_EMAIL_COMPANY"]); + + //------------------------------------------------ + // BUYER + //------------------------------------------------ + + $documentBuilder->setDocumentBuyer($this->data['customer']['name'], $this->data['customer']['customer_id']); + $documentBuilder->setDocumentBuyerAddress( + $this->data['customer']['street'] + , '' + , '' + , $this->data['customer']['postalzone'] + , $this->data['customer']['city'] + , $this->data['customer']['country'] + ); +// $documentBuilder->setDocumentBuyerContact('H. Meier', 'Einkauf', '+49-333-4444444', '+49-333-5555555', 'hm@kunde.de'); +// $documentBuilder->setDocumentBuyerCommunication(ZugferdElectronicAddressScheme::UNECE3155_EM, 'purchase@kunde.de'); + + $documentBuilder->setDocumentBuyerOrderReferencedDocument($this->data['info']['order']); + + //------------------------------------------------ + // Item & total + //------------------------------------------------ + $base=0;$vat=0; $nb=count($this->data['operation']); - ///@note : Pour l'autoliquidation le total TVA = 0 + for ($i=0;$i < $nb;$i++) { + $documentBuilder->addNewPosition($i+1); + $documentBuilder->setDocumentPositionProductDetails($this->data['operation'][$i]['qcode'] + ,$this->data['operation'][$i]['name'] + ,$this->data['operation'][$i]['description'] + ); + $documentBuilder->setDocumentPositionNetPrice($this->data['operation'][$i]['price']); + $documentBuilder->setDocumentPositionQuantity($this->data['operation'][$i]['quantity'] + ,$this->data['operation'][$i]['code_quantity'] + ); + $documentBuilder->addDocumentPositionTax( + $this->data['operation'][$i]['vat_code'] + , ZugferdVatTypeCodes::VALUE_ADDED_TAX + , bcmul($this->data['operation'][$i]['vat_rate'],100,2) + ); + $documentBuilder->setDocumentPositionLineSummation($this->data['operation'][$i]['price']); + + $base=bcadd($base,$this->data['operation'][$i]['price'],2); $vat=bcadd($vat,$this->data['operation'][$i]['vat'],2); $vat=bcsub($vat,$this->data['operation'][$i]['vat_reversed'],2); @@ -140,12 +194,40 @@ class FacturX extends XMLInvoice * il faut alors un "reste" à payer. * Pas de détail par articles ? */ - $invoice->setTaxBasisTotalAmount($base); - $invoice->setTaxTotalAmount($vat); - $invoice->setGrandTotalAmount($tt); - $invoice->setDuePayableAmount($tt); - $xml = KINU_FX1\XmlWriter::write($invoice); - return $xml; + ///@TODO DNY : ajouter les TVA par types ( addDocumentTax) + /// ainsi que la Somme des totaux (setDocumentSummation) + $subTotal=$this->data['subTotalVAT']; + $nb_sub=count($subTotal); + for ($i=0;$i<$nb_sub;$i++) + { + $documentBuilder->addDocumentTax( + $subTotal[$i]["vat_code"] + , ZugferdVatTypeCodes::VALUE_ADDED_TAX + ,sprintf("%.2f",$subTotal[$i]['amount']) + , sprintf("%.2f",$subTotal[$i]['vat']) + , sprintf("%.2f",$subTotal[$i]['percent']) + ); + } + + $documentBuilder->setDocumentSummation( + sprintf("%.2f",$this->data['TaxInclusiveAmount']) + , sprintf("%.2f",$this->data['PayableAmount']) + , sprintf("%.2f",$this->data['TaxExclusiveAmount']) + , 0.0 + , 0.0 + , sprintf("%.2f",$this->data['LineExtensionAmount']) + , sprintf("%.2f",(bcsub($this->data['TaxInclusiveAmount'], + $this->data['TaxExclusiveAmount'], + 2) + ) + ) + , 0 + ); + + + return $documentBuilder; + + } /** * @brief create the invoice in the right format @@ -153,10 +235,14 @@ class FacturX extends XMLInvoice * @return string PDF Invoice including the XML */ function create_invoice($operation_id) { - $xml = $this->make_xml($operation_id); - $facturx = new FX_ATGP\Facturx(); - $invoice=$facturx->generateFacturxFromFiles($this->pdf_filename, $xml); - return $invoice; + $documentBuilder= $this->make_xml($operation_id); + + $invoice = \horstoeko\zugferd\ZugferdDocumentPdfBuilder::fromPdfFile($documentBuilder, $this->pdf_filename); + $invoice->generateDocument(); + $invoice->saveDocument($this->pdf_filename."-new.pdf"); + return $invoice->downloadString(); } + + } \ No newline at end of file diff --git a/include/XMLDocument/InvoiceUBL21.php b/include/XMLDocument/InvoiceUBL21.php index 009d2b210..951d84d93 100644 --- a/include/XMLDocument/InvoiceUBL21.php +++ b/include/XMLDocument/InvoiceUBL21.php @@ -70,40 +70,6 @@ class InvoiceUBL21 extends XMLInvoice { include NOALYSS_TEMPLATE."/invoiceUBL21-display_error.php"; } - /** - * @brief check that all the data are correct - * @returns null : no errors, string separated with comma of error code - * @see get_message_error - * @see InvoiceUBL21::get_message_error() - */ - function verify() - { - - // verify all VAT - ///@var $a_error : array of error_code see check_company_error - $a_error = array(); - $a_error['general'] = parent::verify(); - $a_error['operation']=[]; - - // verify that all needed data in PARAMETER are valid - $a_error['company'] = $this->check_company_data(); - $a_error['customer'] = $this->check_customer_data($this->data['customer']['card_id']); - - return $a_error; - } - /** - * @brief set the PDF - * @param $pdf_filename (string) full path to the PDF - * @return $this - * @throws \Exception if the filename doesn't exist - */ - public function set_pdf_filename($pdf_filename) { - if ( !file_exists($pdf_filename)) { - throw new \Exception("AD65 $pdf_filename doesn't not exist"); - } - $this->pdf_filename = $pdf_filename; - return $this; - } /** * @brief check that mandatory info are saved in the DB for company (seller) @@ -145,31 +111,7 @@ class InvoiceUBL21 extends XMLInvoice { return $a_error; } - /** - * @brief check that the VAT is using a PEPPOL Code - */ - function check_VAT() - { - $a_error=array(); - $nb_operation=count($this->data['operation']); - for ($i=0;$i <$nb_operation;$i++) - { - if ( $this->data['operation'][$i]['vat_code'] == "" ) { - $card=new \Fiche( - $this->cn - ,$this->data['operation'][$i]['card_id'] - ); - $tva= \Acc_Tva::build($this->cn, $this->data['operation'][$i]['vat_id']); - $a_error[]=sprintf(_("%s : %s code TVA pour PEPPOL non configuré code TVA [ %s %s ]") - , $i - , $card->get_quick_code() - ,$tva->tva_id - ,$tva->tva_code - ); - } - } - return $a_error; - } + /** * @brief transform an operation ($jr_id) into an array, which contains * needed information for making an e-invoice @@ -178,60 +120,11 @@ class InvoiceUBL21 extends XMLInvoice { * @param type $jr_id * @see XMLInvoice::build_data */ - function build_data($jr_id): array { - $result = parent::build_data($jr_id); - /** - * Compute totals VAT and AMOUNT - */ - $nb_operation = count($result['operation']); + function build_data($jr_id): array + { - /// block cac:LegalMonetaryTotal - $result['LineExtensionAmount']=0; - $result['TaxExclusiveAmount']=0; - $result['TaxInclusiveAmount']=0; - $result['PayableAmount']=0; - - // block cac:TaxTotal - $result['TaxableAmount']=0; - $result['TaxAmount']=0; - - // array for TaxSubtotal - $VAT_SubTotal=array(); - $idx_subtotal=0; - bcscale(2); - // for each operation - $VAT_SubTotal=array(); - for ($i=0;$i < $nb_operation;$i++) { - $acc_tva=\Acc_TVA::build($this->cn,$result['operation'][$i]['vat_id'] ); - $percent = bcmul($acc_tva->tva_rate,100,2); - // subtotal for VAT - $n = find_idx($VAT_SubTotal,'percent',$percent); - if ($n == -1 ) { - $n=$idx_subtotal; - $VAT_SubTotal[$idx_subtotal]=array(); - $VAT_SubTotal[$idx_subtotal]['percent']=$percent; - $VAT_SubTotal[$idx_subtotal]['amount']=$VAT_SubTotal[$idx_subtotal]['vat']=0; - $idx_subtotal++; - } - /** - * @todo Pour les intracomm , quel taux utilisé ? 0 ou 21% - */ - $VAT_SubTotal[$n]['amount']=bcadd($VAT_SubTotal[$n]['amount'],$result['operation'][$i]['price']); - $VAT_SubTotal[$n]['vat']=bcadd($VAT_SubTotal[$n]['vat'],$result['operation'][$i]['vat']); - $VAT_SubTotal[$n]['vat']=bcsub($VAT_SubTotal[$n]['vat'],$result['operation'][$i]['vat_reversed']); - $result['TaxableAmount']=bcadd( $result['TaxableAmount'],$result['operation'][$i]['price']); - $result['TaxAmount']=bcadd( $result['TaxAmount'],$result['operation'][$i]['vat']); - $result['TaxAmount']=bcsub( $result['TaxAmount'],$result['operation'][$i]['vat_reversed']); - $result['operation'][$i]['vat_percent']=$percent; - } - $result['subTotalVAT']=$VAT_SubTotal; - $result['LineExtensionAmount']= $result['TaxableAmount']; - $result['TaxExclusiveAmount']= $result['TaxableAmount']; - $result['TaxInclusiveAmount']=bcadd( $result['TaxableAmount'],$result['TaxAmount']); - $result['PayableAmount']=bcadd( $result['TaxableAmount'],$result['TaxAmount']);; - - $this->data=$result; - return $result; + $this->data=parent::build_data($jr_id); + return $this->data; } /** * @brief Information customer @@ -403,7 +296,11 @@ class InvoiceUBL21 extends XMLInvoice { $subTotalXML->appendChild($this->createElement('cbc:TaxAmount',sprintf("%.2f",$subTotal[$i]['vat']))) ->setAttribute("currencyID",$this->data['currency']); $taxCategory=$this->createElement("cac:TaxCategory"); - $taxCategory->appendChild($this->createElement("cbc:ID","S")); + /** + * @TODO DNY + * Pas toujours S !? + */ + //$taxCategory->appendChild($this->createElement("cbc:ID",$subTotal[$i]['vat_code'])); $taxCategory->appendChild($this->createElement("cbc:Percent",sprintf("%.2f",$subTotal[$i]['percent']))); $taxScheme=$this->createElement("cac:TaxScheme"); $taxScheme->appendChild($this->createElement("cbc:ID", "VAT")); @@ -482,9 +379,8 @@ class InvoiceUBL21 extends XMLInvoice { // ITEM $item=$this->createElement("cac:Item"); - $card=new \Fiche($this->cn,$row['card_id']); - $item->appendChild($this->createElement("cbc:Description", $card->get_attribute(ATTR_DEF_NAME))); - $item->appendChild($this->createElement("cbc:Name", $card->get_attribute(ATTR_DEF_QUICKCODE))); + $item->appendChild($this->createElement("cbc:Description",$row['name'])); + $item->appendChild($this->createElement("cbc:Name", $row['qcode'])); $classifiedTaxCat=$this->createElement("cac:ClassifiedTaxCategory"); //cbc:ID S = standard rate diff --git a/include/XMLDocument/XMLInvoice.php b/include/XMLDocument/XMLInvoice.php index 63f6d1e04..777236675 100644 --- a/include/XMLDocument/XMLInvoice.php +++ b/include/XMLDocument/XMLInvoice.php @@ -193,9 +193,12 @@ abstract class XMLInvoice extends \DOMDocument for ($i=0;$i < $nb_operation;$i++) { $result['operation'][$i]['card_id']=$operation->det->array[$i]['qs_fiche']; $result['operation'][$i]['quantity']=$operation->det->array[$i]['qs_quantite']; - + $card=new \Fiche($this->cn,$operation->det->array[$i]['qs_fiche']); + $result['operation'][$i]['qcode']=$card->get_attribute(ATTR_DEF_QUICKCODE); + $result['operation'][$i]['name']=$card->get_attribute(ATTR_DEF_NAME); + $result['operation'][$i]['description']=$card->get_attribute(9); // get the type of unity, if not found then it will be EA - $x= \Card_Property::get_attribute($this->cn,$operation->det->array[$i]['qs_fiche'], ATTR_DEF_QUANTITY_TYPE); + $x= $card->get_attribute(ATTR_DEF_QUANTITY_TYPE,0); $result['operation'][$i]['code_quantity']=($x===false||$x=="")?"EA":$x; // $operation->det->currency_id == 0 default currency of the folder @@ -214,9 +217,10 @@ abstract class XMLInvoice extends \DOMDocument } $result['operation'][$i]['vat_id']=$operation->det->array[$i]['qs_vat_code']; // // tva code for PEPPOL - $x=$this->cn->get_value("select tva_peppol_code from tva_rate where tva_id=$1" + $x=$this->cn->get_row("select tva_peppol_code,tva_rate from tva_rate where tva_id=$1" ,[ $result['operation'][$i]['vat_id']]); - $result['operation'][$i]['vat_code']=($x=="")?"S":$x; + $result['operation'][$i]['vat_code']=($x['tva_peppol_code']=="")?"S":$x['tva_peppol_code']; + $result['operation'][$i]['vat_rate']=$x['tva_rate']; $result['operation'][$i]['vat_reversed']=$operation->det->array[$i]['qs_vat_sided']; } @@ -241,9 +245,64 @@ abstract class XMLInvoice extends \DOMDocument } } $result['info']['communication']=($result['info']['communication']=="")?$result['id']:""; + /** + * Compute totals VAT and AMOUNT + */ + $nb_operation = count($result['operation']); + + /// block cac:LegalMonetaryTotal + $result['LineExtensionAmount']=0; + $result['TaxExclusiveAmount']=0; + $result['TaxInclusiveAmount']=0; + $result['PayableAmount']=0; + + // block cac:TaxTotal + $result['TaxableAmount']=0; + $result['TaxAmount']=0; + + // array for TaxSubtotal + $VAT_SubTotal=array(); + $idx_subtotal=0; + bcscale(2); + // for each operation + $VAT_SubTotal=array(); + for ($i=0;$i < $nb_operation;$i++) { + $acc_tva=\Acc_TVA::build($this->cn,$result['operation'][$i]['vat_id'] ); + $percent = bcmul($acc_tva->tva_rate,100,2); + $idx=sprintf("%s - %s",$percent,$result['operation'][$i]['vat_code'] ); + // subtotal for VAT + $n = find_idx($VAT_SubTotal,'idx',$idx); + if ($n == -1 ) { + $n=$idx_subtotal; + $VAT_SubTotal[$idx_subtotal]=array(); + $VAT_SubTotal[$idx_subtotal]['idx']=$idx; + $VAT_SubTotal[$idx_subtotal]['vat_code']=$result['operation'][$i]['vat_code'] ; + $VAT_SubTotal[$idx_subtotal]['percent']=$percent; + $VAT_SubTotal[$idx_subtotal]['amount']=$VAT_SubTotal[$idx_subtotal]['vat']=0; + $idx_subtotal++; + } + /** + * @todo Pour les intracomm , quel taux utilisé ? 0 ou 21% + */ + $VAT_SubTotal[$n]['amount']=bcadd($VAT_SubTotal[$n]['amount'],$result['operation'][$i]['price']); + $VAT_SubTotal[$n]['vat']=bcadd($VAT_SubTotal[$n]['vat'],$result['operation'][$i]['vat']); + $VAT_SubTotal[$n]['vat']=bcsub($VAT_SubTotal[$n]['vat'],$result['operation'][$i]['vat_reversed']); + $result['TaxableAmount']=bcadd( $result['TaxableAmount'],$result['operation'][$i]['price']); + $result['TaxAmount']=bcadd( $result['TaxAmount'],$result['operation'][$i]['vat']); + $result['TaxAmount']=bcsub( $result['TaxAmount'],$result['operation'][$i]['vat_reversed']); + $result['operation'][$i]['vat_percent']=$percent; + } + $result['subTotalVAT']=$VAT_SubTotal; + $result['LineExtensionAmount']= $result['TaxableAmount']; + $result['TaxExclusiveAmount']= $result['TaxableAmount']; + $result['TaxInclusiveAmount']=bcadd( $result['TaxableAmount'],$result['TaxAmount']); + $result['PayableAmount']=bcadd( $result['TaxableAmount'],$result['TaxAmount']); + return $result; } + + /** * @brief make an array of parameter_extra where pe_code as key and pe_value * as value @@ -281,6 +340,42 @@ abstract class XMLInvoice extends \DOMDocument */ abstract function create_invoice($operation_id) ; + /** + * @brief display_error display a warning with all error + */ + public function display_error() + { + $a_error=$this->verify(); + include NOALYSS_TEMPLATE."/xmlinvoice-display_error.php"; + + } + + /** + * @brief check that the VAT is using a PEPPOL Code + */ + function check_VAT() + { + $a_error=array(); + $nb_operation=count($this->data['operation']); + for ($i=0;$i <$nb_operation;$i++) + { + if ( $this->data['operation'][$i]['vat_code'] == "" ) { + $card=new \Fiche( + $this->cn + ,$this->data['operation'][$i]['card_id'] + ); + $tva= \Acc_Tva::build($this->cn, $this->data['operation'][$i]['vat_id']); + $a_error[]=sprintf(_("%s : %s code TVA pour PEPPOL non configuré code TVA [ %s %s ]") + , $i + , $card->get_quick_code() + ,$tva->tva_id + ,$tva->tva_code + ); + } + } + return $a_error; + } + /** * @brief thanks MY_INVOICE_FORMAT , create the corresponding object * - UBL21BEL => InvoiceUBL21 @@ -298,15 +393,26 @@ abstract class XMLInvoice extends \DOMDocument return null; } - /** + /** * @brief check that all the data are correct - * @returns int 0 : no errors, int separated value - * @see InvoiceUBL21::get_message_error() + * @returns null : no errors, string separated with comma of error code + * @see get_message_error */ - function verify() + public function verify() { - return array(); - } + // verify all VAT + ///@var $a_error : array of error_code see check_company_error + $a_error = array(); + $a_error['general'] = []; + $a_error['operation']=[]; + + // verify that all needed data in PARAMETER are valid + $a_error['company'] = $this->check_company_data(); + $a_error['customer'] = $this->check_customer_data($this->data['customer']['card_id']); + + return $a_error; + } + /** * @brief retrieve data from customer and return it into an array * @param $card_id (int) FICHE.F_ID @@ -419,4 +525,19 @@ abstract class XMLInvoice extends \DOMDocument } return $result; } + + /** + * @brief set the PDF + * @param $pdf_filename (string) full path to the PDF + * @return $this + * @throws \Exception if the filename doesn't exist + */ + public function set_pdf_filename($pdf_filename) { + if ( !file_exists($pdf_filename)) { + throw new \Exception("AD65 $pdf_filename doesn't not exist"); + } + $this->pdf_filename = $pdf_filename; + return $this; + } + } diff --git a/include/class/acc_document.class.php b/include/class/acc_document.class.php index b96fca43c..efe9c7ea5 100644 --- a/include/class/acc_document.class.php +++ b/include/class/acc_document.class.php @@ -120,6 +120,32 @@ class Acc_Document extends Document { $this->db->commit(); return true; } + /** + * @brief for FACTURX we replace the PDF save in DB by this one, always + * a PDF (since it is a FACTURX document) + */ + function replace_receipt($new_oid) + { + if ($this->d_lob != "") + { + $this->db->lo_unlink($this->d_lob); + } + $this->d_lob=$new_oid; + $this->db->exec_sql(" + update jrn + set + jr_pj = $1 + ,jr_pj_name =$2 + ,jr_pj_type =$3 + where jr_id=$4 + ", + [$this->d_lob + ,$this->d_filename + ,$this->d_mimetype + ,$this->d_id] + ); + + } /** * @brief save the Large Object $oid in the column JRN.JR_DOCUMENT_XML * @param $oid( OID) PostgreSQL Object ID @@ -357,5 +383,5 @@ class Acc_Document extends Document { .''; return $r; } - + } \ No newline at end of file diff --git a/include/class/document.class.php b/include/class/document.class.php index 31bf6749d..9c96b9479 100644 --- a/include/class/document.class.php +++ b/include/class/document.class.php @@ -58,6 +58,24 @@ class Document // counter for MARCH_NEXT $this->counter=0; } + + function __toString(): string + { + return "Document[db=" . $this->db + . ", d_id=" . $this->d_id + . ", ag_id=" . $this->ag_id + . ", d_mimetype=" . $this->d_mimetype + . ", d_filename=" . $this->d_filename + . ", d_lob=" . $this->d_lob + . ", d_description=" . $this->d_description + . ", d_number=" . $this->d_number + . ", md_id=" . $this->md_id + . ", f_id=" . $this->f_id + . ", counter=" . $this->counter + . ", d_name=" . $this->d_name + . ", md_type=" . $this->md_type + . "]"; + } /** * @brief insert a minimal document and set the d_id diff --git a/include/compta_ven.inc.php b/include/compta_ven.inc.php index f1634df06..838a048fd 100644 --- a/include/compta_ven.inc.php +++ b/include/compta_ven.inc.php @@ -66,6 +66,9 @@ if ( isset ($_POST['view_invoice'] ) ) $p_msg=$e->getMessage(); $correct=1; } + //------------------------------------------------ + // Confirm before saving + //------------------------------------------------ // if correct is not set it means it is correct if ( ! isset($correct)) { @@ -219,7 +222,7 @@ if ( isset($_POST['record']) ) $xmldocument->set_pdf_filename($pdf_filename); // make the XML + PDF - $xml=$xmldocument->make_xml($Ledger->jr_id); + $xml=$xmldocument->create_invoice($Ledger->jr_id); if (DEBUGNOALYSS > 1) { $mt=date ('ymd-Hi').'+'.$Ledger->jr_id; $uniq= $_ENV['TMP']. DIRECTORY_SEPARATOR."$mt-e-invoice.xml"; @@ -228,16 +231,24 @@ if ( isset($_POST['record']) ) echo \Noalyss\Dbg::echo_file("file save $uniq"); } + // FOR BELGIUM : XML and PDF will be store separately // save XML string into the DB $oid=$cn->lo_write($xml); echo \Noalyss\Dbg::echo_var(1, "oid is $oid"); if ($oid == false) { throw new Exception ('CV177 : cannot import e-invoice'); } - $acc_document->update_document_xml($oid); + if ( $g_parameter->MY_INVOICE_FORMAT == 'UBL21BEL') + { + $acc_document->update_document_xml($oid); + $receipt= HtmlInput::show_receipt_document($Ledger->jr_id,$acc_document->d_filename) + . $acc_document->link_download_xml(); + }elseif ($g_parameter->MY_INVOICE_FORMAT=='FACTURXFR') + { + $acc_document->replace_receipt($oid); + $receipt= HtmlInput::show_receipt_document($Ledger->jr_id,$acc_document->d_filename); + } - $receipt= HtmlInput::show_receipt_document($Ledger->jr_id,$acc_document->d_filename) - . $acc_document->link_download_xml(); } } diff --git a/include/template/invoiceUBL21-display_error.php b/include/template/xmlinvoice-display_error.php similarity index 100% rename from include/template/invoiceUBL21-display_error.php rename to include/template/xmlinvoice-display_error.php