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

[12.0][BPRT] edi_storage_oca: Backport from 14.0 #970

Open
wants to merge 71 commits into
base: 12.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
1c9f863
Add edi_storage
simahawk Nov 27, 2020
d771a55
edi_storage: add base tests for component
simahawk Nov 27, 2020
0981a9c
edi_storage: fix messages test isolation
simahawk Nov 29, 2020
07f6a7d
[UPD] Update edi_storage.pot
oca-travis Nov 30, 2020
f75847a
edi_storage 13.0.1.1.0
OCA-git-bot Nov 30, 2020
999fc5c
edi_storage: adapt to edi api changes
simahawk Dec 2, 2020
0b1372a
edi_storage 13.0.1.2.0
OCA-git-bot Dec 2, 2020
40482bc
edi_storage: put ack handling on hold
simahawk Dec 2, 2020
c988f15
edi_storage 13.0.1.3.0
OCA-git-bot Dec 2, 2020
3fe14cf
edi_storage: adapt to new components lookup
simahawk Feb 8, 2021
d7c9902
edi_storage 13.0.1.4.0
OCA-git-bot Mar 10, 2021
c9cac46
[CHG] edi: Use more permissive licence: AGPL-> LGPL
etobella Mar 10, 2021
c6975d9
[UPD] README.rst
OCA-git-bot Mar 15, 2021
2d8efda
edi_storage 13.0.1.4.1
OCA-git-bot Mar 15, 2021
5199a4b
[FIX] edi_storage: sort key was not working properly
etobella Apr 7, 2021
c541d77
edi_storage 13.0.1.5.0
OCA-git-bot Apr 9, 2021
4555d85
[IMP] edi_storage_oca: isort, black, prettier.
fshah-initos May 5, 2021
1112bb3
[MIG] Migrate module edi_storage_oca to v14.
fshah-initos May 5, 2021
5fc567f
[UPD] Update edi_storage_oca.pot
oca-travis May 27, 2021
afae839
[UPD] README.rst
OCA-git-bot May 27, 2021
b78b648
[IMP] edi_storage_oca: implement basis of the input process.
LoisRForgeFlow Jun 22, 2021
f6fe96e
[FIX] edi_oca: show the exchange file name while there is no file yet.
LoisRForgeFlow Jun 22, 2021
bc561db
edi_storage: improve input process
simahawk Jun 23, 2021
32bb19b
[FIX] edi_storage_oca: support the use or not of filename patern + sm…
LoisRForgeFlow Jun 23, 2021
9c16b91
[IMP] edi_storage_oca: add specific channel and job function definitions
LoisRForgeFlow Jul 1, 2021
967a7bd
[FIX] edi_storage_oca: support regex pattern searching when fetching …
LoisRForgeFlow Jul 1, 2021
e5f04f8
[FIX] edi_storage: consider if the exchange type has a specific backe…
LoisRForgeFlow Jul 2, 2021
b6731c5
[IMP] : black, isort, prettier
LoisRForgeFlow Jul 5, 2021
8e27039
[UPD] Update edi_storage_oca.pot
oca-travis Jul 6, 2021
476489a
[UPD] README.rst
OCA-git-bot Jul 6, 2021
2017c44
edi_storage_oca 14.0.1.1.0
OCA-git-bot Jul 6, 2021
49d83b8
[IMP] edi_storage: add listener to move files to done/error dirs
LoisRForgeFlow Jul 5, 2021
8171cc5
[FIX] edi_storage: `list_files` expects a string.
LoisRForgeFlow Jul 9, 2021
a495a36
edi_storage_oca 14.0.1.2.0
OCA-git-bot Jul 14, 2021
7c6d281
[14.0][FIX] edi_storage_oca: remove duplicate backend_type_id field i…
JordiMForgeFlow Aug 4, 2021
df266a8
edi_storage_oca 14.0.1.2.1
OCA-git-bot Aug 4, 2021
c9f24bc
[FIX] edi_storage: incorrect call to output checker in receive compon…
LoisRForgeFlow Sep 6, 2021
8ca9afd
edi_storage_oca 14.0.1.2.2
OCA-git-bot Oct 1, 2021
439a2b5
edi: improve backend view extension
simahawk Sep 17, 2021
a169044
[UPD] Update edi_storage_oca.pot
oca-travis Oct 13, 2021
e0e9d13
edi_storage_oca 14.0.1.3.0
OCA-git-bot Oct 13, 2021
1137766
edi: load main vars at init
simahawk Sep 22, 2021
fd0ff28
edi_storage: fix find files test
simahawk Oct 30, 2021
e3dddda
edi_storage_oca 14.0.1.4.0
OCA-git-bot Nov 2, 2021
e823baa
edi: get rid of name, use identifier
simahawk Mar 10, 2022
fb26946
edi_storage: fail gracefully w/o error report
simahawk Mar 10, 2022
282df2f
edi_storage_oca 14.0.1.5.0
OCA-git-bot Mar 19, 2022
d36b276
edi_storage_oca: improve error handling
jcoux May 17, 2022
7403aa3
edi_storage_oca 14.0.1.5.1
OCA-git-bot May 19, 2022
6f4e400
edi_storage: path configurable by type and param
simahawk May 6, 2022
4970f93
[IMP] edi_storage_oca: Update development status
JasminSForgeFlow Apr 12, 2022
206f1fd
[UPD] README.rst
OCA-git-bot Jul 13, 2022
c519050
edi_storage_oca 14.0.1.5.2
OCA-git-bot Jul 13, 2022
6bee8ce
edi_storage_oca 14.0.1.6.0
OCA-git-bot Jul 28, 2022
747d63a
edi: fix _cron_check_output_exchange_sync
simahawk Aug 28, 2022
68c98c5
edi_storage_oca 14.0.1.7.0
OCA-git-bot Aug 29, 2022
3786472
edi_storage: adapt _check_output_exchange_sync override
simahawk Sep 6, 2022
12eb44d
edi_storage_oca 14.0.1.8.0
OCA-git-bot Sep 6, 2022
97cd544
[IMP] edi_storage_oca: Delete processed files if you want it
etobella Feb 7, 2023
a1c693e
[UPD] Update edi_storage_oca.pot
Feb 15, 2023
a1efc45
edi_storage_oca 14.0.1.8.1
OCA-git-bot Feb 15, 2023
ec0c82e
[UPD] README.rst
OCA-git-bot Sep 3, 2023
18d26de
Added translation using Weblate (Spanish)
Ivorra78 Nov 20, 2023
4df00c6
Translated using Weblate (Spanish)
Ivorra78 Nov 20, 2023
216bc1e
[IMP] edi_storage_oca: black, isort, prettier
thienvh332 Apr 15, 2024
45c2f9f
Add edi_storage
simahawk Nov 27, 2020
8edb534
edi_storage: add base tests for component
simahawk Nov 27, 2020
88ee7e3
[BPRT] edi_storage_oca: Backport from 14.0
thienvh332 Apr 17, 2024
a69182f
[IMP] edi_storage_oca: Fix permission
tuantrantg Mar 26, 2024
7f4cce9
[DON'T MERGE] Add test-requirements.txt
thienvh332 Apr 17, 2024
f070e47
account_invoice_*facturx: fix factur-x lib version
simahawk Dec 4, 2024
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
114 changes: 114 additions & 0 deletions edi_storage_oca/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
===========================
EDI Storage backend support
===========================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:58511c29ba3a21a1216a155c53ffb1da90ba5561d407af23213e4207b9a0bcaf
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |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-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fedi-lightgray.png?logo=github
:target: https://github.com/OCA/edi/tree/12.0/edi_storage_oca
:alt: OCA/edi
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/edi-12-0/edi-12-0-edi_storage_oca
: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=12.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

Allow exchange files using storage backends from `OCA/storage`.

This module adds a storage backend relation on the EDI backend.
There you can configure the backend to be used (most often and SFTP)
and the paths where to read or put files.

Often the convention when exchanging files via SFTP
is to have one input forder (to receive files)
and an output folder (to send files).

Inside this folder you have this hierarchy::

input/output folder
|- pending
|- done
|- error

* `pending` folder contains files that have been just sent
* `done` folder contains files that have been processes successfully
* `error` folder contains files with errors and cannot be processed

The storage handlers take care of reading files and putting files
in/from the right place and update exchange records data accordingly.

**Table of contents**

.. contents::
:local:

Usage
=====

Go to "EDI -> EDI backend" then configure your backend to use a storage backend.

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:%20edi_storage_oca%0Aversion:%2012.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
~~~~~~~

* ACSONE

Contributors
~~~~~~~~~~~~

* Simone Orsi <[email protected]>
* Foram Shah <[email protected]>
* Lois Rilo <[email protected]>
* `Trobz <https://trobz.com>`_:

* Thien <[email protected]>


Other credits
~~~~~~~~~~~~~

The backport of this module from 14.0 to 12.0 was 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.

This module is part of the `OCA/edi <https://github.com/OCA/edi/tree/12.0/edi_storage_oca>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
2 changes: 2 additions & 0 deletions edi_storage_oca/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import components
from . import models
24 changes: 24 additions & 0 deletions edi_storage_oca/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2020 ACSONE
# @author: Simone Orsi <[email protected]>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

{
"name": "EDI Storage backend support",
"summary": """
Base module to allow exchanging files via storage backend (eg: SFTP).
""",
"version": "12.0.1.0.1",
"development_status": "Beta",
"license": "LGPL-3",
"website": "https://github.com/OCA/edi",
"author": "ACSONE,Odoo Community Association (OCA)",
"depends": ["edi_oca", "storage_backend", "component"],
"data": [
"data/cron.xml",
"data/job_channel_data.xml",
"data/queue_job_function_data.xml",
"security/ir_model_access.xml",
"views/edi_backend_views.xml",
],
"demo": ["demo/edi_backend_demo.xml"],
}
5 changes: 5 additions & 0 deletions edi_storage_oca/components/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from . import base
from . import check
from . import send
from . import receive
from . import listener
99 changes: 99 additions & 0 deletions edi_storage_oca/components/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Copyright 2020 ACSONE
# Copyright 2022 Camptocamp
# @author: Simone Orsi <[email protected]>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
import logging
from pathlib import PurePath

from odoo.addons.component.core import AbstractComponent

_logger = logging.getLogger(__file__)


class EDIStorageComponentMixin(AbstractComponent):

_name = "edi.storage.component.mixin"
_inherit = "edi.component.mixin"
# Components having `_storage_backend_type` will have precedence.
# If the value is not set, generic components will be used.
_storage_backend_type = None

@classmethod
def _component_match(cls, work, usage=None, model_name=None, **kw):
res = super()._component_match(work, usage=usage, model_name=model_name, **kw)
storage_type = kw.get("storage_backend_type")
if storage_type and cls._storage_backend_type:
return cls._storage_backend_type == storage_type
return res

@property
def storage(self):
return self.backend.storage_id

def _dir_by_state(self, direction, state):
"""Return remote directory path by direction and state.

:param direction: string stating direction of the exchange
:param state: string stating state of the exchange
:return: PurePath object
"""
assert direction in ("input", "output")
assert state in ("pending", "done", "error")
return PurePath(
(self.backend[direction + "_dir_" + state] or "").strip().rstrip("/")
)

def _remote_file_path(self, direction, state, filename):
"""Return remote file path by direction and state for give filename.

:param direction: string stating direction of the exchange
:param state: string stating state of the exchange
:param filename: string for file name
:return: PurePath object
"""
_logger.warning(
"Call of deprecated function `_remote_file_path`. "
"Please use `_get_remote_file_path` instead.",
)
return self._dir_by_state(direction, state) / filename.strip("/ ")

def _get_remote_file_path(self, state, filename=None):
"""Retrieve remote path for current exchange record."""
filename = filename or self.exchange_record.exchange_filename
direction = self.exchange_record.direction
directory = self._dir_by_state(direction, state).as_posix()
path = self.exchange_record.type_id._storage_fullpath(
directory=directory, filename=filename
)
return path

def _get_remote_file(self, state, filename=None, binary=False):
"""Get file for current exchange_record in the given destination state.

:param state: string ("pending", "done", "error")
:param filename: custom file name, exchange_record filename used by default
:return: remote file content as string
"""
path = self._get_remote_file_path(state, filename=filename)
try:
# TODO: support match via pattern (eg: filename-prefix-*)
# otherwise is impossible to retrieve input files and acks
# (the date will never match)
return self.storage.sudo().get(path.as_posix(), binary=binary)
except FileNotFoundError:
_logger.info(
"Ignored FileNotFoundError when trying "
"to get file %s into path %s for state %s",
filename,
path,
state,
)
return None
except OSError:
_logger.info(
"Ignored OSError when trying to get file %s into path %s for state %s",
filename,
path,
state,
)
return None
92 changes: 92 additions & 0 deletions edi_storage_oca/components/check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Copyright 2020 ACSONE
# @author: Simone Orsi <[email protected]>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

import logging

from odoo.tools import pycompat

from odoo.addons.component.core import Component

_logger = logging.getLogger(__name__)


class EDIStorageCheckComponentMixin(Component):

_name = "edi.storage.component.check"
_inherit = [
"edi.component.check.mixin",
"edi.storage.component.mixin",
]
_usage = "storage.check"

def check(self):
return self._exchange_output_check()

def _exchange_output_check(self):
"""Check status output exchange and update record.

1. check if the file has been processed already (done)
2. if yes, post message and exit
3. if not, check for errors
4. if no errors, return

:return: boolean
* False if there's nothing else to be done
* True if file still need action
"""
if self._get_remote_file("done"):
_logger.info(
"%s done",
self.exchange_record.identifier,
)
if (
not self.exchange_record.edi_exchange_state
== "output_sent_and_processed"
):
self.exchange_record.edi_exchange_state = "output_sent_and_processed"
self.exchange_record._notify_done()
return False

error = self._get_remote_file("error")
if error:
_logger.info(
"%s error",
self.exchange_record.identifier,
)
# Assume a text file will be placed there w/ the same name and error suffix
err_filename = self.exchange_record.exchange_filename + ".error"
error_report = (
self._get_remote_file("error", filename=err_filename) or "no-report"
)
if self.exchange_record.edi_exchange_state == "output_sent":
self.exchange_record.update(
{
"edi_exchange_state": "output_sent_and_error",
"exchange_error": pycompat.to_text(error_report),
}
)
self.exchange_record._notify_error("process_ko")
return False
return True

# FIXME: this is not used ATM -> should be refactored
# into an incoming exchange.
# The backend will look for records needing an ack
# and generate and ack record.
def _exchange_output_handle_ack(self):
ack_type = self.exchange_record.type_id.ack_type_id
filename = ack_type._make_exchange_filename(self.exchange_record)
ack_file = self._get_remote_file("done", filename=filename)
if ack_file:
self.backend.create_record(
ack_type.code,
{
"parent_id": self.exchange_record.id,
"exchange_file": ack_file,
"edi_exchange_state": "input_received",
},
)
self.exchange_record._notify_ack_received()
else:
self.exchange_record._notify_ack_missing()
Loading
Loading