Giter VIP home page Giter VIP logo

einvoicing's Introduction

Build Status Latest Version Supported PHP Versions License Documentation

About

eInvoicing is a PHP library for creating and reading electronic invoices according to the eInvoicing Directive and European standard.

It aims to be 100% compliant with EN 16931 as well as with the most popular CIUS and extensions, such as PEPPOL BIS.

Installation

First of all, make sure your environment meets the following requirements:

Then, you should be able to install this library using Composer:

composer require josemmo/einvoicing

Usage

For a proper quick start guide, visit the documentation website at https://josemmo.github.io/einvoicing/.

Importing invoice documents

use Einvoicing\Exceptions\ValidationException;
use Einvoicing\Readers\UblReader;

$reader = new UblReader();
$document = file_get_contents(__DIR__ . "/example.xml");
$inv = $reader->import($document);
try {
    $inv->validate();
} catch (ValidationException $e) {
    // Invoice is not EN 16931 complaint 
}

Exporting invoice documents

use Einvoicing\Identifier;
use Einvoicing\Invoice;
use Einvoicing\InvoiceLine;
use Einvoicing\Party;
use Einvoicing\Presets;
use Einvoicing\Writers\UblWriter;

// Create PEPPOL invoice instance
$inv = new Invoice(Presets\Peppol::class);
$inv->setNumber('F-202000012')
    ->setIssueDate(new DateTime('2020-11-01'))
    ->setDueDate(new DateTime('2020-11-30'));

// Set seller
$seller = new Party();
$seller->setElectronicAddress(new Identifier('9482348239847239874', '0088'))
    ->setCompanyId(new Identifier('AH88726', '0183'))
    ->setName('Seller Name Ltd.')
    ->setTradingName('Seller Name')
    ->setVatNumber('ESA00000000')
    ->setAddress(['Fake Street 123', 'Apartment Block 2B'])
    ->setCity('Springfield')
    ->setCountry('DE');
$inv->setSeller($seller);

// Set buyer
$buyer = new Party();
$buyer->setElectronicAddress(new Identifier('ES12345', '0002'))
    ->setName('Buyer Name Ltd.')
    ->setCountry('FR');
$inv->setBuyer($buyer);

// Add a product line
$line = new InvoiceLine();
$line->setName('Product Name')
    ->setPrice(100)
    ->setVatRate(16)
    ->setQuantity(1);
$inv->addLine($line);

// Export invoice to a UBL document
header('Content-Type: text/xml');
$writer = new UblWriter();
echo $writer->export($inv);

Roadmap

These are the expected features for the library and how's it going so far:

  • Representation of invoices, parties and invoice lines as objects
  • Compatibility with the most used CIUS and extensions
  • Export invoices to UBL documents
  • Import invoices from UBL documents
  • Export invoices to CII documents
  • Import invoices from CII documents
  • Proper documentation

einvoicing's People

Contributors

christianvermeulen avatar hmazter avatar josemmo avatar peter279k avatar rycks avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

einvoicing's Issues

How to add tag SupplierAssignedAccountID

I'm trying to export UBL invoices for importing in an accounting application (Venice) and need to add cac:AccountingCustomerParty/cbc:SupplierAssignedAccountID to the XML file.

How can this be done using this package?

Screenshot from 2022-12-05 15-18-22

Thanks in advance

XML validator when there is allowance on lines

Hello,
here is my problem:

Element/context: /:Invoice[1]/cac:InvoiceLine[1]
XPath test: u:slack($lineExtensionAmount, ($quantity * ($priceAmount div $baseQuantity)) + $chargesTotal - $allowancesTotal, 0.02)
Error message: Invoice line net amount MUST equal (Invoiced quantity * (Item net price/item price base quantity) + Sum of invoice line charge amount - sum of invoice line allowance amount

My invoice is really basic: only one line:

  • price: 100
  • quantity: 1
  • vat rate: 20%
  • discount : 10%

Invoice rounding problem

Hi!

It seems there is rounding problem with the xml generator:
[BR-CO-15]-Invoice total amount with VAT (BT-112) = Invoice total amount without VAT (BT-109) + Invoice total VAT amount (BT-110).

example data input:

$line = new InvoiceLine();
$line->setPrice(0.25)
    ->setQuantity(26935.78)
    ->setVatRate(19)

Which generates this nodes:

<cac:TaxTotal>
<cbc:TaxableAmount currencyID="RON">6733.95</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="RON">1279.45</cbc:TaxAmount>
...
<cac:LegalMonetaryTotal>
    <cbc:LineExtensionAmount currencyID="RON">6733.95</cbc:LineExtensionAmount>
    <cbc:TaxExclusiveAmount currencyID="RON">6733.95</cbc:TaxExclusiveAmount>
    <cbc:TaxInclusiveAmount currencyID="RON">8013.39</cbc:TaxInclusiveAmount>
    <cbc:PayableAmount currencyID="RON">8013.39</cbc:PayableAmount>
</cac:LegalMonetaryTotal>

The final amounts should be 8013.40, not 8013.39

And here is the generated xml:
factura-102-o2u-2022-e-ron-00066.txt

Add seller iban and bank name

How to add seller iban and bank name

$transfer = new Transfer();
$transfer->setAccountId('IBAN')
->setAccountName('Numecont')
->setProvider('ING bank');
$inv->addPaymentTransferNode($transfer);

Missing fields

Hi Josemmo,

Love this package! It seems that there are still some fields missing.
E.g. AccountingCostCode is a field that can be placed in the invoice or invoice lines.

Is it possible to add these fields, or is it perhaps possible to add these using a general function?

Something like

public function setCustomValues(string $fieldName, string $fieldValue) {
        $this->{$fieldName} = $fieldValue;
        return $this;
    }

Add support for TaxCurrencyCode (BT-6)

Hi @josemmo

First: thanks for this awesome library!

I'm currently developing integration with anaf (romanian tax authority). They use a special ruleset: RO_CIUS
They have a special (fatal) rule:
BR-RO-030: If the "Invoice Currency Code" (BT-5) is other than "RON", then the item "VAT Accounting Currency Code" (BT-6) must be "RON".

It seems the library doesn't have a support for BT-6. We've created two xml-s with smartbill I've attached them here. However BT-6 requires an extra:

<cac:TaxTotal>
    <cbc:TaxAmount currencyID="RON">93.89</cbc:TaxAmount><!--BT-111-->
</cac:TaxTotal>

so BT-6 maybe needs an exchange rate option to correctly calculate the amount (eg: EUR to RON: 4.1234, RON to RON 1.000)?

Samples:
RON2RON.txt
EUR2RON.txt

(these are xmls but github doesn't allow xml uploads)

How to best handle XML entities

First of all, thank you for your wonderful work with this package!

Today I came across a bug when generating an e-invoice where the seller's name had an ampersand (&) in their name:

DOMDocument::createElement(): unterminated entity reference             REDACTED

REDACTED\vendor\josemmo\uxml\src\UXML.php:66
REDACTED\vendor\josemmo\uxml\src\UXML.php:130

Adding htmlspecialchars() to all method calls when creating the invoice of course fixed the problem.

My question is, maybe this package should call htmlspecialchars() on all values instead? I can't see any drawbacks. An other option could be to add a note about this in the documentation.

An other (more obtrusive) option would be to change your UXML package:

    public static function newInstance(string $name, ?string $value=null, array $attrs=[], DOMDocument $doc=null): self {
        $targetDoc = ($doc === null) ? new DOMDocument() : $doc;
        $domElement = $targetDoc->createElement($name); // <----
        $domElement->textContent = $value; // <----

        // Set attributes
        foreach ($attrs as $attrName=>$attrValue) {
            if ($attrName === "xmlns" || strpos($attrName, 'xmlns:') === 0) {
                $domElement->setAttributeNS('http://www.w3.org/2000/xmlns/', $attrName, $attrValue);
            } else {
                $domElement->setAttribute($attrName, $attrValue);
            }
        }

        // Create instance
        return new self($domElement);
    }

Negative PayableRoundingAmount

Thanks for a helpful library! Discovered a problem with RoundingAmount.

cbc:PayableRoundingAmount can be negative and positive, but the element only shows if the amount is positive. Suggest changing line 831 in UblWriter.php from:
if ($totals->roundingAmount > 0) {

to:
if ($totals->roundingAmount <> 0) {

Many thanks

PartyTaxScheme xsd validation error with passing null as scheme

Hi @josemmo!

It seems I've encountered a bug

$Seller->setTaxRegistrationId(
    new Identifier("12345678")
);

This generates an invalid xml (validated by xsd validation), because <cac:TaxScheme> node is missing in the generated xml. It appears that <cac:TaxScheme/> is the valid option here.

You can validate against xsd here:
https://ecosio.com/en/peppol-and-xml-document-validator/
Example xml-s (check line 48 <cac:PartyTaxScheme> node):
taxscheme_with_value.txt Valid
taxscheme_novalue.txt Valid
taxscheme_missing.txt Invalid

Division by zero for $invoice->getTotals()->taxInclusiveAmount

Division by zero for
$invoice->getTotals()->taxInclusiveAmount

Invoice is from E.ON Energie ..

i've put xml relevant part bellow.

cac:LegalMonetaryTotal
<cbc:LineExtensionAmount currencyID="RON">0.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="RON">0.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="RON">0.00</cbc:TaxInclusiveAmount>
<cbc:PayableRoundingAmount currencyID="RON">0.00</cbc:PayableRoundingAmount>
<cbc:PayableAmount currencyID="RON">0.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
cac:InvoiceLine
cbc:ID1</cbc:ID>
<cbc:InvoicedQuantity unitCode="EA">2.776</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="RON">4.55</cbc:LineExtensionAmount>
cac:Item
cbc:NameIncarcare electrica - Ianuarie 2024 Conform contract</cbc:Name>
cac:ClassifiedTaxCategory
cbc:IDS</cbc:ID>
cbc:Percent19</cbc:Percent>
cac:TaxScheme
cbc:IDVAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
cac:Price
<cbc:PriceAmount currencyID="RON">163.77</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="C62">0.00</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>
cac:InvoiceLine
cbc:ID2</cbc:ID>
<cbc:InvoicedQuantity unitCode="EA">1.000</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="RON">-4.55</cbc:LineExtensionAmount>
cac:Item
cbc:NameStornare incarcare electrica - Ianuarie 2024 Conform contract</cbc:Name>
cac:ClassifiedTaxCategory
cbc:IDS</cbc:ID>
cbc:Percent19</cbc:Percent>
cac:TaxScheme
cbc:IDVAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
cac:Price
<cbc:PriceAmount currencyID="RON">454.62</cbc:PriceAmount>
<cbc:BaseQuantity unitCode="C62">0.00</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>

Add support for CompanyLegalForm (BT-33)

Hi @josemmo

First: thanks for this awesome library (again 😃 )!

It seems the library doesn't have a support for BT-33 (Additional legal information about the Seller)

<cac:PartyLegalEntity>
   <cbc:RegistrationName>Teszt</cbc:RegistrationName><!--BT-27-->
   <cbc:CompanyLegalForm>Capital social: 123123 lei</cbc:CompanyLegalForm><!--BT-33-->
</cac:PartyLegalEntity>

It's a free text node, nothing special, and RO_CIUS doesn't have any extra rule for it.
Sample:
BT-33.txt

CreditNote support

Hello,
From what I'm seeing this package doesn't have support for credit notes?

Add support for multiple Invoice Notes (BG-1 -> BT-22)

Hi @josemmo!

I've noticed in RO_CIUS validation rules:
BR-RO-A020 BG-1 (Fatal): The maximum allowed number of occurrences is 20.

So it seems the UBL 2.1 standard allows multiple Notes, however the library only has a setter on the Invoice (instead of eg: addNote maybe?).
Although, invoice lines does not support multiple notes, only 1 (I think this is not a RO_CIUS, but UBL 2.1 regulation).

BT-22 Note
Example of use:

<cbc:Note>Operator tag:operater1</cbc:Note>
<cbc:Note>Release Time:15:02:23</cbc:Notes>
<cbc:Note>JIR:66d0d0d1-3834-466f-a632-995ce32547b8</cbc:Note>
<cbc:Note>ZKI:efc9303e849c070c5382198c7c154610</cbc:Notes>
<cbc:Note>Responsible person:Name and surname</cbc:Notes>
<cbc:Note>Applying the Tax Procedure to the Charged Fee</cbc:Note>
<cbc:Notes>We calculate default interest on your account if your account is not paid within the</cbc:Note>

European standard EN 16931 - UBL 2.1.pdf

BT-22-example.txt

REST Wrapper

Since you do something really helpful for anyone who wants to start with e-invoicing, it would be useful to provide REST enpoints for people who are not familiar with php like me. For example, I want to use it in a java project.
Maybe it's in the scope of this project since you want to create a php library but it could be a familiar project.

Text for Payment Means (BT-82) is bugged?

Hi @josemmo!

it seems setMeansText is generating a wrong xml node:

$payment = new Payment();
$payment->setMeansCode(31);
$payment->setMeansText("Payment Text");

this generates the following xml:

<cac:PaymentMeans>
    <cbc:PaymentMeansCode name="Payment Text">31</cbc:PaymentMeansCode>
</cac:PaymentMeans>

instead of:

<cac:PaymentMeans>
    <cbc:PaymentMeansCode>31</cbc:PaymentMeansCode>
    <cbc:InstructionNote>Payment Text</cbc:InstructionNote>
</cac:PaymentMeans>

BT-82 is the InstructionNote, in regards to the documentations.

Support for BG-30 Line VAT information attributes schemID and schemeAgencyId (NLCIUS v1.0.3)

Hi @josemmo,

Thank you for creating this package and publishing it open source. I'm currently dealing with some validation issues with our Peppol partner. I need to set the schemeID attribute to UN/ECE 5153 and schemeAgencyID to 6 in the cac:TaxScheme node. This is currently not supported by this package and I couldn't extend the package by swapping the instances.

Before I considered creating this issue I tried to get a good grasp of how the ecosystem of einvoices and the available specifications, but the information is quite vague. This support request hopefully makes sense.

It's already possible to set the value of the cac:TaxScheme node:

$invoiceLine = (new InvoiceLine())
    ->setName('Some name')
    ->setPrice(120)
    ->setVatRate(21)
    ->setQuantity(2)
    ->setVatCategory('Z');

It is however not possible to set the attribute values of:

  • schemeID
  • schemeAgencyID

Some resources:

I would like to create a pull request for this feature, but since I'm not fully known in this domain I do like to get some feedback on this feature request.

decimal rounding number

Hi and thank your for your work
I'm currently trying to implement your superb library for Saoudan Arabia rules
I need to set all prices and totals with 2 decimal rounding, is the feature missing or am I missing someting ?

Multiple PartyTaxSchemes

Hi!

According to https://docs.peppol.eu/poacc/billing/3.0/syntax/ubl-invoice/cac-AccountingSupplierParty/cac-Party/cac-PartyTaxScheme/ allows up to 2 instances of PartyTaxScheme on the AccountingSupplierParty.

And we are in need of using both those instances to accomplish this output:

<cac:PartyTaxScheme>
  <cbc:CompanyID>SE555555-555501</cbc:CompanyID>
  <cac:TaxScheme>
    <cbc:ID>VAT</cbc:ID>
  </cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyTaxScheme>
  <cbc:CompanyID>GODKÄND FÖR F-SKATT</cbc:CompanyID>
  <cac:TaxScheme>
    <cbc:ID>TAX</cbc:ID>
  </cac:TaxScheme>
</cac:PartyTaxScheme>

What could be a good approach to add that functionality?
I can open a PR, but wanted to ask for directions first.

Edge case using VAT

Hello,

I have the following scenario that's not outputting the correct total.
I know it's not a bug, but what would be a valid solution?

This is the code that's creating an invoice line with a 100k quantity and the price of 100 including VAT (that's why 100 / 1.19)

$line = (new \Einvoicing\InvoiceLine())
            ->setQuantity(100_000)
            ->setPrice(100 / 1.19)
            ->setVatRate(19);
$invoice = (new \Einvoicing\Invoice(CiusRo::class))
    ->addLine($line);
echo $invoice->getTotals()->taxInclusiveAmount;

The output of this code is 9.999.999,99 instead of 10.000.000

UXML get returns self|null ...

Hello,
with a "bad" XML file this bug could happens:

Call to a member function asText() on null", "exception": "Error", "file": "vendor/josemmo/einvoicing/src/Readers/UblReader.php", "line": 61

Because of get function in UXML.php returns self or null

So i could make a fix but i don't know if the best solution is to return an empty object instead off null or add a test on each ->get call ?

For example

Solution 1 in UXML.php could become


    /**
     * Find one element
     * @param  string    $xpath XPath query relative to this element
     * @return self|empty object        First matched element or empty object if not found
     */
    public function get(string $xpath): ?self {
        $res = $this->getAll($xpath, 1);
        return $res[0] ?? new UXML();
    }

Or Solution 2 will be to change every (like in UblReader.php line 61 and all others)

            $rate = (float) $node->get("{{$cbc}}Percent")->asText();

to


if(isset($node->get("{{$cbc}}Percent"))) {
            $rate = (float) $node->get("{{$cbc}}Percent")->asText();
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.