Initial commit: OCA Edi packages (42 packages)

This commit is contained in:
Ernad Husremovic 2025-08-29 15:43:05 +02:00
commit df976c03db
2184 changed files with 571602 additions and 0 deletions

View file

@ -0,0 +1,45 @@
# Account Invoice Export
Odoo addon: account_invoice_export
## Installation
```bash
pip install odoo-bringout-oca-edi-framework-account_invoice_export
```
## Dependencies
This addon depends on:
- account
- account_invoice_transmit_method
## Manifest Information
- **Name**: Account Invoice Export
- **Version**: 16.0.1.0.0
- **Category**: Invoicing Management
- **License**: AGPL-3
- **Installable**: True
## Source
Based on [OCA/edi-framework](https://github.com/OCA/edi-framework) branch 16.0, addon `account_invoice_export`.
## License
This package maintains the original AGPL-3 license from the upstream Odoo project.
## Documentation
- Overview: doc/OVERVIEW.md
- Architecture: doc/ARCHITECTURE.md
- Models: doc/MODELS.md
- Controllers: doc/CONTROLLERS.md
- Wizards: doc/WIZARDS.md
- Install: doc/INSTALL.md
- Usage: doc/USAGE.md
- Configuration: doc/CONFIGURATION.md
- Dependencies: doc/DEPENDENCIES.md
- Troubleshooting: doc/TROUBLESHOOTING.md
- FAQ: doc/FAQ.md

View file

@ -0,0 +1,97 @@
======================
Account Invoice Export
======================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:ded419ed17e642aaf14f71f78778c50e6480162d6931a6431f2574ffafa15adf
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fedi-lightgray.png?logo=github
:target: https://github.com/OCA/edi/tree/16.0/account_invoice_export
:alt: OCA/edi
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/edi-16-0/edi-16-0-account_invoice_export
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/edi&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
The goal of this module is to allow sending invoices in different format to external systems.
It extends the module `account_invoice_transmit_method`, adding options to configure an url and credentials (Basic Authentication).
In the UI a new button `Send ebill` send the invoice pdf to the configure url.
The actual sending of the invoice is manage by queue.job and the standard Odoo chatter on the invoice is used to inform the user on success/failure of the dispatch.
**Table of contents**
.. contents::
:local:
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/edi/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/edi/issues/new?body=module:%20account_invoice_export%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Camptocamp SA
Contributors
~~~~~~~~~~~~
* Thierry Ducrest <thierry.ducrest@camptocamp.com>
* Tam (Nguyen Duc) <tamnd@trobz.com>
Other credits
~~~~~~~~~~~~~
The development of this module has been financially supported by:
* Camptocamp
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
.. |maintainer-TDu| image:: https://github.com/TDu.png?size=40px
:target: https://github.com/TDu
:alt: TDu
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-TDu|
This module is part of the `OCA/edi <https://github.com/OCA/edi/tree/16.0/account_invoice_export>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

@ -0,0 +1 @@
from . import models

View file

@ -0,0 +1,22 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
{
"name": "Account Invoice Export",
"version": "16.0.1.0.0",
"category": "Invoicing Management",
"license": "AGPL-3",
"development_status": "Beta",
"summary": "",
"author": "Camptocamp SA, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/edi",
"depends": ["account", "account_invoice_transmit_method"],
"maintainers": ["TDu"],
"data": [
"data/mail_activity_type.xml",
"views/transmit_method.xml",
"views/account_move.xml",
"views/message_template.xml",
],
"installable": True,
}

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="mail_activity_transmit_warning" model="mail.activity.type">
<field name="name">Transmission Error</field>
<field name="icon">fa-warning</field>
<field name="delay_count">0</field>
<field name="sequence">99</field>
<field name="decoration_type">warning</field>
</record>
</odoo>

View file

@ -0,0 +1,149 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_invoice_export
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_invoice_export
#: model:ir.model.fields,help:account_invoice_export.field_account_bank_statement_line__send_through_http
#: model:ir.model.fields,help:account_invoice_export.field_account_move__send_through_http
#: model:ir.model.fields,help:account_invoice_export.field_account_payment__send_through_http
#: model:ir.model.fields,help:account_invoice_export.field_transmit_method__send_through_http
msgid "Adds a Send eBill button on the invoice"
msgstr ""
#. module: account_invoice_export
#. odoo-python
#: code:addons/account_invoice_export/models/account_move.py:0
#, python-format
msgid "An error of type {} occured."
msgstr ""
#. module: account_invoice_export
#: model_terms:ir.ui.view,arch_db:account_invoice_export.transmit_method_form
msgid ""
"By default the PDF of the invoice will be sent using the connection "
"parameters below (basic authenticaiton)."
msgstr ""
#. module: account_invoice_export
#: model_terms:ir.ui.view,arch_db:account_invoice_export.view_move_form
msgid "Ebill has already been sent. Are you sure you want to send it again ?"
msgstr ""
#. module: account_invoice_export
#: model:ir.model.fields,field_description:account_invoice_export.field_account_bank_statement_line__send_through_http
#: model:ir.model.fields,field_description:account_invoice_export.field_account_move__send_through_http
#: model:ir.model.fields,field_description:account_invoice_export.field_account_payment__send_through_http
#: model:ir.model.fields,field_description:account_invoice_export.field_transmit_method__send_through_http
msgid "Enable send eBill"
msgstr ""
#. module: account_invoice_export
#: model_terms:ir.ui.view,arch_db:account_invoice_export.exception_sending_invoice
msgid "Error sending invoice to"
msgstr ""
#. module: account_invoice_export
#. odoo-python
#: code:addons/account_invoice_export/models/account_move.py:0
#, python-format
msgid "HTTP error {status_code} sending invoice to {method_name}"
msgstr ""
#. module: account_invoice_export
#: model_terms:ir.ui.view,arch_db:account_invoice_export.transmit_method_form
msgid ""
"Handling specific connection needs and/or exporting other files can be done "
"through code."
msgstr ""
#. module: account_invoice_export
#: model:ir.model.fields,field_description:account_invoice_export.field_account_bank_statement_line__invoice_export_confirmed
#: model:ir.model.fields,field_description:account_invoice_export.field_account_move__invoice_export_confirmed
#: model:ir.model.fields,field_description:account_invoice_export.field_account_payment__invoice_export_confirmed
msgid "Invoice Export Confirmed"
msgstr ""
#. module: account_invoice_export
#: model:ir.model.fields,field_description:account_invoice_export.field_account_bank_statement_line__invoice_exported
#: model:ir.model.fields,field_description:account_invoice_export.field_account_move__invoice_exported
#: model:ir.model.fields,field_description:account_invoice_export.field_account_payment__invoice_exported
msgid "Invoice Exported"
msgstr ""
#. module: account_invoice_export
#. odoo-python
#: code:addons/account_invoice_export/models/account_move.py:0
#, python-format
msgid "Invoice successfuly sent to {}"
msgstr ""
#. module: account_invoice_export
#: model:ir.model,name:account_invoice_export.model_account_move
msgid "Journal Entry"
msgstr ""
#. module: account_invoice_export
#. odoo-python
#: code:addons/account_invoice_export/models/account_move.py:0
#, python-format
msgid "Nothing done, invoice has already been exported before."
msgstr ""
#. module: account_invoice_export
#: model:ir.model.fields,field_description:account_invoice_export.field_transmit_method__destination_pwd
msgid "Password"
msgstr ""
#. module: account_invoice_export
#: model_terms:ir.ui.view,arch_db:account_invoice_export.view_move_form
msgid "Resend eBill"
msgstr ""
#. module: account_invoice_export
#: model:ir.actions.server,name:account_invoice_export.action_send_ebill
#: model_terms:ir.ui.view,arch_db:account_invoice_export.view_move_form
msgid "Send eBill"
msgstr ""
#. module: account_invoice_export
#: model_terms:ir.ui.view,arch_db:account_invoice_export.exception_sending_invoice
msgid "The failed job has the uuid"
msgstr ""
#. module: account_invoice_export
#: model:mail.activity.type,name:account_invoice_export.mail_activity_transmit_warning
msgid "Transmission Error"
msgstr ""
#. module: account_invoice_export
#: model:ir.model,name:account_invoice_export.model_transmit_method
msgid "Transmit Method of a document"
msgstr ""
#. module: account_invoice_export
#. odoo-python
#: code:addons/account_invoice_export/models/account_move.py:0
#, python-format
msgid "Transmit method is not configured to send through HTTP"
msgstr ""
#. module: account_invoice_export
#: model:ir.model.fields,field_description:account_invoice_export.field_transmit_method__destination_url
msgid "Url"
msgstr ""
#. module: account_invoice_export
#: model:ir.model.fields,field_description:account_invoice_export.field_transmit_method__destination_user
msgid "User"
msgstr ""

View file

@ -0,0 +1,156 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_invoice_export
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-08-23 12:06+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.6.2\n"
#. module: account_invoice_export
#: model:ir.model.fields,help:account_invoice_export.field_account_bank_statement_line__send_through_http
#: model:ir.model.fields,help:account_invoice_export.field_account_move__send_through_http
#: model:ir.model.fields,help:account_invoice_export.field_account_payment__send_through_http
#: model:ir.model.fields,help:account_invoice_export.field_transmit_method__send_through_http
msgid "Adds a Send eBill button on the invoice"
msgstr "Aggiunge un pulsante Invia e-fattura nella fattura"
#. module: account_invoice_export
#. odoo-python
#: code:addons/account_invoice_export/models/account_move.py:0
#, python-format
msgid "An error of type {} occured."
msgstr "Si è verificato un errore di tipo []."
#. module: account_invoice_export
#: model_terms:ir.ui.view,arch_db:account_invoice_export.transmit_method_form
msgid ""
"By default the PDF of the invoice will be sent using the connection "
"parameters below (basic authenticaiton)."
msgstr ""
"In modo predefinito il PDF della fattura verrà inviato utilizzando i "
"parametri di connessione sottostanti (autorizzazione base)."
#. module: account_invoice_export
#: model_terms:ir.ui.view,arch_db:account_invoice_export.view_move_form
msgid "Ebill has already been sent. Are you sure you want to send it again ?"
msgstr "L'e-fattura è già stata inviata. Si è sicuri di rispedirla?"
#. module: account_invoice_export
#: model:ir.model.fields,field_description:account_invoice_export.field_account_bank_statement_line__send_through_http
#: model:ir.model.fields,field_description:account_invoice_export.field_account_move__send_through_http
#: model:ir.model.fields,field_description:account_invoice_export.field_account_payment__send_through_http
#: model:ir.model.fields,field_description:account_invoice_export.field_transmit_method__send_through_http
msgid "Enable send eBill"
msgstr "Abilita invio e-fattura"
#. module: account_invoice_export
#: model_terms:ir.ui.view,arch_db:account_invoice_export.exception_sending_invoice
msgid "Error sending invoice to"
msgstr "Errore nell'invio della fattura a"
#. module: account_invoice_export
#. odoo-python
#: code:addons/account_invoice_export/models/account_move.py:0
#, python-format
msgid "HTTP error {status_code} sending invoice to {method_name}"
msgstr "Errore HTTP {status_code} nell'invio della fattura a {method_name}"
#. module: account_invoice_export
#: model_terms:ir.ui.view,arch_db:account_invoice_export.transmit_method_form
msgid ""
"Handling specific connection needs and/or exporting other files can be done "
"through code."
msgstr ""
"La gestione di esigenze specifiche di connessione e/o l'esportazione di "
"altri file può essere fatta attraverso il codice."
#. module: account_invoice_export
#: model:ir.model.fields,field_description:account_invoice_export.field_account_bank_statement_line__invoice_export_confirmed
#: model:ir.model.fields,field_description:account_invoice_export.field_account_move__invoice_export_confirmed
#: model:ir.model.fields,field_description:account_invoice_export.field_account_payment__invoice_export_confirmed
msgid "Invoice Export Confirmed"
msgstr "Esportazione fattura confermata"
#. module: account_invoice_export
#: model:ir.model.fields,field_description:account_invoice_export.field_account_bank_statement_line__invoice_exported
#: model:ir.model.fields,field_description:account_invoice_export.field_account_move__invoice_exported
#: model:ir.model.fields,field_description:account_invoice_export.field_account_payment__invoice_exported
msgid "Invoice Exported"
msgstr "Fattura esportata"
#. module: account_invoice_export
#. odoo-python
#: code:addons/account_invoice_export/models/account_move.py:0
#, python-format
msgid "Invoice successfuly sent to {}"
msgstr "Fattura inviata con successo a {}"
#. module: account_invoice_export
#: model:ir.model,name:account_invoice_export.model_account_move
msgid "Journal Entry"
msgstr "Registrazione contabile"
#. module: account_invoice_export
#. odoo-python
#: code:addons/account_invoice_export/models/account_move.py:0
#, python-format
msgid "Nothing done, invoice has already been exported before."
msgstr "Nessuna attività, la fattura è già stata esportata in precedenza."
#. module: account_invoice_export
#: model:ir.model.fields,field_description:account_invoice_export.field_transmit_method__destination_pwd
msgid "Password"
msgstr "Password"
#. module: account_invoice_export
#: model_terms:ir.ui.view,arch_db:account_invoice_export.view_move_form
msgid "Resend eBill"
msgstr "Reinvia e-fattura"
#. module: account_invoice_export
#: model:ir.actions.server,name:account_invoice_export.action_send_ebill
#: model_terms:ir.ui.view,arch_db:account_invoice_export.view_move_form
msgid "Send eBill"
msgstr "Invia e-fattura"
#. module: account_invoice_export
#: model_terms:ir.ui.view,arch_db:account_invoice_export.exception_sending_invoice
msgid "The failed job has the uuid"
msgstr "Il lavoro in errore ha uuid"
#. module: account_invoice_export
#: model:mail.activity.type,name:account_invoice_export.mail_activity_transmit_warning
msgid "Transmission Error"
msgstr "Errore di trasmissione"
#. module: account_invoice_export
#: model:ir.model,name:account_invoice_export.model_transmit_method
msgid "Transmit Method of a document"
msgstr "Metodo trasmissione di un documento"
#. module: account_invoice_export
#. odoo-python
#: code:addons/account_invoice_export/models/account_move.py:0
#, python-format
msgid "Transmit method is not configured to send through HTTP"
msgstr "Il metodo di trasmissione non è configurato per inviare attraverso HTTP"
#. module: account_invoice_export
#: model:ir.model.fields,field_description:account_invoice_export.field_transmit_method__destination_url
msgid "Url"
msgstr "URL"
#. module: account_invoice_export
#: model:ir.model.fields,field_description:account_invoice_export.field_transmit_method__destination_user
msgid "User"
msgstr "Utente"

View file

@ -0,0 +1,2 @@
from . import account_move
from . import transmit_method

View file

@ -0,0 +1,121 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
import requests
import odoo
from odoo import _, fields, models
from odoo.exceptions import UserError, except_orm
class AccountMove(models.Model):
_inherit = "account.move"
invoice_exported = fields.Boolean(copy=False)
# Usefull when the distant system does not validate the export synchronously
invoice_export_confirmed = fields.Boolean(copy=False)
send_through_http = fields.Boolean(related="transmit_method_id.send_through_http")
def export_invoice(self):
resend_invoice = self.env.context.get("resend_ebill", False)
for invoice in self:
invoice._job_export_invoice(resend_invoice)
def _job_export_invoice(self, resend_invoice=False):
"""Export ebill to external server and update the chatter."""
self.ensure_one()
if (
not resend_invoice
and self.invoice_exported
and self.invoice_export_confirmed
):
return _("Nothing done, invoice has already been exported before.")
try:
res = self._export_invoice()
except Exception as e:
values = {
"job_id": self.env.context.get("job_uuid"),
"error_detail": "",
"error_type": type(e).__name__,
"transmit_method_name": self.transmit_method_id.name,
}
if isinstance(e, except_orm):
values["error_detail"] = e.name
with odoo.api.Environment.manage():
with odoo.registry(self.env.cr.dbname).cursor() as new_cr:
# Create a new environment with new cursor database
new_env = odoo.api.Environment(
new_cr, self.env.uid, self.env.context
)
# The chatter of the invoice need to be updated, when the job fails
self.with_env(new_env).log_error_sending_invoice(values)
raise
self.log_success_sending_invoice()
return res
def _export_invoice(self):
"""Export electronic invoice to external service."""
if not self.transmit_method_id.send_through_http:
raise UserError(_("Transmit method is not configured to send through HTTP"))
file_data = self._get_file_for_transmission_method()
headers = self.transmit_method_id.get_transmission_http_header()
url = self.transmit_method_id.get_transmission_url()
# TODO: Should be configurable as a parameter
res = requests.post(url, headers=headers, files=file_data, timeout=10)
if res.status_code != 200:
raise UserError(
_(
"HTTP error {status_code} sending invoice to {method_name}".format(
status_code=res.status_code,
method_name=self.transmit_method_id.name,
)
)
)
self.invoice_exported = self.invoice_export_confirmed = True
return res.text
def _get_file_for_transmission_method(self):
"""Return the file description to send.
Use the format expected by the request library
By default returns the PDF report.
"""
report = "account.report_invoice"
pdf, _ = self.env["ir.actions.report"]._render(report, [self.id])
filename = self._get_report_base_filename().replace("/", "_") + ".pdf"
return {"file": (filename, pdf, "application/pdf")}
def log_error_sending_invoice(self, values):
"""Log an exception in invoice's chatter when sending fails.
If an exception already exists it is update otherwise a new one
is created.
"""
activity_type = "account_invoice_export.mail_activity_transmit_warning"
activity = self.activity_reschedule(
[activity_type], date_deadline=fields.Date.today()
)
if not activity:
template = "account_invoice_export.exception_sending_invoice"
message = self.env["ir.ui.view"]._render_template(template, values=values)
activity = self.activity_schedule(
activity_type, summary="Job error sending invoice", note=message
)
error_log = values.get("error_detail")
if not error_log:
error_log = _("An error of type {} occured.").format(
values.get("error_type")
)
activity.note += "<div class='mt16'><p>{}</p></div>".format(error_log)
def log_success_sending_invoice(self):
"""Log success sending invoice and clear existing exception, if any."""
self.activity_feedback(
["account_invoice_export.mail_activity_transmit_warning"],
feedback="It worked on a later try",
)
self.message_post(
body=_("Invoice successfuly sent to {}").format(
self.transmit_method_id.name
)
)

View file

@ -0,0 +1,36 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
import base64
from odoo import fields, models
class TransmitMethod(models.Model):
_inherit = "transmit.method"
send_through_http = fields.Boolean(
string="Enable send eBill", help="Adds a Send eBill button on the invoice"
)
destination_url = fields.Char(string="Url")
destination_user = fields.Char(string="User", copy=False)
destination_pwd = fields.Char(string="Password", copy=False)
def get_transmission_http_header(self):
"""Generate the HTTP header needed by the transmission method.
For now only basic authentication is implemented.
"""
self.ensure_one()
auth = "{}:{}".format(self.destination_user or "", self.destination_pwd or "")
auth64 = base64.encodebytes(auth.encode("ascii"))[:-1]
return {"Authorization": "Basic " + auth64.decode("utf-8")}
def get_transmission_url(self):
"""Returns the base url used to export.
Override it to add variable parameters.
"""
self.ensure_one()
return self.destination_url or ""

View file

@ -0,0 +1,2 @@
* Thierry Ducrest <thierry.ducrest@camptocamp.com>
* Tam (Nguyen Duc) <tamnd@trobz.com>

View file

@ -0,0 +1,3 @@
The development of this module has been financially supported by:
* Camptocamp

View file

@ -0,0 +1,6 @@
The goal of this module is to allow sending invoices in different format to external systems.
It extends the module `account_invoice_transmit_method`, adding options to configure an url and credentials (Basic Authentication).
In the UI a new button `Send ebill` send the invoice pdf to the configure url.
The actual sending of the invoice is manage by queue.job and the standard Odoo chatter on the invoice is used to inform the user on success/failure of the dispatch.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,435 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Account Invoice Export</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="account-invoice-export">
<h1 class="title">Account Invoice Export</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:ded419ed17e642aaf14f71f78778c50e6480162d6931a6431f2574ffafa15adf
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/edi/tree/16.0/account_invoice_export"><img alt="OCA/edi" src="https://img.shields.io/badge/github-OCA%2Fedi-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/edi-16-0/edi-16-0-account_invoice_export"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/edi&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>The goal of this module is to allow sending invoices in different format to external systems.</p>
<p>It extends the module <cite>account_invoice_transmit_method</cite>, adding options to configure an url and credentials (Basic Authentication).
In the UI a new button <cite>Send ebill</cite> send the invoice pdf to the configure url.</p>
<p>The actual sending of the invoice is manage by queue.job and the standard Odoo chatter on the invoice is used to inform the user on success/failure of the dispatch.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-3">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-4">Contributors</a></li>
<li><a class="reference internal" href="#other-credits" id="toc-entry-5">Other credits</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-1">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/edi/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/edi/issues/new?body=module:%20account_invoice_export%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-2">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-3">Authors</a></h2>
<ul class="simple">
<li>Camptocamp SA</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-4">Contributors</a></h2>
<ul class="simple">
<li>Thierry Ducrest &lt;<a class="reference external" href="mailto:thierry.ducrest&#64;camptocamp.com">thierry.ducrest&#64;camptocamp.com</a>&gt;</li>
<li>Tam (Nguyen Duc) &lt;<a class="reference external" href="mailto:tamnd&#64;trobz.com">tamnd&#64;trobz.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="other-credits">
<h2><a class="toc-backref" href="#toc-entry-5">Other credits</a></h2>
<p>The development of this module has been financially supported by:</p>
<ul class="simple">
<li>Camptocamp</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/TDu"><img alt="TDu" src="https://github.com/TDu.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/edi/tree/16.0/account_invoice_export">OCA/edi</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1 @@
from . import test_export_invoice

View file

@ -0,0 +1,52 @@
# Copyright 2023 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
from odoo.tests.common import TransactionCase
class CommonCase(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls.send_exception = cls.env.ref(
"account_invoice_export.mail_activity_transmit_warning"
)
cls.transmit_method = cls.env["transmit.method"].create(
{
"name": "HttpPost",
"code": "httppost",
"customer_ok": True,
"send_through_http": True,
"destination_url": "https://example.com/post",
"destination_user": "user",
"destination_pwd": "pwd",
}
)
cls.country = cls.env.ref("base.ch")
cls.customer = cls.env.ref("base.res_partner_1")
cls.account = cls.env["account.account"].search(
[("account_type", "=", "income"), ("company_id", "=", cls.env.company.id)],
limit=1,
)
cls.product = cls.env.ref("product.product_product_1")
cls.invoice_1 = cls.env["account.move"].create(
{
"partner_id": cls.customer.id,
"move_type": "out_invoice",
"transmit_method_id": cls.transmit_method.id,
"invoice_line_ids": [
(
0,
0,
{
"account_id": cls.account.id,
"product_id": cls.product.product_variant_ids[:1].id,
"name": "Product 1",
"quantity": 4.0,
"price_unit": 123.00,
},
)
],
}
)
cls.invoice_1.action_post()

View file

@ -0,0 +1,32 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
from .common import CommonCase
class TestExportAcountInvoice(CommonCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
def test_log_error_in_chatter(self):
values = {
"job_id": "13:123:123",
"send_error": 500,
"transmit_method_name": "SendMethod",
}
self.invoice_1.log_error_sending_invoice(values)
self.assertEqual(len(self.invoice_1.activity_ids), 1)
self.assertEqual(
self.invoice_1.activity_ids[0].activity_type_id, self.send_exception
)
# Multiple error only one exception message
self.invoice_1.log_error_sending_invoice(values)
self.assertEqual(len(self.invoice_1.activity_ids), 1)
# At success exception messages are cleared
self.invoice_1.log_success_sending_invoice()
self.assertEqual(len(self.invoice_1.activity_ids), 0)
def test_get_file_description(self):
res = self.invoice_1._get_file_for_transmission_method()
self.assertTrue(res["file"])

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_move_form" model="ir.ui.view">
<field name="name">Account Invoice Export on Invoice form view</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form" />
<field name="arch" type="xml">
<field name="transmit_method_id" position="after">
<field name="invoice_exported" invisible="1" />
<field name="invoice_export_confirmed" invisible="1" />
<field name="send_through_http" invisible="1" />
</field>
<button name="action_invoice_sent" position="after">
<button
name="export_invoice"
string="Send eBill"
type="object"
attrs="{'invisible':['|', '|', '|', ('send_through_http', '=', False), ('state', '!=', 'posted'), ('invoice_exported', '=', True), ('move_type', 'not in', ('out_invoice', 'out_refund'))]}"
groups="base.group_user"
class="oe_highlight"
/>
<button
name="export_invoice"
string="Resend eBill"
type="object"
attrs="{'invisible':['|', '|', '|', ('send_through_http', '=', False), ('state', '!=', 'posted'), ('invoice_exported', '=', False), ('move_type', 'not in', ('out_invoice', 'out_refund'))]}"
context="{'resend_ebill': True}"
groups="base.group_user"
class="oe_highlight"
confirm="Ebill has already been sent. Are you sure you want to send it again ?"
/>
</button>
</field>
</record>
<record id="view_invoice_tree" model="ir.ui.view">
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_invoice_tree" />
<field name="arch" type="xml">
<field name="state" position="after">
<field
name="activity_exception_decoration"
widget="activity_exception"
/>
</field>
</field>
</record>
<record model="ir.actions.server" id="action_send_ebill">
<field name="name">Send eBill</field>
<field name="model_id" ref="account.model_account_move" />
<field name="binding_model_id" ref="account.model_account_move" />
<field name="state">code</field>
<field name="code">
records.export_invoice()
</field>
</record>
</odoo>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<template id="exception_sending_invoice">
<div>
<p>Error sending invoice to <t t-out="transmit_method_name" />.</p>
<p>The failed job has the uuid <t t-out="job_id" /></p>
</div>
</template>
</odoo>

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="transmit_method_form" model="ir.ui.view">
<field name="name">Transmit Method Form view Export</field>
<field name="model">transmit.method</field>
<field
name="inherit_id"
ref="account_invoice_transmit_method.transmit_method_form"
/>
<field name="arch" type="xml">
<xpath expr="//group[@name='main']" position="after">
<group
name="export"
attrs="{'invisible': [('customer_ok', '=', False)]}"
>
<field name="send_through_http" />
<div
role="alert"
class="alert alert-info"
colspan="2"
attrs="{'invisible': [('send_through_http', '=', False)]}"
>
<p
>By default the PDF of the invoice will be sent using the connection parameters below (basic authenticaiton).</p>
<p
>Handling specific connection needs and/or exporting other files can be done through code.</p>
</div>
<field
name="destination_url"
attrs="{'invisible': [('send_through_http', '=', False)]}"
/>
<field
name="destination_user"
attrs="{'invisible': [('send_through_http', '=', False)]}"
/>
<field
name="destination_pwd"
attrs="{'invisible': [('send_through_http', '=', False)]}"
/>
</group>
</xpath>
</field>
</record>
</odoo>

View file

@ -0,0 +1,32 @@
# Architecture
```mermaid
flowchart TD
U[Users] -->|HTTP| V[Views and QWeb Templates]
V --> C[Controllers]
V --> W[Wizards Transient Models]
C --> M[Models and ORM]
W --> M
M --> R[Reports]
DX[Data XML] --> M
S[Security ACLs and Groups] -. enforces .-> M
subgraph Account_invoice_export Module - account_invoice_export
direction LR
M:::layer
W:::layer
C:::layer
V:::layer
R:::layer
S:::layer
DX:::layer
end
classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px
```
Notes
- Views include tree/form/kanban templates and report templates.
- Controllers provide website/portal routes when present.
- Wizards are UI flows implemented with `models.TransientModel`.
- Data XML loads data/demo records; Security defines groups and access.

View file

@ -0,0 +1,3 @@
# Configuration
Refer to Odoo settings for account_invoice_export. Configure related models, access rights, and options as needed.

View file

@ -0,0 +1,3 @@
# Controllers
This module does not define custom HTTP controllers.

View file

@ -0,0 +1,6 @@
# Dependencies
This addon depends on:
- [account](../../odoo-bringout-oca-ocb-account)
- [account_invoice_transmit_method](../../odoo-bringout-oca-account-invoicing-account_invoice_transmit_method)

View file

@ -0,0 +1,4 @@
# FAQ
- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged).
- Q: How to enable? A: Start server with --addon account_invoice_export or install in UI.

View file

@ -0,0 +1,7 @@
# Install
```bash
pip install odoo-bringout-oca-edi-framework-account_invoice_export"
# or
uv pip install odoo-bringout-oca-edi-framework-account_invoice_export"
```

View file

@ -0,0 +1,13 @@
# Models
Detected core models and extensions in account_invoice_export.
```mermaid
classDiagram
class account_move
class transmit_method
```
Notes
- Classes show model technical names; fields omitted for brevity.
- Items listed under _inherit are extensions of existing models.

View file

@ -0,0 +1,6 @@
# Overview
Packaged Odoo addon: account_invoice_export. Provides features documented in upstream Odoo 16 under this addon.
- Source: OCA/OCB 16.0, addon account_invoice_export
- License: LGPL-3

View file

@ -0,0 +1,3 @@
# Reports
This module does not define custom reports.

View file

@ -0,0 +1,8 @@
# Security
This module does not define custom security rules or access controls beyond Odoo defaults.
Default Odoo security applies:
- Base user access through standard groups
- Model access inherited from dependencies
- No custom row-level security rules

View file

@ -0,0 +1,5 @@
# Troubleshooting
- Ensure Python and Odoo environment matches repo guidance.
- Check database connectivity and logs if startup fails.
- Validate that dependent addons listed in DEPENDENCIES.md are installed.

View file

@ -0,0 +1,7 @@
# Usage
Start Odoo including this addon (from repo root):
```bash
python3 scripts/nix_odoo_web_server.py --db-name mydb --addon account_invoice_export
```

View file

@ -0,0 +1,3 @@
# Wizards
This module does not include UI wizards.

View file

@ -0,0 +1,43 @@
[project]
name = "odoo-bringout-oca-edi-framework-account_invoice_export"
version = "16.0.0"
description = "Account Invoice Export - "
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-ocb-account>=16.0.0",
"odoo-bringout-oca-edi-framework-account_invoice_transmit_method>=16.0.0",
"requests>=2.25.1"
]
readme = "README.md"
requires-python = ">= 3.11"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Office/Business",
]
[project.urls]
homepage = "https://github.com/bringout/0"
repository = "https://github.com/bringout/0"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.metadata]
allow-direct-references = true
[tool.hatch.build.targets.wheel]
packages = ["account_invoice_export"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]