From 5a3b3772aa3054d84871a1ef79e41989e151e65f Mon Sep 17 00:00:00 2001 From: snt Date: Fri, 20 Sep 2024 16:11:57 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20liquidaciones.=20Cambia=20los=20creates?= =?UTF-8?q?=20a=20multi=20para=20evitar=20el=20warning.=20A=C3=B1ade=20cam?= =?UTF-8?q?pos=20is=20desit=20y=20=C3=BAltima=20fecha=20de=20liquidaci?= =?UTF-8?q?=C3=B3n=20a=20purchase.order.=20Se=20asegura=20de=20linkar=20la?= =?UTF-8?q?=20l=C3=ADnea=20de=20invoice=20con=20la=20l=C3=ADnea=20de=20pur?= =?UTF-8?q?chase=20order.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../models/purchase_order.py | 63 +++++--- stock_picking_deposito/models/res_partner.py | 152 +++++++++--------- .../models/stock_picking.py | 11 +- .../views/purchase_order.xml | 9 +- .../views/view_res_partner.xml | 4 +- 5 files changed, 138 insertions(+), 101 deletions(-) diff --git a/stock_picking_deposito/models/purchase_order.py b/stock_picking_deposito/models/purchase_order.py index 6c15c69..8ae1845 100644 --- a/stock_picking_deposito/models/purchase_order.py +++ b/stock_picking_deposito/models/purchase_order.py @@ -2,34 +2,33 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import models, fields, api -from odoo.exceptions import ValidationError, Warning +from odoo.exceptions import ValidationError -import pdb -import logging -_logger = logging.getLogger(__name__) -class PurchaseOrde(models.Model): +class PurchaseOrderDesposito(models.Model): _inherit = 'purchase.order' is_deposit = fields.Boolean( help='Éste proveedor nos deja material a depósito.', - string='Es a depósito', + string='A depósito', ) deposit_last_liquidation_date = fields.Datetime( - string='Fecha última liquidación compras', - help="Cuándo se realizó la última liquidación de compras con éste proveedor." + string='Última liquidación', + help="La fecha en la que se realizó la última liquidación de compras de éste depósito." ) - @api.model - def create(self, vals): - if self.is_deposit: - if not self.partner_id.deposit_buy_accept: - raise ValidationError("Este proveedor no suministra material en depósito, configúralo antes de crear un depósito para él.") - vals['deposit_last_liquidation_date'] = fields.datetime.now() - return super(PurchaseOrde, self).create(vals) + @api.model_create_multi + def create(self, vals_list): + pol = super().create(vals_list) + for po in pol: + if po.is_deposit: + if not po.partner_id.deposit_buy_accept: + raise ValidationError("Este proveedor no suministra material en depósito, configúralo antes de crear un depósito para él.") + po.deposit_last_liquidation_date = fields.datetime.now() + return pol - def make_liquidation_invoice(self, context = None): - invoice_obj = self.env['account.move'] + def get_products_sold_sales(self): + product_dict = {} if self.deposit_last_liquidation_date: sale_orders = self.env['sale.order'].search([ ('date_order', '>', self.deposit_last_liquidation_date), @@ -42,7 +41,6 @@ class PurchaseOrde(models.Model): ('state', 'in', ['sale', 'done']) ]) - product_dict = {} if sale_orders: sale_lines = self.env['sale.order.line'].search([ ('order_id', 'in', sale_orders.ids), @@ -62,9 +60,11 @@ class PurchaseOrde(models.Model): 'tax_ids': [(6, 0, line.product_id.supplier_taxes_id.ids)], 'quantity': line.product_uom_qty } - _logger.warning("product_dict %s", product_dict) - pdb.set_trace() - pos_orders = False + + return product_dict + + def get_products_sold_pos(self): + product_dict = {} if self.deposit_last_liquidation_date: pos_orders = self.env['pos.order'].search([ ('date_order', '>', self.deposit_last_liquidation_date), @@ -76,7 +76,6 @@ class PurchaseOrde(models.Model): ('lines.product_id', 'in', self.order_line.mapped('product_id').ids), ('state', 'in', ['invoiced', 'done']) ]) - if pos_orders: pos_lines = self.env['pos.order.line'].search([ ('order_id', 'in', pos_orders.ids), @@ -96,6 +95,12 @@ class PurchaseOrde(models.Model): 'tax_ids': [(6, 0, line.product_id.supplier_taxes_id.ids)], 'quantity': line.qty } + return product_dict + + def make_liquidation_invoice(self, context = None): + invoice_obj = self.env['account.move'] + product_dict = self.get_products_sold_sales() + product_dict |= self.get_products_sold_pos() # > Python 3.9 if not product_dict: msg = "No se ha vendido ningún producto en depósito de éste proveedor desde la última liquidación.\n\n" @@ -104,7 +109,7 @@ class PurchaseOrde(models.Model): else: msg += "Todavía no se ha realizado ninguna liquidación de compras a éste proveedor." raise ValidationError(msg) - _logger.warning("product_dict %s", product_dict) + invoice_vals = invoice_obj.default_get(invoice_obj._fields.keys()) invoice_vals.update({ 'ref': "Liquidación Compras " + self.name, @@ -117,7 +122,19 @@ class PurchaseOrde(models.Model): 'purchase_id': self.id, }) invoice = invoice_obj.create(invoice_vals) + + self.update({'invoice_ids': [(4, invoice.id)]}) + self.invoice_count = len(self.invoice_ids) self.deposit_last_liquidation_date = fields.datetime.now() + + for line in self.order_line: + if line: + invoice_line = invoice.invoice_line_ids.filtered(lambda x: x.product_id.id == line.product_id.id) + if invoice_line: + line.invoice_lines = [(4, invoice_line.id)] + + self.message_post(body="Se ha creado la liquidación de compras %s" % invoice.name) + return { 'type': 'ir.actions.act_window', 'res_model': 'account.move', diff --git a/stock_picking_deposito/models/res_partner.py b/stock_picking_deposito/models/res_partner.py index 897fedc..26b2fc6 100644 --- a/stock_picking_deposito/models/res_partner.py +++ b/stock_picking_deposito/models/res_partner.py @@ -2,71 +2,76 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo import models, fields, api -from odoo.exceptions import ValidationError, Warning +from odoo.exceptions import ValidationError class ResPartner(models.Model): - _inherit = 'res.partner' + _inherit = 'res.partner' - deposit_sale_accept = fields.Boolean( + deposit_sale_accept = fields.Boolean( string='Acepta depósitos de venta', help='Éste cliente acepta nuestro material en depósito.', - ) - deposit_buy_accept = fields.Boolean( + ) + deposit_buy_accept = fields.Boolean( string='Acepta depósitos de compra', help='Éste proveedor nos deja material a depósito.', - ) - deposit_sale_location_id = fields.Many2one( - comodel_name='stock.location', - string='Ubicación de depósito de ventas', - help="Ubicación usada para gestionar el depósito que dejamos a éste proveedor." - ) - deposit_buy_location_id = fields.Many2one( - comodel_name='stock.location', - string='Ubicación de depósito de compras', - help="Ubicación usada para gestionar el material que éste proveedor nos deja en depósito." - ) - deposit_buy_last_liquidation_date = fields.Datetime( - string='Fecha última liquidación compras', - help="Cuándo se realizó la última liquidación de compras con éste proveedor." - ) - deposit_sale_last_liquidation_date = fields.Datetime( - string='Fecha última liquidación ventas', - help="Cuándo se realizó la última liquidación de ventas con éste proveedor." - ) + ) + deposit_sale_location_id = fields.Many2one( + comodel_name='stock.location', + string='Ubicación de depósito de ventas', + help="Ubicación usada para gestionar el depósito que dejamos a éste proveedor." + ) + deposit_buy_location_id = fields.Many2one( + comodel_name='stock.location', + string='Ubicación de depósito de compras', + help="Ubicación usada para gestionar el material que éste proveedor nos deja en depósito." + ) + deposit_buy_last_liquidation_date = fields.Datetime( + string='Fecha última liquidación compras', + help="Cuándo se realizó la última liquidación de compras con éste proveedor." + ) + deposit_sale_last_liquidation_date = fields.Datetime( + string='Fecha última liquidación ventas', + help="Cuándo se realizó la última liquidación de ventas con éste proveedor." + ) - @api.model - def create(self, vals): - if vals.get('deposit_sale_accept', False) == True: - vals['deposit_sale_location_id'] = self.env['stock.location'].create({ - 'usage': 'transit', - 'name': vals.get('name'), - 'location_id': self.env.ref('stock_picking_deposito.stock_location_deposits_stock').id - }).id - if vals.get('deposit_buy_accept', False) == True: - vals['deposit_buy_location_id'] = self.env['stock.location'].create({ - 'usage': 'transit', - 'name': vals.get('name'), - 'location_id': self.env.ref('stock_picking_deposito.location_deposit_buy').id - }).id - return super().create(vals) + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + vals = self.create_single(vals) + return super().create(vals_list) + + def create_single(self, vals): + if vals.get('deposit_sale_accept', False) == True: + vals['deposit_sale_location_id'] = self.env['stock.location'].create({ + 'usage': 'transit', + 'name': vals.get('name'), + 'location_id': self.env.ref('stock_picking_deposito.stock_location_deposits_stock').id + }).id + if vals.get('deposit_buy_accept', False) == True: + vals['deposit_buy_location_id'] = self.env['stock.location'].create({ + 'usage': 'transit', + 'name': vals.get('name'), + 'location_id': self.env.ref('stock_picking_deposito.location_deposit_buy').id + }).id + return vals - def write(self, vals): - if ( vals.get('deposit_sale_accept', False) == True ) and not self.deposit_sale_location_id: - vals['deposit_sale_location_id'] = self.env['stock.location'].create({ - 'usage': 'transit', - 'name': self.name, - 'location_id': self.env.ref('stock_picking_deposito.stock_location_deposits_stock').id - }).id - if ( vals.get('deposit_buy_accept', False) == True ) and not self.deposit_buy_location_id: - vals['deposit_buy_location_id'] = self.env['stock.location'].create({ - 'usage': 'transit', - 'name': self.name, - 'location_id': self.env.ref('stock_picking_deposito.location_deposit_buy').id - }).id - return super().write(vals) + def write(self, vals): + if ( vals.get('deposit_sale_accept', False) == True ) and not self.deposit_sale_location_id: + vals['deposit_sale_location_id'] = self.env['stock.location'].create({ + 'usage': 'transit', + 'name': self.name, + 'location_id': self.env.ref('stock_picking_deposito.stock_location_deposits_stock').id + }).id + if (vals.get('deposit_buy_accept', False) == True ) and not self.deposit_buy_location_id: + vals['deposit_buy_location_id'] = self.env['stock.location'].create({ + 'usage': 'transit', + 'name': self.name, + 'location_id': self.env.ref('stock_picking_deposito.location_deposit_buy').id + }).id + return super().write(vals) - def make_liquidation_buy(self, context = None): + def make_liquidation_buy(self, context = None): invoice_obj = self.env['account.move'] search_vals = [ ('location_id', '=', self.deposit_buy_location_id.id),'|', @@ -78,26 +83,27 @@ class ResPartner(models.Model): move_lines = self.env['stock.move.line'].search(search_vals) product_list = [] for mv in move_lines: - new_prod = True - for p in product_list: - if p[2]['product_id'] == mv.product_id.id: - p[2]['debit'] += mv.qty_done * mv.product_id.standard_price - new_prod = False - break - if new_prod: - product_list.append([0, False, { - 'product_id': mv.product_id.id, - 'debit': mv.qty_done * mv.product_id.standard_price, - 'name': mv.product_id.name, - 'price_unit': mv.product_id.lst_price, - 'tax_ids' : mv.product_id.supplier_taxes_id, - } - ]) + new_prod = True + for p in product_list: + if p[2]['product_id'] == mv.product_id.id: + p[2]['debit'] += mv.qty_done * mv.product_id.standard_price + new_prod = False + break + if new_prod: + product_list.append([0, False, { + 'product_id': mv.product_id.id, + 'debit': mv.qty_done * mv.product_id.standard_price, + 'name': mv.product_id.name, + 'price_unit': mv.product_id.lst_price, + 'tax_ids' : mv.product_id.supplier_taxes_id, + }]) if len(product_list): invoice_vals = invoice_obj.default_get(invoice_obj._fields.keys()) - inv_lines = [] + if self.deposit_buy_last_liquidation_date: + invoice_vals['ref'] = "Liquidación de compras desde " + self.deposit_buy_last_liquidation_date.strftime("%Y-%m-%d %H:%M:%S") + else: + invoice_vals['ref'] = "Primera Liquidación de Compras." invoice_vals.update({ - 'ref': "Liquidación Compras " + self.deposit_buy_last_liquidation_date.strftime("%d-%m-%Y"), 'financial_type': 'payable', 'journal_id': self.env.user.company_id.deposit_journal_id.id, 'partner_id': self.id, @@ -106,6 +112,7 @@ class ResPartner(models.Model): }) invoice = invoice_obj.create(invoice_vals) self.deposit_buy_last_liquidation_date = fields.datetime.now() + self.message_post(body="Se ha creado la liquidación de compras %s" %invoice.name) views = [(self.env.ref('account.view_move_form').id, 'form')] return { 'type': 'ir.actions.act_window', @@ -122,7 +129,7 @@ class ResPartner(models.Model): msg += "Todavía no se ha realizado ninguna liquidación de compras a éste proveedor." raise ValidationError(msg) - def make_liquidation_sale(self, context = None): + def make_liquidation_sale(self, context = None): self.deposit_sale_location_id sale_order_obj = self.env['sale.order'] search_vals = [('location_id', '=', self.deposit_sale_location_id.id)] @@ -149,6 +156,7 @@ class ResPartner(models.Model): }) sale_order = self.env['sale.order'].sudo().create(so_vals) + self.message_post(body="Se ha creado la liquidación de ventas %s" %sale_order.name) views = [(self.env.ref('sale.view_order_form').id, 'form')] return { 'type': 'ir.actions.act_window', diff --git a/stock_picking_deposito/models/stock_picking.py b/stock_picking_deposito/models/stock_picking.py index 70d961f..5d8d086 100644 --- a/stock_picking_deposito/models/stock_picking.py +++ b/stock_picking_deposito/models/stock_picking.py @@ -20,13 +20,18 @@ class PickingType(models.Model): class Picking(models.Model): _inherit = 'stock.picking' - @api.model - def create(self, vals): + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + vals = self.create_single(vals) + return super().create(vals_list) + + def create_single(self, vals): if vals.get('picking_type_id'): picking_type = self.env['stock.picking.type'].browse(vals.get('picking_type_id')) if picking_type.is_deposit: self.change_dest_location(vals, picking_type.code) - return super().create(vals) + return vals def write(self, vals): if vals.get("picking_type_id"): diff --git a/stock_picking_deposito/views/purchase_order.xml b/stock_picking_deposito/views/purchase_order.xml index c1d7257..3c2acc5 100644 --- a/stock_picking_deposito/views/purchase_order.xml +++ b/stock_picking_deposito/views/purchase_order.xml @@ -19,9 +19,16 @@ class="oe_stat_button" icon="fa-calendar" help="Realiza el informe de liquidación para éste proveedor." - groups="stock.group_stock_manager" + groups="account.group_account_invoice" + attrs="{'invisible': ['|',('is_deposit', '=', False),('state', '!=', 'purchase')]}" /> + + + + + + diff --git a/stock_picking_deposito/views/view_res_partner.xml b/stock_picking_deposito/views/view_res_partner.xml index 0a998f3..c9d58e2 100644 --- a/stock_picking_deposito/views/view_res_partner.xml +++ b/stock_picking_deposito/views/view_res_partner.xml @@ -31,7 +31,7 @@ - +