Skip to content

Commit

Permalink
[IMP] l10n_br_delivery_nfe: nfe40 vols from stock.picking
Browse files Browse the repository at this point in the history
  • Loading branch information
DiegoParadeda committed Sep 20, 2024
1 parent 25f2c12 commit bfc19b6
Show file tree
Hide file tree
Showing 15 changed files with 590 additions and 0 deletions.
1 change: 1 addition & 0 deletions l10n_br_delivery_nfe/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from . import models
from . import wizards
7 changes: 7 additions & 0 deletions l10n_br_delivery_nfe/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@
"l10n_br_account",
"l10n_br_delivery",
"product_net_weight",
"product_brand",
],
"data": [
# Security
"security/ir.model.access.csv",
# Wizards
"wizards/stock_invoice_onshipping_view.xml",
"wizards/stock_generate_volumes_view.xml",
# Views
"views/nfe_document_view.xml",
"views/view_product_product.xml",
"views/view_product_template.xml",
"views/view_stock_picking.xml",
],
"installable": True,
"auto_install": True,
Expand Down
3 changes: 3 additions & 0 deletions l10n_br_delivery_nfe/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from . import document
from . import product_product
from . import product_template
from . import stock_picking_vol
from . import stock_picking_lacres
from . import stock_picking
137 changes: 137 additions & 0 deletions l10n_br_delivery_nfe/models/stock_picking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Copyright (C) 2024 Diego Paradeda - KMEE
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models


class StockPicking(models.Model):
_inherit = "stock.picking"

has_vol = fields.Boolean(
string="Has Vol IDs",
help="Technical Field: Indicates if the picking has already generated Volume IDs.",
copy=False,
)

vol_ids = fields.One2many(
string="Volume Data",
comodel_name="stock.picking.vol",
inverse_name="picking_id",
copy=False,
)

number_of_volumes = fields.Integer(
string="Number of Volumes",
default=0,
copy=False,
)

def _get_volume_data_package_level(self):
"""Generate a single volume for packages"""
vols_data = []
for picking_id in self:
if picking_id.package_ids:
for package_level_id in picking_id.package_level_ids:
manual_weight = package_level_id.package_id.shipping_weight
vol_data = {
"nfe40_qVol": 1,
"nfe40_esp": "",
"nfe40_marca": "",
"nfe40_pesoL": 0,
"nfe40_pesoB": (manual_weight if manual_weight else 0),
"picking_id": picking_id.id,
}

for line in package_level_id.move_line_ids:
vol_data["nfe40_esp"] = (
vol_data["nfe40_esp"] or line.product_id.product_volume_type
)
product_nfe40_marca = (
line.product_id.product_brand_id.name
if line.product_id.product_brand_id
else ""
)
vol_data["nfe40_marca"] = (
vol_data["nfe40_marca"] or product_nfe40_marca
)
pesoL = line.qty_done * line.product_id.net_weight
pesoB = line.qty_done * line.product_id.weight
vol_data["nfe40_pesoL"] += pesoL
vol_data["nfe40_pesoB"] += 0 if manual_weight else pesoB
vols_data.append(vol_data)

return vols_data

def _get_volume_data_wo_package(self):
"""Generate a single volume for lines without package"""
vols_data = []
for picking_id in self:
# Filter out move lines with in a package
if not picking_id.move_line_ids_without_package.filtered(
lambda ml: not ml.package_level_id
):
continue

new_vol = {
"nfe40_qVol": 0,
"nfe40_esp": "",
"nfe40_marca": "",
"nfe40_pesoL": 0,
"nfe40_pesoB": 0,
"picking_id": picking_id.id,
}

for line in picking_id.move_line_ids_without_package.filtered(
lambda ml: not ml.package_level_id and not ml.result_package_id
):
new_vol["nfe40_qVol"] += line.qty_done
new_vol["nfe40_esp"] = (
new_vol["nfe40_esp"] or line.product_id.product_volume_type
)
product_nfe40_marca = (
line.product_id.product_brand_id.name
if line.product_id.product_brand_id
else ""
)
new_vol["nfe40_marca"] = new_vol["nfe40_marca"] or product_nfe40_marca
pesoL = line.qty_done * line.product_id.net_weight
pesoB = line.qty_done * line.product_id.weight
new_vol["nfe40_pesoL"] += pesoL
new_vol["nfe40_pesoB"] += pesoB

new_vol["nfe40_qVol"] = f"{new_vol['nfe40_qVol']:.0f}"
vols_data.append(new_vol)

return vols_data

def _get_pre_generated_volumes(self):
"""Retreive and convert already generated volumes that are stored on picking"""
vols_data = []
for picking_id in self:
for vol_id in picking_id.vol_ids:
vol_data = vol_id.copy_data()[0]
vols_data.append(vol_data)
return vols_data

def prepare_vols_data_from_picking(self):
pre_generated_pickings = self.filtered(lambda p: p.has_vol)
to_generate_pickings = self.filtered(lambda p: not p.has_vol)

vols_data = []
vols_data += pre_generated_pickings._get_pre_generated_volumes()
vols_data += to_generate_pickings._get_volume_data_package_level()
vols_data += to_generate_pickings._get_volume_data_wo_package()
return vols_data

def _compute_number_of_volumes(self):
for picking in self:
if len(picking.invoice_ids) == 1:
picking.number_of_volumes = sum(
[
float(v)
for v in picking.invoice_ids.mapped(
"fiscal_document_id.nfe40_vol.nfe40_qVol"
)
]
)
else:
picking.number_of_volumes = 0
23 changes: 23 additions & 0 deletions l10n_br_delivery_nfe/models/stock_picking_lacres.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright (C) 2024 Diego Paradeda - KMEE
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from odoo import fields, models


class StockPickingLacres(models.Model):
_name = "stock.picking.lacres"
_description = "lacres"
# _inherit = "nfe.40.lacres"

"""
NFe40 fields start
##################
this section copies fields from nfe.40.vol
sadly, _name/_inherit breaks spec_model
"""
nfe40_lacres_vol_id = fields.Many2one(comodel_name="stock.picking.vol")
nfe40_nLacre = fields.Char(string="Número dos Lacres")
"""
NFe40 fields end
################
"""
52 changes: 52 additions & 0 deletions l10n_br_delivery_nfe/models/stock_picking_vol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright (C) 2024 Diego Paradeda - KMEE
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from odoo import fields, models


class StockPickingVol(models.Model):
_name = "stock.picking.vol"
_description = "Volume Data"
# _inherit = "nfe.40.vol"

"""
NFe40 fields start
##################
this section copies fields from nfe.40.vol
sadly, _name/_inherit breaks spec_model
TODO: learn how to inherit nfe mixin (https://github.com/OCA/l10n-brazil/pull/3091)
"""
nfe40_vol_transp_id = fields.Many2one(comodel_name="nfe.40.transp")
nfe40_qVol = fields.Char(string="Quantidade de volumes transportados")
nfe40_esp = fields.Char(string="Espécie dos volumes transportados")
nfe40_marca = fields.Char(string="Marca dos volumes transportados")
nfe40_nVol = fields.Char(string="Numeração dos volumes transportados")

nfe40_pesoL = fields.Float(
string="Peso líquido (em kg)",
digits=(
12,
3,
),
)

nfe40_pesoB = fields.Float(
string="Peso bruto (em kg)",
digits=(
12,
3,
),
)

nfe40_lacres = fields.One2many(
"stock.picking.lacres", "nfe40_lacres_vol_id", string="lacres"
)
"""
NFe40 fields end
################
"""

picking_id = fields.Many2one(
comodel_name="stock.picking",
string="Stock Picking",
)
6 changes: 6 additions & 0 deletions l10n_br_delivery_nfe/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
l10n_br_delivery_nfe_onshipping_vol,l10n_br_delivery_nfe.onshipping_vol,l10n_br_delivery_nfe.model_stock_invoice_onshipping_vol,stock.group_stock_user,1,1,1,1
l10n_br_delivery_nfe_onshipping_lacres,l10n_br_delivery_nfe.onshipping_lacres,l10n_br_delivery_nfe.model_stock_invoice_onshipping_lacres,stock.group_stock_user,1,1,1,1
l10n_br_delivery_nfe_stock_generate_volumes,l10n_br_delivery_nfe.stock_generate_volumes,l10n_br_delivery_nfe.model_stock_generate_volumes,stock.group_stock_user,1,1,1,1
l10n_br_delivery_nfe_stock_picking_vol,l10n_br_delivery_nfe.stock_picking_vol,l10n_br_delivery_nfe.model_stock_picking_vol,stock.group_stock_user,1,1,1,1
l10n_br_delivery_nfe_stock_picking_lacres,l10n_br_delivery_nfe.stock_picking_lacres,l10n_br_delivery_nfe.model_stock_picking_lacres,stock.group_stock_user,1,1,1,1
57 changes: 57 additions & 0 deletions l10n_br_delivery_nfe/views/view_stock_picking.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<odoo>
<record id="view_picking_withcarrier_out_form_inherit" model="ir.ui.view">
<field name="model">stock.picking</field>
<field name="inherit_id" ref="delivery.view_picking_withcarrier_out_form" />
<field name="arch" type="xml">

<xpath expr="//group[@name='carrier_data']" position="inside">
<field
name="number_of_volumes"
attrs="{'invisible': [('invoice_ids', '=', [])]}"
/>
</xpath>

<xpath expr="//notebook" position="before">
<field name="has_vol_ids" invisible="1" />
</xpath>

<xpath expr="//button[@name='action_toggle_is_locked']" position="before">
<button
name="%(action_generate_volume_ids)d"
string="Create Volumes"
attrs="{'invisible': ['|', ('state', '!=', 'done'), ('has_vol_ids', '=', True)]}"
type="action"
class="btn-primary"
groups="base.group_user"
/>
</xpath>

<xpath expr="//notebook" position="inside">
<page
name="volumes"
string="Volumes"
attrs="{'invisible': [('has_vol_ids', '=', False)]}"
>

<group string="Volumes">
<group>
<field name="number_of_volumes" />
</group>
<field name="vol_ids" nolabel="1">
<tree>
<field name="nfe40_qVol" string="Qt Vol" />
<field name="nfe40_esp" string="Esp." />
<field name="nfe40_marca" string="Marca" />
<field name="nfe40_nVol" string="N. Vol." />
<field name="nfe40_pesoL" string="Peso L." />
<field name="nfe40_pesoB" string="Peso B." />
</tree>
</field>
</group>

</page>
</xpath>

</field>
</record>
</odoo>
3 changes: 3 additions & 0 deletions l10n_br_delivery_nfe/wizards/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import vol_stock_invoice_onshipping
from . import stock_invoice_onshipping
from . import stock_generate_volumes
71 changes: 71 additions & 0 deletions l10n_br_delivery_nfe/wizards/stock_generate_volumes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Copyright (C) 2024 Diego Paradeda - KMEE
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from odoo import _, api, fields, models
from odoo.exceptions import UserError


class StockGenerateVolumes(models.TransientModel):
"""
This wizard allows for the pre-generation of picking volumes. If triggered, the
field 'stock_picking.field_vol_ids' will be populated and later replicated in the
'nfe40_vol' field.
If not triggered, the volumes will be automatically generated during the invoice
creation process (in 'stock.invoice.onshipping').
"""

_name = "stock.generate.volumes"
_description = "Stock Generate Volumes"

vol_ids = fields.One2many(
string="Volume Data",
comodel_name="stock.invoice.onshipping.vol",
inverse_name="generate_vols_wizard_id",
)

def _load_picking_id(self):
picking_obj = self.env["stock.picking"]
active_ids = self.env.context.get("active_ids", [])
picking_id = picking_obj.browse(active_ids)[0]
if not picking_id:
raise UserError(_("No picking to generate vols!"))
return picking_id

@api.model
def default_get(self, fields_list):
"""
Inherit to add default vol_ids
:param fields_list: list of str
:return: dict
"""
result = super().default_get(fields_list)

picking_id = self._load_picking_id()
vols_data = picking_id.prepare_vols_data_from_picking()
vol_ids = [(0, 0, vol) for vol in vols_data]

result["vol_ids"] = vol_ids
return result

def action_generate(self):
"""
Launch the volume generation
:return:
"""
self.ensure_one()
picking_id = self._load_picking_id()

# Update the volume generation state on pickings
picking_id.has_vol = True

volume_data = []
for vol_id in self.vol_ids:
vol_data = vol_id.copy_data({"picking_id": picking_id.id})[0]
vol_data.pop("invoice_wizard_id", None)
vol_data.pop("generate_vols_wizard_id", None)
volume_data.append(vol_data)

new_picks = picking_id.vol_ids.create(volume_data)
picking_id.number_of_volumes = sum(
[float(v) for v in new_picks.mapped("nfe40_qVol")]
)
Loading

0 comments on commit bfc19b6

Please sign in to comment.