Modules d'export comptable ============================ enDI utilise pyramid_services pour accéder aux classes à utiliser lors du processus d'export comptable. Afin de produire des exports différents de ceux proposés par enDI, il est possible de développer de nouvelles classes : - Pour produire les données des écritures ( ITreasuryProducer ) - Pour exporter les écritures dans un fichier ( ITreasuryWriter ) Méthodologie ------------- Récupérer - Un export enDI SAGE des écritures - Un fichier comportant les écritures attendues Développer des Classes de génération d'écritures, des Producer et des Writers. Pour tester une sortie, LibreOffice propose une fonctionnalité de comparaison de document. En prenant l'export généré par le module custom des mêmes documents que ceux du fichier exemple : - Ouvrir le fichier exemple - Édition -> Suivi des modifications -> Comparer le document Schéma de fonctionnement ------------------------- Le schéma ci-dessous décrit le fonctionnement de l'export .. image:: _static/export_comptable/cycle_export_comptable.png :width: 100% :alt: Diagramme décrivant le fonctionnement des exports Le développement d'export custom peut donc se faire - En développant des Modules d'export - En développant des Producer (ITreasuryProducer) - En développant des Writers (ITreasuryWriter) Modification des règles de calcul, attribution des valeurs : Modules et Producer --------------------------------------------------------------------------------- Les Producers implémentent l'interface `endi.interfaces.ITreasuryProducer` Ils produisent les données utilisées dans les écritures comptables sous forme de dictionnaires. Ils font usage de Module qui produisent chacun un certain type d'écritures (contribution, assurance ...), en collectant les comptes à utiliser, les montants, les pourcentages... La plupart des opérations sont réalisées dans les Modules. On développera ainsi un Module pour modifier les comportements par défaut d'enDI et un Producer pour le référencer. Un Producer custom permettra de : - Référencer des Modules différents de ceux par défaut - Limiter la production d'écritures aux écritures générales ou analytiques Formattage des données, Format de fichier : Writer -------------------------------------------------- Les Writers implémentent l'interface `endi.interfaces.ITreasuryWriter` Ils produisent les données renvoyées à l'utilisateur - Sous forme de fichier - Sous forme de pré-visualisation Ils formattent les données pour qu'elles ressortent dans le format attendu (format des dates, des nombres ...). Ils sont également utils pour facilement rajouter une colonne fixe (Currency par exemple). Le writer peut hériter de classe de sqla_inspect : .. code-block:: python from sqla_inspect.csv import CsvExporter from sqla_inspect.excel import XlsExporter as XlsxExporter Il doit fournir les éléments requis par l'interface `endi.interfaces.ITreasuryWriter` - Les headers - Une méthode format_row (NB : déjà fournie par les classes de sqla_inspect) - Une méthode format_cell (NB : déjà fournie par les classes de sqla_inspect) - Une méthode set_datas (NB : déjà fournie par les classes de sqla_inspect) headers ........ Les headers doivent être de la forme .. code-block:: python { 'name': , 'label': } Un 'typ' peut être ajouté pour le rendu dans le preview: 'typ': 'text'|'date'|'number' NB : Les headers peuvent référencer des colonnes qui ne sont pas générées par le Producer, cela permet d'ajouter des colonnes vides ou des colonnes à valeur fixe (comme la currency par exemple) format_row(self, row_dict) ........................... Prend le dictionnaire généré par le Producer en entrée. Renvoie la ligne d'écriture sous la forme : d'une liste ou d'un dictionnaire (en fonction du writer). Cette méthode est fournie par les classes de sqla_inspect et peut être overridée pour formatter des données en ayant accès aux autres données. .. code-block:: python headers = [ ... {'name': 'credit_debit', 'label': 'MONTANT'}, {'name': 'sens', 'label': 'TYPE'}, ... ] # Exemple dans le module d'export CEGID def format_row(self, row) -> List: if row.get("debit", 0) and not row.get("credit", 0): row["sens"] = "D" row["credit_debit"] = row["debit"] else: row["sens"] = "C" row["credit_debit"] = row["credit"] result = super().format_row(row) return result format_(self, value) ............................. Prend la valeur renvoyée par le Producer pour l'attribut "column" et renvoie la valeur formattée pour le rendu dans la sortie finale. .. code-block:: python def format_compte_cg(self, value): """ Réduit les comptes généraux à 6 caractères """ if value: value = value[:6] return value def format_currency(self, value): return "EUR" Exemple ---------- Développer un Module custom .. code-block:: python from endi.compute.sage.invoice import SageFacturation class MainInvoice(SageFacturation): """ """ static_columns = ( 'code_journal', 'date', 'num_facture', 'libelle', 'type_', ) @property def libelle(self): return self.invoice.customer.name.upper() def debit_ttc(self, product): """ Déplace le compte tiers dans la colonne compte_cg pour les débits TTC du module vente """ gen_line, ana_line = super().debit_ttc(product) ana_line["compte_cg"] = ana_line["compte_tiers"] return gen_line, ana_line Utilisez ce Module dans un Producer .. code-block:: python from zope.interface import implementer from endi.compute.sage.invoice import InvoiceExportProducer from endi.interface import ITreasuryProducer @implementer(ITreasuryProducer) class InvoiceProducer(InvoiceExportProducer): """ Custom producer pour les factures c'est lui qui produit les lignes d'export pour les factures ici il s'assure de vire une des deux lignes analytiques/générales """ use_analytic = False _default_modules = (MainInvoice, ) _available_modules = {} Ajouter un Writer spécifique .. code-block:: python from zope.interface import implementer from sqla_inspect.excel import XlsExporter from endi.utils.datetime import format_short_date from endi.utils import strings from endi.interface import ITreasuryInvoiceWriter @implementer(ITreasuryInvoiceWriter) class InvoiceXlsxWriter(XlsExporter): """ Sage invoice csv writer Add the handling of the invoice prefix in invoice number formatting """ encoding = "utf-8" mimetype = ( "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) extension = 'xlsx' amount_precision = 5 headers = ( {'name': 'date', 'label': "date", "typ": "date"}, {'name': 'num_facture', 'label': 'n° de pièce'}, {'name': 'compte_cg', 'label': "n° de compte"}, {'name': 'libelle', 'label': 'libellé'}, {"name": "currency", "label": "Colonne vide"}, {'name': 'debit', 'label': "débit", "typ": "number"}, {'name': 'credit', 'label': "crédit", "typ": "number"}, ) def __init__(self, *args): XlsExporter.__init__(self) def format_debit(self, debit): """ Format the debit entry to get a clean float in our export 12000 => 120,00 """ if debit == '': return 0 else: return strings.format_amount( debit, grouping=False, precision=self.amount_precision ).replace(',', '.') def format_credit(self, credit): """ format the credit entry to get a clean float """ return self.format_debit(credit) def format_num_facture(self, value): return "F{0}".format(value) def format_date(self, value): return format_short_date(value) Configurer enDI dans le fichier .ini pour utiliser ces éléments .. code-block:: [app:endi] ... endi.services.treasury_invoice_producer=endi.export.custom.InvoiceProducer endi.services.treasury_invoice_writer=endi.export.custom.InvoiceXlsxWriter ... Les écritures se feront alors au format xlsx, les données seront reformattées selon les règles ci-dessus. Liste des Producers par défaut ------------------------------- Ventes :py:class:`endi.compute.sage.invoice.InvoiceExportProducer` :py:class:`endi.compute.sage.invoice.InternalInvoiceExportProducer` Encaissements :py:class:`endi.compute.sage.payment.PaymentExportProducer` :py:class:`endi.compute.sage.payment.InternalPaymentExportProducer` Notes de dépenses :py:class:`endi.compute.sage.expense.ExpenseExportProducer` Paiement des Notes de dépenses :py:class:`endi.compute.sage.expense_payment.ExpensePaymentExportProducer` Factures fournisseurs :py:class:`endi.compute.sage.supplier_invoice.SupplierInvoiceExportProducer` :py:class:`endi.compute.sage.supplier_invoice.InternalSupplierInvoiceExportProducer` Paiements des Factures fournisseurs :py:class:`endi.compute.sage.supplier_invoice_payment.SupplierPaymentExportProducer` :py:class:`endi.compute.sage.supplier_invoice_payment.InternalSupplierPaymentExportProducer` :py:class:`endi.compute.sage.supplier_invoice_payment.SupplierUserPaymentExportProducer` Liste des Writers par défaut ---------------------------- Ventes :py:class:`endi.export.sage.SageInvoiceCsvWriter` Encaissements :py:class:`endi.export.sage.SagePaymentCsvWriter` Notes de dépenses :py:class:`endi.export.sage.SageExpenseCsvWriter` Paiement des Notes de dépenses :py:class:`endi.export.sage.SageExpensePaymentCsvWriter` Factures fournisseurs :py:class:`endi.export.sage.SageSupplierInvoiceCsvWriter` Paiements des Factures fournisseurs :py:class:`endi.export.sage.SageSupplierPaymentCsvWriter` Clé de configuration --------------------- .. code-block:: inifile endi.services.treasury_invoice_producer endi.services.treasury_internalinvoice_producer endi.services.treasury_invoice_writer endi.services.treasury_payment_producer endi.services.treasury_internalpayment_producer endi.services.treasury_payment_writer endi.services.treasury_expense_producer endi.services.treasury_expense_writer endi.services.treasury_expense_payment_producer endi.services.treasury_expense_payment_writer endi.services.treasury_supplier_invoice_producer endi.services.treasury_internalsupplier_invoice_producer endi.services.treasury_supplier_invoice_writer endi.services.treasury_supplier_payment_producer endi.services.treasury_supplier_payment_user_producer endi.services.treasury_internalsupplier_payment_producer endi.services.treasury_supplier_payment_writer