summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzka Nathan <darizkyfaz@gmail.com>2025-10-30 10:09:00 +0700
committerAzka Nathan <darizkyfaz@gmail.com>2025-10-30 10:09:00 +0700
commit099bec753a310ec83ea3562a78c304dffb6d50d8 (patch)
tree5e5e76c032c199a79a0d191699ea6a00725ea029
parentb35a287e6c431375458d47407f28ccb3978d0194 (diff)
mark partial delivery and delivery status
-rw-r--r--indoteknik_custom/models/partial_delivery.py4
-rwxr-xr-xindoteknik_custom/models/sale_order.py2
-rw-r--r--indoteknik_custom/models/stock_move.py50
-rw-r--r--indoteknik_custom/models/stock_picking.py91
-rw-r--r--indoteknik_custom/views/stock_picking.xml6
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&gt;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>