diff options
| author | Azka Nathan <darizkyfaz@gmail.com> | 2025-10-30 10:09:00 +0700 |
|---|---|---|
| committer | Azka Nathan <darizkyfaz@gmail.com> | 2025-10-30 10:09:00 +0700 |
| commit | 099bec753a310ec83ea3562a78c304dffb6d50d8 (patch) | |
| tree | 5e5e76c032c199a79a0d191699ea6a00725ea029 | |
| parent | b35a287e6c431375458d47407f28ccb3978d0194 (diff) | |
mark partial delivery and delivery status
| -rw-r--r-- | indoteknik_custom/models/partial_delivery.py | 4 | ||||
| -rwxr-xr-x | indoteknik_custom/models/sale_order.py | 2 | ||||
| -rw-r--r-- | indoteknik_custom/models/stock_move.py | 50 | ||||
| -rw-r--r-- | indoteknik_custom/models/stock_picking.py | 91 | ||||
| -rw-r--r-- | indoteknik_custom/views/stock_picking.xml | 6 |
5 files changed, 152 insertions, 1 deletions
diff --git a/indoteknik_custom/models/partial_delivery.py b/indoteknik_custom/models/partial_delivery.py index 744db325..519f505c 100644 --- a/indoteknik_custom/models/partial_delivery.py +++ b/indoteknik_custom/models/partial_delivery.py @@ -115,9 +115,13 @@ class PartialDeliveryWizard(models.TransientModel): raise UserError(_("Picking harus dalam status Ready (assigned).")) lines_by_qty = self.line_ids.filtered(lambda l: l.selected_qty > 0) + lines_validation = self.line_ids.filtered(lambda l: l.selected_qty > l.reserved_qty) lines_by_selected = self.line_ids.filtered(lambda l: l.selected and not l.selected_qty) selected_lines = lines_by_qty | lines_by_selected # gabung dua domain hasil filter + if lines_validation: + raise UserError(_("Jumlah yang dipilih melebihi jumlah yang terdapat di DO.")) + if not selected_lines: raise UserError(_("Tidak ada produk yang dipilih atau diisi jumlahnya.")) diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 7b60863e..494aeaa2 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -2720,7 +2720,7 @@ class SaleOrder(models.Model): raise UserError("Yahaha gabisa confirm so, minta ke sales nya ajah") if self.env.context.get("ask_approval") and user.id in (3401, 20, 3988): - raise UserError("Yahaha gabisa confirm so, minta ke sales nya ajah") + return True salesperson_id = self.user_id.id approver_id = user.id diff --git a/indoteknik_custom/models/stock_move.py b/indoteknik_custom/models/stock_move.py index 1da2befe..8f8ba66f 100644 --- a/indoteknik_custom/models/stock_move.py +++ b/indoteknik_custom/models/stock_move.py @@ -186,6 +186,56 @@ class StockMoveLine(models.Model): line_no = fields.Integer('No', default=0) note = fields.Char('Note') manufacture = fields.Many2one('x_manufactures', string="Brands", related="product_id.x_manufacture", store=True) + outstanding_qty = fields.Float( + string='Outstanding Qty', + compute='_compute_delivery_line_status', + store=False + ) + delivery_status = fields.Selection([ + ('none', 'No Movement'), + ('partial', 'Partial'), + ('partial_final', 'Partial Final'), + ('full', 'Full'), + ], string='Delivery Status', compute='_compute_delivery_line_status', store=False) + + @api.depends('qty_done', 'product_uom_qty', 'picking_id.state') + def _compute_delivery_line_status(self): + for line in self: + line.outstanding_qty = 0.0 + line.delivery_status = 'none' + + picking = line.picking_id + if not picking or picking.picking_type_id.code != 'outgoing': + continue + + total_qty = line.move_id.product_uom_qty or 0 + done_qty = line.qty_done or 0 + + line.outstanding_qty = max(total_qty - done_qty, 0) + + if total_qty == 0: + continue + + if done_qty == 0: + line.delivery_status = 'none' + elif done_qty > 0: + has_other_out = self.env['stock.picking'].search_count([ + ('group_id', '=', picking.group_id.id), + ('name', 'ilike', 'BU/OUT'), + ('id', '!=', picking.id), + ('state', '=', 'done'), + ]) + if has_other_out and done_qty == total_qty: + line.delivery_status = 'partial_final' + elif not has_other_out and done_qty >= total_qty: + line.delivery_status = 'full' + elif has_other_out and done_qty < total_qty: + line.delivery_status = 'partial' + elif done_qty < total_qty: + line.delivery_status = 'partial' + else: + line.delivery_status = 'none' + # Ambil uom dari stock move @api.model diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index d6096cc0..7f8523a3 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -177,6 +177,97 @@ class StockPicking(models.Model): area_name = fields.Char(string="Area", compute="_compute_area_name") is_bu_iu = fields.Boolean('Is BU/IU', compute='_compute_is_bu_iu', default=False, copy=False, readonl=True) + qty_yang_mau_dikirim = fields.Float( + string='Qty yang Mau Dikirim', + compute='_compute_delivery_status_detail', + store=False + ) + qty_terkirim = fields.Float( + string='Qty Terkirim', + compute='_compute_delivery_status_detail', + store=False + ) + qty_gantung = fields.Float( + string='Qty Gantung', + compute='_compute_delivery_status_detail', + store=False + ) + delivery_status = fields.Selection([ + ('none', 'No Movement'), + ('partial', 'Partial'), + ('partial_final', 'Partial Final'), + ('full', 'Full'), + ], string='Delivery Status', compute='_compute_delivery_status_detail', store=False) + + @api.depends('move_line_ids_without_package.qty_done', 'move_line_ids_without_package.product_uom_qty', 'state') + def _compute_delivery_status_detail(self): + for picking in self: + # Default values + picking.qty_yang_mau_dikirim = 0.0 + picking.qty_terkirim = 0.0 + picking.qty_gantung = 0.0 + picking.delivery_status = 'none' + + # Hanya berlaku untuk pengiriman (BU/OUT) + if picking.picking_type_id.code != 'outgoing': + continue + + move_lines = picking.move_line_ids_without_package + if not move_lines: + continue + + # ====================== + # HITUNG QTY + # ====================== + total_qty = sum(line.product_uom_qty for line in move_lines) + + done_qty_total = sum(line.sale_line_id.qty_delivered for line in picking.move_ids_without_package) + order_qty_total = sum(line.sale_line_id.product_uom_qty for line in picking.move_ids_without_package) + gantung_qty_total = order_qty_total - done_qty_total - total_qty + + picking.qty_yang_mau_dikirim = total_qty + picking.qty_terkirim = done_qty_total + picking.qty_gantung = gantung_qty_total + + # if total_qty == 0: + # picking.delivery_status = 'none' + # continue + + # if done_qty_total == 0: + # picking.delivery_status = 'none' + # continue + + # ====================== + # CEK BU/OUT LAIN (BACKORDER) + # ====================== + has_other_out = self.env['stock.picking'].search_count([ + ('group_id', '=', picking.group_id.id), + ('name', 'ilike', 'BU/OUT'), + ('id', '!=', picking.id), + ('state', 'in', ['assigned', 'waiting', 'confirmed', 'done']), + ]) + + # ====================== + # LOGIKA STATUS + # ====================== + if gantung_qty_total == 0 and done_qty_total == 0: + # Semua barang udah terkirim, ga ada picking lain + picking.delivery_status = 'full' + + elif gantung_qty_total > 0 and total_qty > 0 and done_qty_total == 0: + # Masih ada picking lain dan sisa gantung → proses masih jalan + picking.delivery_status = 'partial' + + # elif gantung_qty_total > 0: + # # Ini picking terakhir, tapi qty belum full + # picking.delivery_status = 'partial_final' + + elif gantung_qty_total == 0 and done_qty_total > 0 and total_qty > 0: + # Udah kirim semua tapi masih ada picking lain (rare case) + picking.delivery_status = 'partial_final' + + else: + picking.delivery_status = 'none' @api.depends('name') def _compute_is_bu_iu(self): diff --git a/indoteknik_custom/views/stock_picking.xml b/indoteknik_custom/views/stock_picking.xml index 44ab6355..050fc819 100644 --- a/indoteknik_custom/views/stock_picking.xml +++ b/indoteknik_custom/views/stock_picking.xml @@ -226,6 +226,10 @@ <group> <group> <field name="notee"/> + <field name="qty_yang_mau_dikirim"/> + <field name="qty_terkirim"/> + <field name="qty_gantung"/> + <field name="delivery_status"/> <field name="note_logistic"/> <field name="note_info"/> <field name="responsible"/> @@ -394,6 +398,8 @@ decoration-danger="qty_done>product_uom_qty and state!='done' and parent.picking_type_code != 'incoming'" decoration-success="qty_done==product_uom_qty and state!='done' and not result_package_id"> <field name="note" placeholder="Add a note here"/> + <field name="outstanding_qty"/> + <field name="delivery_status" widget="badge" options="{'colors': {'full': 'success', 'partial': 'warning', 'partial_final': 'danger'}}"/> </tree> </field> </record> |
