Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16.0][MIG] edi_account_storage #517

Merged
merged 14 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions edi_account_storage/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This module allows you to send invoices via SFTP.
2 changes: 2 additions & 0 deletions edi_account_storage/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import components
from . import models
19 changes: 19 additions & 0 deletions edi_account_storage/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "L10n Es Facturae Storage",
"summary": """
Summary""",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "CreuBlanca",
"website": "https://github.com/tegin/cb-addons",
"development_status": "Beta",
"depends": ["edi_account_oca", "edi_storage_oca", "edi_exchange_template_oca"],
"data": [
"data/edi_data.xml",
"views/res_partner.xml",
"security/ir.model.access.csv",
],
}
1 change: 1 addition & 0 deletions edi_account_storage/components/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import account_move_mail_listener
44 changes: 44 additions & 0 deletions edi_account_storage/components/account_move_mail_listener.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Copyright 2020 Creu Blanca
# @author: Enric Tobella
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo.addons.component.core import Component


class AccountMoveMailListener(Component):
_name = "account.move.storage.listener"
_inherit = "base.event.listener"
_apply_on = ["account.move"]

def _get_exchange_record_vals(self, record):
return {
"model": record._name,
"res_id": record.id,
}

def on_post_account_move(self, records):
for record in records:
if record.edi_disable_auto:
continue

Check warning on line 22 in edi_account_storage/components/account_move_mail_listener.py

View check run for this annotation

Codecov / codecov/patch

edi_account_storage/components/account_move_mail_listener.py#L22

Added line #L22 was not covered by tests
partner = record.partner_id
if record.move_type not in ["out_invoice", "out_refund"]:
continue
if not partner.account_invoice_storage_exchange_type_id:
continue
backend = partner.account_invoice_storage_exchange_type_id.backend_id
if not backend:
continue

Check warning on line 30 in edi_account_storage/components/account_move_mail_listener.py

View check run for this annotation

Codecov / codecov/patch

edi_account_storage/components/account_move_mail_listener.py#L30

Added line #L30 was not covered by tests
exchange_type = partner.account_invoice_storage_exchange_type_id.code
if record._has_exchange_record(exchange_type, backend):
continue

Check warning on line 33 in edi_account_storage/components/account_move_mail_listener.py

View check run for this annotation

Codecov / codecov/patch

edi_account_storage/components/account_move_mail_listener.py#L33

Added line #L33 was not covered by tests
exchange_record = backend.create_record(
exchange_type, self._get_exchange_record_vals(record)
)
if record.partner_id.account_invoice_storage_clean_file_name:
filename = exchange_record.exchange_filename
exchange_record.exchange_filename = filename.replace("/", "-")

Check warning on line 39 in edi_account_storage/components/account_move_mail_listener.py

View check run for this annotation

Codecov / codecov/patch

edi_account_storage/components/account_move_mail_listener.py#L38-L39

Added lines #L38 - L39 were not covered by tests
backend.exchange_generate(exchange_record)
backend.exchange_send(exchange_record)

def on_generate_account_edi(self, records):
return self.on_post_account_move(records)

Check warning on line 44 in edi_account_storage/components/account_move_mail_listener.py

View check run for this annotation

Codecov / codecov/patch

edi_account_storage/components/account_move_mail_listener.py#L44

Added line #L44 was not covered by tests
7 changes: 7 additions & 0 deletions edi_account_storage/data/edi_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" ?>
<odoo noupdate="1">
<record id="backend_type" model="edi.backend.type">
<field name="name">Move Storage Backend type</field>
<field name="code">account_move_storage</field>
</record>
</odoo>
177 changes: 177 additions & 0 deletions edi_account_storage/migrations/13.0.1.0.0/post-migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# Copyright 2020 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
from openupgradelib import openupgrade


@openupgrade.migrate()
def migrate(env, version):
integration_field_name = openupgrade.get_legacy_name("account_move_integration_id")
if not openupgrade.table_exists(env.cr, "account_move_integration"):
return
if not openupgrade.table_exists(env.cr, "account_move_integration_method"):
return
if not openupgrade.column_exists(
env.cr, "edi_exchange_record", integration_field_name
):
openupgrade.logged_query(
env.cr,
"""
ALTER TABLE edi_exchange_record
ADD COLUMN %s numeric"""
% integration_field_name,
)
openupgrade.logged_query(
env.cr,
"SELECT id from account_move_integration_method where code = 'storage'",
)
data = env.cr.fetchall()
if not data:
return
method_id = data[0][0]
backend_type = env.ref("edi_account_storage.backend_type")

openupgrade.logged_query(
env.cr,
"""
SELECT
rp.id,
rp.account_integration_report_id,
rp.account_integration_storage_id,
rp.account_integration_filename_pattern
FROM res_partner rp, account_move_integration_method_res_partner_rel amimrpr
WHERE rp.l10n_es_facturae_sending_code is NULL
AND amimrpr.res_partner_id = rp.id
AND amimrpr.account_move_integration_method_id = {method_id}
""".format(
method_id=method_id
),
)
for x in env.cr.fetchall():
partner = env["res.partner"].browse(x[0])
backend = env["edi.backend"].create(
{
"name": "EDI backend for %s" % partner.name,
"backend_type_id": backend_type.id,
"storage_id": x[2],
}
)

exchange_type = env["edi.exchange.type"].create(
{
"name": "Storage Invoice Exchange type for %s" % partner.name,
"backend_type_id": backend_type.id,
"backend_id": backend.id,
"code": "edi_account_storage_partner_%s" % partner.id,
"direction": "output",
"exchange_filename_pattern": x[3].replace("{invoice", "{record"),
"model_ids": [(4, env.ref("account.model_account_move").id)],
"enable_snippet": "result = not record."
"_has_exchange_record(exchange_type.code)",
}
)
exchange_type.write(
{
"enable_domain": "[('state', '!=', 'draft'), ('partner_id."
"account_invoice_storage_exchange_type_id'"
", '=', %s)]" % exchange_type.id,
}
)
env["edi.exchange.template.output"].create(
{
"name": "Storage backend for %s" % partner.name,
"backend_type_id": backend_type.id,
"backend_id": backend.id,
"type_id": exchange_type.id,
"code": "edi_account_storage_partner_template_%s" % partner.id,
"output_type": "pdf",
"generator": "report",
"report_id": x[1],
}
)
partner.account_invoice_storage_exchange_type_id = exchange_type
partner.flush()
openupgrade.logged_query(
env.cr,
"""
INSERT INTO edi_exchange_record (
{integration_field},
edi_exchange_state,
identifier,
external_identifier,
type_id,
backend_id,
exchange_filename,
create_date,
create_uid,
write_date,
write_uid,
model,
res_id,
exchanged_on,
l10n_es_facturae_status,
l10n_es_facturae_cancellation_status,
l10n_es_facturae_motive,
l10n_es_facturae_cancellation_motive
) SELECT
ami.id,
CASE WHEN ami.state in ('sent', 'cancelled') THEN 'output_sent'
WHEN ami.state = 'pending' THEN 'output_pending'
ELSE 'output_error_on_send'
END,
ami.name,
ami.register_number,
eet.id,
eet.backend_id,
ia.name,
ami.create_date,
ami.create_uid,
ami.write_date,
ami.write_uid,
'account.move',
ami.move_id,
case when ami.state = 'sent' then COALESCE(ami.update_date, ami.write_date)
END,
ami.integration_status,
ami.cancellation_status,
ami.integration_description,
ami.cancellation_description
FROM account_move_integration ami
LEFT JOIN ir_attachment ia ON ia.id = ami.attachment_id
LEFT JOIN account_move am ON am.id = ami.move_id
LEFT JOIN res_partner rp ON rp.id = am.partner_id
LEFT JOIN edi_exchange_type eet ON eet.id =
rp.account_invoice_storage_exchange_type_id
WHERE ami.method_id = {method_id}""".format(
integration_field=integration_field_name,
method_id=method_id,
),
)
openupgrade.logged_query(
env.cr,
"""
UPDATE ir_attachment at
SET res_model = 'edi.exchange.record', res_id = eer.id,
res_field = 'exchange_file'
FROM account_move_integration aii
INNER JOIN edi_exchange_record eer on eer.{integration_field} = aii.id
WHERE aii.attachment_id = at.id and aii.method_id = {method_id}
""".format(
integration_field=integration_field_name,
method_id=method_id,
),
)
openupgrade.logged_query(
env.cr,
"""
UPDATE ir_attachment at
SET res_model = 'edi.exchange.record', res_id = eer.id
FROM account_invoice_integration_ir_attachment_rel aiiia
INNER JOIN account_move_integration aii
ON aii.id = aiiia.account_invoice_integration_id
INNER JOIN edi_exchange_record eer
ON eer.{integration_field} = aii.id
WHERE aiiia.ir_attachment_id = at.id
""".format(
integration_field=integration_field_name,
),
)
1 change: 1 addition & 0 deletions edi_account_storage/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import res_partner
11 changes: 11 additions & 0 deletions edi_account_storage/models/res_partner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import fields, models


class ResPartner(models.Model):
_inherit = "res.partner"

account_invoice_storage_exchange_type_id = fields.Many2one("edi.exchange.type")
account_invoice_storage_clean_file_name = fields.Boolean()
2 changes: 2 additions & 0 deletions edi_account_storage/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_storage_backend_account,access_storage_backend_account,fs_storage.model_fs_storage,account.group_account_invoice,1,0,0,0
1 change: 1 addition & 0 deletions edi_account_storage/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_storage_integration
122 changes: 122 additions & 0 deletions edi_account_storage/tests/test_storage_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# © 2017 Creu Blanca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

from odoo.tests import common

from odoo.addons.edi_oca.tests.common import EDIBackendCommonComponentRegistryTestCase


class EDIBackendTestCase(
EDIBackendCommonComponentRegistryTestCase, common.TransactionCase
):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls._load_module_components(cls, "component_event")
cls._load_module_components(cls, "edi")
cls._load_module_components(cls, "storage")
cls._load_module_components(cls, "edi_account_oca")
cls._load_module_components(cls, "edi_storage_oca")
cls._load_module_components(cls, "edi_account_storage")
cls.tax = cls.env["account.tax"].create(
{
"name": "Test tax",
"amount_type": "percent",
"amount": 21,
"type_tax_use": "sale",
}
)
cls.storage = cls.env["fs.storage"].create(
{"name": "storage", "protocol": "odoofs", "code": "demo.fs.storage"}
)
cls.backend = cls.env["edi.backend"].create(
{
"name": "Demo Backend",
"backend_type_id": cls.env.ref("edi_account_storage.backend_type").id,
"storage_id": cls.storage.id,
}
)
cls.exchange_type = cls.env["edi.exchange.type"].create(
{
"name": "Storage backend demo",
"backend_type_id": cls.env.ref("edi_account_storage.backend_type").id,
"backend_id": cls.backend.id,
"code": "edi_account_storage_partner",
"direction": "output",
}
)
cls.env["edi.exchange.template.output"].create(
{
"name": "Storage backend demo",
"backend_type_id": cls.env.ref("edi_account_storage.backend_type").id,
"backend_id": cls.backend.id,
"type_id": cls.exchange_type.id,
"code": "edi_account_storage_partner_template",
"output_type": "pdf",
"generator": "report",
"report_id": cls.env.ref("account.account_invoices").id,
}
)
cls.partner = cls.env["res.partner"].create(
{
"name": "Cliente de prueba",
"street": "C/ Ejemplo, 13",
"zip": "13700",
"city": "Tomelloso",
"country_id": cls.env.ref("base.es").id,
"vat": "ES05680675C",
"account_invoice_storage_exchange_type_id": cls.exchange_type.id,
}
)
main_company = cls.env.ref("base.main_company")
main_company.vat = "ESA12345674"
main_company.partner_id.country_id = cls.env.ref("base.uk")
cls.sale_journal = cls.env["account.journal"].create(
{
"name": "Sale journal",
"code": "SALE_TEST",
"type": "sale",
"company_id": main_company.id,
}
)
cls.account = cls.env["account.account"].create(
{
"company_id": main_company.id,
"name": "Facturae Product account",
"code": "testproduct",
"account_type": "income",
}
)
cls.move = cls.env["account.move"].create(
{
"partner_id": cls.partner.id,
"journal_id": cls.sale_journal.id,
"invoice_date": "2016-03-12",
"move_type": "out_invoice",
"invoice_line_ids": [
(
0,
0,
{
"product_id": cls.env.ref("product.product_delivery_02").id,
"account_id": cls.account.id,
"name": "Producto de prueba",
"quantity": 1.0,
"price_unit": 100.0,
"tax_ids": [(6, 0, cls.tax.ids)],
},
)
],
}
)
cls.move.flush_recordset()

def test_send(self):
self.move.with_context(
force_edi_send=True, _edi_send_break_on_error=True
).action_post()
self.assertTrue(self.move.exchange_record_ids)
self.assertEqual(
self.move.exchange_record_ids.edi_exchange_state, "output_sent"
)
Loading
Loading