I’m working on interfacing Tryton with Chorus (platform to send electronic invoice for French administration).
This platform supports many format like UBL, UN/CEFACT, CPP etc. I choose to implement UN/CEFACT (because it is the basis for Factur-X ) Indeed UBL and UN/CEFACT are very similar and they both rely on standard code from UNECE (which is also the author of UN/CEFACT).
Now, the hard part is to create a module structure for those modules. We should keep in mind that electronic invoice is only one kind of electronic document, those standard implements Shipment, Quotation, Purchase Request etc. For the same Tryton document, we may need to generate different electronic documents, for example to send to different parties or systems.
Also each norm has many revisions and we may need to support many at the same time for compatibility. That’s why I think we should follow the same design as the account_payment_sepa
module with one template per version.
To avoid the multiplication of modules, I think we should have a single module per format which will implement all the different kind of documents. Those will be registered in function of the installed modules (thanks to issue7178).
So my proposal is to use “edocument” as general prefix. I find it to be not too long (compared to electronic_document) and it is pretty clear what it covers.
So we will have for example those modules:
- edocument_unece: define common code from UNECE
- edocument_uncefact: implement UN/CEFACT documents
- edocument_ubl: implement UBL documents
Inside the module we will have:
edocument_uncefact/
template/
16B/
CrossIndustryInvoice.xml
CrossIndustryOrder.xml
CrossIndustryQuotationProposal.xml
16B-CII/
CrossIndustryInvoice.xml
edocument_ubl/
template/
2.0/
Invoice.xml
2.1/
CreditNote.xml
Invoice.xml
Order.xml
The generation and processing of the document will be managed by a simple Model, this will prevent to pollute to much the document Model. For example for UN/CEFACT CrossIndustryInvoice:
class Invoice(Model):
__name__ = 'edocument.uncefact.invoice'
def __init__(self, invoice):
self.invoice = invoice
def get(self, template='16B-CII/CrossIndustryInvoice.xml'):
…
@classmethod
def process(cls, document):
…