diff options
| -rw-r--r-- | indoteknik_custom/models/tukar_guling.py | 99 | ||||
| -rw-r--r-- | indoteknik_custom/views/tukar_guling.xml | 21 |
2 files changed, 65 insertions, 55 deletions
diff --git a/indoteknik_custom/models/tukar_guling.py b/indoteknik_custom/models/tukar_guling.py index a2168f5b..2c39b547 100644 --- a/indoteknik_custom/models/tukar_guling.py +++ b/indoteknik_custom/models/tukar_guling.py @@ -57,25 +57,23 @@ class TukarGuling(models.Model): line_ids = fields.One2many('tukar.guling.line', 'tukar_guling_id', string='Product Lines') mapping_koli_ids = fields.One2many('tukar.guling.mapping.koli', 'tukar_guling_id', string='Mapping Koli') - @api.constrains('mapping_koli_ids') def _check_mapping_koli(self): for record in self: if record.operations.picking_type_id.id == 29: # Only for BU/OUT if not record.mapping_koli_ids: raise UserError("❌ Mapping Koli belum diisi") - # Calculate totals as integers - total_mapping_qty = sum(int(mapping.qty_done) for mapping in record.mapping_koli_ids.qty_return) + # Calculate totals + total_mapping_qty = sum(int(mapping.qty_return) for mapping in record.mapping_koli_ids) total_line_qty = sum(int(line.product_uom_qty) for line in record.line_ids) - # Strict integer comparison if total_mapping_qty != total_line_qty: raise UserError( "❌ Total quantity return di mapping koli (%d) tidak sama dengan quantity retur product lines (%d)" % (total_mapping_qty, total_line_qty) ) else: - _logger.info("qty koli sesuai") + _logger.info("✅ Qty mapping koli sesuai dengan product lines") @api.onchange('operations') def _onchange_operations(self): @@ -107,7 +105,8 @@ class TukarGuling(models.Model): 'sequence': sequence, 'pick_id': koli_line.pick_id.id, 'product_id': pick_move.product_id.id, - 'qty_done': pick_move.qty_done + 'qty_done': pick_move.qty_done, + 'qty_return': 0 })) sequence += 10 @@ -482,47 +481,39 @@ class TukarGuling(models.Model): if not record.operations: raise UserError("BU/OUT dari field operations tidak ditemukan.") + created_returns = [] + bu_pick_to_return = record.operations.konfirm_koli_lines.pick_id bu_out_to_return = record.operations if not bu_pick_to_return and not bu_out_to_return: raise UserError("Tidak ada BU/PICK atau BU/OUT yang selesai untuk diretur.") - created_returns = [] - - # Picking types & locations srt_type = self.env['stock.picking.type'].browse(73) ort_type = self.env['stock.picking.type'].browse(74) bu_pick_type = self.env['stock.picking.type'].browse(30) bu_out_type = self.env['stock.picking.type'].browse(29) - def _create_return_from_picking(picking): + PARTNER_LOCATION_ID = 5 + BU_OUTPUT_LOCATION_ID = 60 + BU_STOCK_LOCATION_ID = 57 + + def _create_return_from_picking_grouped(picking): if not picking: return None - grup = record.operations.group_id - PARTNER_LOCATION_ID = 5 - BU_OUTPUT_LOCATION_ID = 60 - BU_STOCK_LOCATION_ID = 57 + grup = record.operations.group_id if picking.picking_type_id.id == 30: - # BU/PICK → ORT - return_type = ort_type default_location_id = BU_OUTPUT_LOCATION_ID default_location_dest_id = BU_STOCK_LOCATION_ID elif picking.picking_type_id.id == 74: - # ORT → BU/PICK - return_type = bu_pick_type default_location_id = BU_STOCK_LOCATION_ID default_location_dest_id = BU_OUTPUT_LOCATION_ID elif picking.picking_type_id.id == 29: - # BU/OUT → SRT - return_type = srt_type default_location_id = PARTNER_LOCATION_ID default_location_dest_id = BU_OUTPUT_LOCATION_ID elif picking.picking_type_id.id == 73: - # SRT → BU/OUT - return_type = bu_out_type default_location_id = BU_OUTPUT_LOCATION_ID default_location_dest_id = PARTNER_LOCATION_ID else: @@ -542,58 +533,75 @@ class TukarGuling(models.Model): 'original_location_id': default_location_id }) + # 🔥 If BU/OUT, ambil qty dari mapping koli (group by product) return_lines = [] - for line in record.line_ids: - move = picking.move_lines.filtered(lambda m: m.product_id == line.product_id) - if move: + if picking.picking_type_id.id == 29 and record.mapping_koli_ids: + grouped_qty = {} + for map_line in record.mapping_koli_ids: + pid = map_line.product_id.id + grouped_qty[pid] = grouped_qty.get(pid, 0) + map_line.qty_return + + for pid, qty in grouped_qty.items(): + move = picking.move_lines.filtered(lambda mv: mv.product_id.id == pid) + if move: + return_lines.append((0, 0, { + 'product_id': pid, + 'quantity': qty, + 'move_id': move[0].id, + })) + else: + raise UserError(_("Tidak ditemukan move line di picking %s untuk produk %s") + % (picking.name, map_line.product_id.display_name)) + else: + # Default kalau bukan BU/OUT (misalnya ORT), retur full qty done + for move in picking.move_lines: return_lines.append((0, 0, { - 'product_id': line.product_id.id, - 'quantity': line.product_uom_qty, - 'move_id': move[0].id, + 'product_id': move.product_id.id, + 'quantity': move.quantity_done or move.product_uom_qty, + 'move_id': move.id, })) - else: - raise UserError( - _("Tidak ditemukan move line di picking %s untuk produk %s") - % (picking.name, line.product_id.display_name) - ) if not return_lines: raise UserError(_("Tidak ada product line valid untuk retur picking %s") % picking.name) return_wizard.product_return_moves = return_lines return_vals = return_wizard.create_returns() - return_id = return_vals.get('res_id') - return_picking = self.env['stock.picking'].browse(return_id) + return_picking = self.env['stock.picking'].browse(return_vals.get('res_id')) if not return_picking: raise UserError("Retur gagal dibuat. Hasil create_returns: %s" % str(return_vals)) return_picking.write({ - 'location_dest_id': default_location_dest_id, 'location_id': default_location_id, + 'location_dest_id': default_location_dest_id, 'group_id': grup.id, 'tukar_guling_id': record.id, }) + for move in return_picking.move_lines: + move.write({ + 'location_id': default_location_id, + 'location_dest_id': default_location_dest_id, + }) + return return_picking - # === PERBAIKI URUTAN === - srt = _create_return_from_picking(bu_out_to_return) + # === FLOW === + srt = _create_return_from_picking_grouped(bu_out_to_return) if srt: created_returns.append(srt) - picks = record.operations.konfirm_koli_lines.pick_id - for picking in picks: - ort = _create_return_from_picking(picking) + for picking in bu_pick_to_return: + ort = _create_return_from_picking_grouped(picking) if ort: created_returns.append(ort) if record.return_type == 'tukar_guling': - bu_pick = _create_return_from_picking(ort) + bu_pick = _create_return_from_picking_grouped(ort) if bu_pick: created_returns.append(bu_pick) if record.return_type == 'tukar_guling' and srt: - bu_out = _create_return_from_picking(srt) + bu_out = _create_return_from_picking_grouped(srt) if bu_out: created_returns.append(bu_out) @@ -601,6 +609,7 @@ class TukarGuling(models.Model): raise UserError("Tidak ada dokumen retur yang berhasil dibuat.") + class TukarGulingLine(models.Model): _name = 'tukar.guling.line' _description = 'Tukar Guling Line' @@ -650,5 +659,5 @@ class TukarGulingMappingKoli(models.Model): pick_id = fields.Many2one('stock.picking', string='BU PICK') product_id = fields.Many2one('product.product', string='Product') qty_done = fields.Float(string='Qty Done BU PICK') - qty_return = fields.Float(string='Qty yang mau diretur') - sequence = fields.Integer(string='Sequence', default=10) + qty_return = fields.Float(string='Qty diretur') + sequence = fields.Integer(string='Sequence', default=10)
\ No newline at end of file diff --git a/indoteknik_custom/views/tukar_guling.xml b/indoteknik_custom/views/tukar_guling.xml index c36089ad..acc48d3f 100644 --- a/indoteknik_custom/views/tukar_guling.xml +++ b/indoteknik_custom/views/tukar_guling.xml @@ -86,13 +86,13 @@ </group> </group> <notebook> - <page string="Product Lines" name="product_lines" create="0" edit="0"> - <field name="line_ids" delete="1" readonly="1"> - <tree string="Product Lines"> + <page string="Product Lines" name="product_lines"> + <field name="line_ids"> + <tree string="Product Lines" editable="top" create="0" delete="1"> <field name="sequence" widget="handle"/> - <field name="product_id" required="1" - options="{'no_create': True, 'no_create_edit': True}"/> - <field name="name" force_save="1"/> + <field name="product_id" required="0" + options="{'no_create': True, 'no_create_edit': True}" readonly="0"/> + <field name="name" force_save="0" readonly="1"/> <field name="product_uom_qty" string="Quantity"/> <field name="product_uom" string="UoM" options="{'no_create': True, 'no_create_edit': True}"/> @@ -101,10 +101,11 @@ </page> <page string="Mapping Koli" name="mapping_koli"> <field name="mapping_koli_ids"> - <tree> - <field name="pick_id"/> - <field name="product_id"/> - <field name="qty_done"/> + <tree editable="top" create="0" delete="1"> + <field name="pick_id" readonly="1" force_save="1"/> + <field name="product_id" readonly="1" force_save="1"/> + <field name="qty_done" force_save="1"/> + <field name="qty_return"/> </tree> </field> </page> |
