From eef5f7d616f9d2e4617994a7552b1bb0e700aa41 Mon Sep 17 00:00:00 2001 From: Karthikeyan Date: Tue, 2 Apr 2024 09:56:18 +0530 Subject: [PATCH] =?UTF-8?q?BUG=20|=20Refactor.=20Negative=20Qty=20Disabled?= =?UTF-8?q?=20in=20Batchwise=20interna=E2=80=A6=20(#135)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Karthi] | BUG | Refactor. Negative Qty Disabled in Batchwise internal transfer * [Karthi] | BUG | Refactor. Negative Qty Disabled in Batchwise internal transfer * [Karthi] | BUG | Refactor. Negative Qty Disabled in Batchwise internal transfer --- bahmni_stock/models/stock_picking.py | 61 ++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/bahmni_stock/models/stock_picking.py b/bahmni_stock/models/stock_picking.py index ad2d054..4fb3de2 100644 --- a/bahmni_stock/models/stock_picking.py +++ b/bahmni_stock/models/stock_picking.py @@ -4,11 +4,72 @@ from odoo import fields, models, api from odoo.tools.float_utils import float_compare from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError, AccessError, RedirectWarning class StockPicking(models.Model): _inherit = 'stock.picking' + def button_validate(self): + # Clean-up the context key at validation to avoid forcing the creation of immediate + # transfers. + ctx = dict(self.env.context) + ctx.pop('default_immediate_transfer', None) + self = self.with_context(ctx) + ### Internal Transfer Batch based code write + if ctx['default_picking_type_id']: + stock_picking_type = self.env['stock.picking.type'].search([('id','=', ctx['default_picking_type_id'])]) + if stock_picking_type.code == 'internal': + for line in self.move_line_ids: + if line.product_id.tracking != 'none': + stock_quant_lot = self.env['stock.quant'].search([ + ('product_id','=', line.product_id.id),('location_id', '=', line.location_id.id), + ('lot_id', '=', line.lot_id.id),('quantity', '>' , 0)]) + if stock_quant_lot.quantity < line.qty_done: + raise UserError("Insufficient batch(%s) quantity for %s and available quantity is %s"\ + %(line.lot_id.name, line.product_id.name, stock_quant_lot.quantity)) + # Sanity checks. + if not self.env.context.get('skip_sanity_check', False): + self._sanity_check() + + self.message_subscribe([self.env.user.partner_id.id]) + + # Run the pre-validation wizards. Processing a pre-validation wizard should work on the + # moves and/or the context and never call `_action_done`. + if not self.env.context.get('button_validate_picking_ids'): + self = self.with_context(button_validate_picking_ids=self.ids) + res = self._pre_action_done_hook() + if res is not True: + return res + + # Call `_action_done`. + pickings_not_to_backorder = self.filtered(lambda p: p.picking_type_id.create_backorder == 'never') + if self.env.context.get('picking_ids_not_to_backorder'): + pickings_not_to_backorder |= self.browse(self.env.context['picking_ids_not_to_backorder']).filtered( + lambda p: p.picking_type_id.create_backorder != 'always' + ) + pickings_to_backorder = self - pickings_not_to_backorder + pickings_not_to_backorder.with_context(cancel_backorder=True)._action_done() + pickings_to_backorder.with_context(cancel_backorder=False)._action_done() + + if self.user_has_groups('stock.group_reception_report'): + pickings_show_report = self.filtered(lambda p: p.picking_type_id.auto_show_reception_report) + lines = pickings_show_report.move_ids.filtered(lambda m: m.product_id.type == 'product' and m.state != 'cancel' and m.quantity_done and not m.move_dest_ids) + if lines: + # don't show reception report if all already assigned/nothing to assign + wh_location_ids = self.env['stock.location']._search([('id', 'child_of', pickings_show_report.picking_type_id.warehouse_id.view_location_id.ids), ('usage', '!=', 'supplier')]) + if self.env['stock.move'].search([ + ('state', 'in', ['confirmed', 'partially_available', 'waiting', 'assigned']), + ('product_qty', '>', 0), + ('location_id', 'in', wh_location_ids), + ('move_orig_ids', '=', False), + ('picking_id', 'not in', pickings_show_report.ids), + ('product_id', 'in', lines.product_id.ids)], limit=1): + action = pickings_show_report.action_view_reception_report() + action['context'] = {'default_picking_ids': pickings_show_report.ids} + return action + return True + # this method is overridden to update cost_price, sale_price and mrp while lot is getting created def _create_lots_for_picking(self): Lot = self.env['stock.production.lot']