Skip to content
Draft
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
26 changes: 26 additions & 0 deletions edi_purchase_diapar_oca/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3

======================
EDI Purchase DIAPAR
======================

Features
--------

This module contains all specific and necessary conditions and treatments to DIAPAR relationship.


Credits
=======

Yassine TEIMI <yteimi01@gmail.com>
Simon Mas <simon.mas@druidoo.io>

Funders
-------

The development of this module has been financially supported by:

* La Louve (https://cooplalouve.fr/)
6 changes: 6 additions & 0 deletions edi_purchase_diapar_oca/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright (C) 2016-Today: Druidoo (<http://www.druidoo.io/>)
# @author: Druidoo
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html

from . import models
from . import components
39 changes: 39 additions & 0 deletions edi_purchase_diapar_oca/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright (C) 2016-Today: Druidoo (<http://www.druidoo.io/>)
# @author: Druidoo
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html

{
"name": "EDI Purchase DIAPAR",
"version": "18.0.1.0.0",
"category": "Custom",
"author": "Druidoo, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/edi-framework",
"license": "AGPL-3",
"depends": [
"product",
"purchase_stock",
"edi_storage_oca",
"edi_purchase_oca",
"edi_exchange_template_oca",
],
"data": [
"security/ir.model.access.csv",
"views/supplier_price_list_views.xml",
"views/picking_update_views.xml",
"views/product_template_views.xml",
"views/res_partner_views.xml",
"views/exchange_type_views.xml",
"views/edi_exchange_template_output.xml",
"views/res_config_settings_views.xml",
"views/menus.xml",
"templates/exchange_template_output_diapar.xml",
],
"demo": [
"demo/fs_storage_demo.xml",
"demo/edi_backend_type_demo.xml",
"demo/edi_exchange_template_output_demo.xml",
"demo/edi_exchange_type_demo.xml",
"demo/edi_field_mapping_demo.xml",
"demo/edi_configuration_demo.xml",
],
}
3 changes: 3 additions & 0 deletions edi_purchase_diapar_oca/components/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import input_process_ble
from . import input_process_ch
from . import generate_diapar_output
30 changes: 30 additions & 0 deletions edi_purchase_diapar_oca/components/generate_diapar_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from odoo import models

from odoo.addons.edi_core_oca.exceptions import EDINotImplementedError


class EdiOcaHandlerGenerate(models.AbstractModel):
_name = "edi.output.diapar.handler"
_inherit = [
"edi.oca.handler.generate",
]
_description = "EDI Handler Generate Output For Diapar"

def generate(self, exchange_record):
exchange_record = self.env["edi.exchange.record"].browse(exchange_record.id)
tmpl = exchange_record.backend_id._get_output_template(exchange_record)
if tmpl:
exchange_record = exchange_record.with_context(
edi_framework_action="generate"
)
tmpl = tmpl.with_context(edi_framework_action="generate")
if exchange_record.model == "purchase.order" and exchange_record.res_id:
order = self.env["purchase.order"].browse(exchange_record.res_id)
if order:
return order.generate_template_output_diapar(
tmpl,
exchange_record,
)
raise EDINotImplementedError(
self.env._("Only purchase order with Diapar output template are supported.")
)
195 changes: 195 additions & 0 deletions edi_purchase_diapar_oca/components/input_process_ble.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import logging

from odoo import Command, models
from odoo.exceptions import ValidationError

_logger = logging.getLogger(__name__)


class EDIInputProcessDiaparDespatchAdvice(models.AbstractModel):
"""
INPUT PROCESSOR BLE
"""

_name = "input.process.diapar.despatch.advice"
_inherit = ["edi.oca.handler.process"]
_description = "Input process despatch advice from Diapar"

def process(self, exchange_record):
_logger.info(">>>>>>>>>>>>>>>>>> Reading BLE file >>>>>>>>>>>>>>>>>>>>>")
picking_update, purchase_order = self._handle_create_picking_update(
exchange_record
)
if picking_update:
picking_update.button_update_picking_order()
if not exchange_record.related_record_ids.filtered(
lambda r: r.model == "purchase.order" and r.res_id == purchase_order.id
):
self.env["edi.exchange.related.record"].create(
{
"exchange_record_id": exchange_record.id,
"res_id": purchase_order.id,
"model": "purchase.order",
}
)
return self.env._(
"Stock Picking %s updated. Related Order: %s",
picking_update.name.name,
purchase_order.name,
)
return self.env._("No picking update created for this file.")

def _parse_file_content_ble(self, exchange_record):
datas = exchange_record._get_file_content()
return datas.split("\n")

def _get_mapping_field_position(self, exchange_type, field_name):
mapping = exchange_type.field_mapping_ids.filtered(
lambda rec: rec.mapping_field_id.name == field_name
)
pos_from = mapping.sequence_start
pos_to = mapping.sequence_end
return pos_from, pos_to

def _get_picking_order_and_supplier_info(
self, line, edi_exchange_type, picking_order, supplier_info, delivery_date
):
pos_from, pos_to = self._get_mapping_field_position(
edi_exchange_type, "product_code"
)
product_code = line[pos_from:pos_to]
purchase_order = self.env["purchase.order"]
supplier_info = self.env["product.supplierinfo"].search(
[("product_code", "=", product_code)],
limit=1,
)
supplier_ids = supplier_info.mapped("partner_id").ids
# Look for corresponding purchase order, normally it
# should be just one even if there is more than one
# supplier associated to product
if supplier_ids:
sdate = f"{delivery_date} 00:00:00"
edate = f"{delivery_date} 23:59:59"
purchase_order = self.env["purchase.order"].search(
[
("partner_id", "in", supplier_ids),
("state", "in", ["purchase", "done"]),
("date_planned", ">=", sdate),
("date_planned", "<=", edate),
],
limit=1,
)
# Assuming purchase order has only one picking order associated.
if purchase_order.exists():
picking_order = purchase_order.picking_ids[0]
return picking_order, supplier_info, purchase_order

def _get_updated_quantity_values(
self, line, edi_exchange_type, picking_order, supplier_info
):
# Look for updated quantity
pos_from, pos_to = self._get_mapping_field_position(
edi_exchange_type, "product_qty"
)
new_quantity = line[pos_from:pos_to]
# Look for ordered quantity
product_tmpl = self.env["product.template"]
if supplier_info:
product_tmpl = supplier_info[0].product_tmpl_id
ordered_product = self.env["product.product"].search(
[("product_tmpl_id", "=", product_tmpl.id)],
limit=1,
)
ordered_operation = self.env["stock.move"].search(
[
("picking_id", "=", picking_order.id),
("product_id", "=", ordered_product.id),
]
)
ordered_quantity = ordered_operation.quantity
# Construct one2many values
vals = dict()
if ordered_quantity != float(new_quantity):
vals.update(
{
"line_to_update_id": ordered_operation.id,
"product_id": ordered_product.id,
"ordered_quantity": ordered_quantity,
"product_qty": float(new_quantity),
}
)
return vals

def _reprepare_delivery_date(self, line, edi_exchange_type):
pos_from, pos_to = self._get_mapping_field_position(
edi_exchange_type, "date_planned"
)
data = line[pos_from:pos_to]
return self.env["edi.configuration"].get_date_format_ble_yyyymmdd(data)

def _prepare_picking_update_values(self, exchange_record):
lines = self._parse_file_content_ble(exchange_record)
edi_exchange_type = exchange_record.type_id

if not lines:
raise ValidationError(
self.env._(
"Please configure fields mapping for BLE interface on your"
" EDI system!"
)
)

delivery_date = delivery_sign = ""
picking_order = self.env["stock.picking"]
supplier_info = self.env["product.supplierinfo"]
purchase_order = self.env["purchase.order"]
proposition_vals = dict()
values_list = []
for line in lines:
if not line or not isinstance(line, str):
continue
# This condition ensures that this job
# consider only one picking per EDI File
line = line.lstrip()
if line.startswith(edi_exchange_type.header_code) and not delivery_date:
# Header processing
delivery_date = self._reprepare_delivery_date(line, edi_exchange_type)
elif line.startswith(edi_exchange_type.lines_code):
# Look if it's a first delivery
delivery_sign = edi_exchange_type.delivery_sign
if delivery_sign == "-":
break

# Look for picking_order, supplier_info
picking_order, supplier_info, purchase_order = (
self._get_picking_order_and_supplier_info(
line,
edi_exchange_type,
picking_order,
supplier_info,
delivery_date,
)
)
# Look for updated quantity
updated_values = self._get_updated_quantity_values(
line, edi_exchange_type, picking_order, supplier_info
)
if updated_values:
values_list += [Command.create(updated_values)]
if delivery_sign == "+":
proposition_vals.update(
{
"name": picking_order.id,
"values_proposed_ids": values_list,
}
)
return proposition_vals, purchase_order

def _handle_create_picking_update(self, exchange_record):
picking_update = self.env["picking.update"]
proposition_vals, purchase_order = self._prepare_picking_update_values(
exchange_record
)
if proposition_vals:
picking_update = picking_update.create(proposition_vals)
return picking_update, purchase_order
Loading
Loading