From e2d186dd98b2c0d1bc9bab8ea9b7d80c59873046 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 19 Aug 2025 14:02:45 +0700 Subject: add percent pie on sale order --- indoteknik_custom/models/sale_order.py | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'indoteknik_custom/models/sale_order.py') diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 0acfa0b0..80790ebe 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -376,6 +376,47 @@ class SaleOrder(models.Model): compute='_compute_advance_payment_moves', store=False ) + reserved_percent = fields.Float( + string="Reserved %", digits=(16, 2), + compute="_compute_reserved_delivered_pie", store=False + ) + delivered_percent = fields.Float( + string="Delivered %", digits=(16, 2), + compute="_compute_reserved_delivered_pie", store=False + ) + unreserved_percent = fields.Float( + string="Unreserved %", digits=(16, 2), + compute="_compute_reserved_delivered_pie", store=False + ) + + @api.depends('order_line.reserved_percent', 'order_line.delivered_percent', 'order_line.unreserved_percent') + def _compute_reserved_delivered_pie(self): + for order in self: + total_qty = sum(order.order_line.mapped('product_uom_qty')) + reserved_qty = delivered_qty = 0.0 + + if total_qty > 0: + for line in order.order_line: + order_qty = line.product_uom_qty or 0.0 + if not order_qty: + continue + + # ambil qty asli dari move, bukan percent agar akurat + pick_moves = line.move_ids.filtered( + lambda m: m.picking_type_id.code == 'internal' and m.state not in ('done', 'cancel') + ) + reserved_qty += sum(pick_moves.mapped('reserved_availability')) + + out_moves = line.move_ids.filtered( + lambda m: m.picking_type_id.code == 'outgoing' and m.state == 'done' + ) + delivered_qty += sum(out_moves.mapped('quantity_done')) + + order.reserved_percent = (reserved_qty / total_qty) * 100 + order.delivered_percent = (delivered_qty / total_qty) * 100 + order.unreserved_percent = 100 - order.reserved_percent - order.delivered_percent + else: + order.reserved_percent = order.delivered_percent = order.unreserved_percent = 0 def _has_ccm(self): if self.id: -- cgit v1.2.3 From 1d44c04f3ec25d3adc19eb8e34589c6461ef8a66 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Wed, 20 Aug 2025 10:04:10 +0700 Subject: fix bug percentpie retur --- indoteknik_custom/models/sale_order.py | 57 ++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 10 deletions(-) (limited to 'indoteknik_custom/models/sale_order.py') diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 80790ebe..53be999f 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -388,8 +388,37 @@ class SaleOrder(models.Model): string="Unreserved %", digits=(16, 2), compute="_compute_reserved_delivered_pie", store=False ) + payment_state_custom = fields.Selection([ + ('unpaid', 'Unpaid'), + ('partial', 'Partially Paid'), + ('paid', 'Paid'), + ('no_invoice', 'No Invoice'), + ], string="Payment Status", compute="_compute_payment_state_custom", store=False) + + @api.depends('invoice_ids.payment_state', 'invoice_ids.amount_total', 'invoice_ids.amount_residual') + def _compute_payment_state_custom(self): + for order in self: + invoices = order.invoice_ids.filtered(lambda inv: inv.state != 'cancel') + total = sum(invoices.mapped('amount_total')) + residual = sum(invoices.mapped('amount_residual')) + + if not invoices or total == 0: + order.payment_state_custom = 'no_invoice' + continue + + paid = total - residual + percent_paid = (paid / total) * 100 if total > 0 else 0.0 + + if percent_paid == 100: + order.payment_state_custom = 'paid' + elif percent_paid == 0: + order.payment_state_custom = 'unpaid' + else: + order.payment_state_custom = 'partial' - @api.depends('order_line.reserved_percent', 'order_line.delivered_percent', 'order_line.unreserved_percent') + @api.depends('order_line.move_ids.state', + 'order_line.move_ids.reserved_availability', + 'order_line.move_ids.quantity_done') def _compute_reserved_delivered_pie(self): for order in self: total_qty = sum(order.order_line.mapped('product_uom_qty')) @@ -401,16 +430,23 @@ class SaleOrder(models.Model): if not order_qty: continue - # ambil qty asli dari move, bukan percent agar akurat - pick_moves = line.move_ids.filtered( - lambda m: m.picking_type_id.code == 'internal' and m.state not in ('done', 'cancel') - ) - reserved_qty += sum(pick_moves.mapped('reserved_availability')) + for move in line.move_ids: + if move.state != 'done': + # reserve qty (draft/assigned) + if move.picking_type_id.code == 'internal': + reserved_qty += move.reserved_availability or 0.0 + continue - out_moves = line.move_ids.filtered( - lambda m: m.picking_type_id.code == 'outgoing' and m.state == 'done' - ) - delivered_qty += sum(out_moves.mapped('quantity_done')) + # sudah done → cek alur lokasi + if move.location_dest_id.usage == 'customer': + # barang keluar → delivered + delivered_qty += move.quantity_done + elif move.location_id.usage == 'customer': + # barang balik (return) → kurangi delivered + delivered_qty -= move.quantity_done + + # clamp biar ga minus + delivered_qty = max(delivered_qty, 0) order.reserved_percent = (reserved_qty / total_qty) * 100 order.delivered_percent = (delivered_qty / total_qty) * 100 @@ -418,6 +454,7 @@ class SaleOrder(models.Model): else: order.reserved_percent = order.delivered_percent = order.unreserved_percent = 0 + def _has_ccm(self): if self.id: self.ccm_id = self.env['tukar.guling'].search([('origin', 'ilike', self.name)], limit=1) -- cgit v1.2.3 From af483feb734c1e135a779008ca3fa32a721d59ff Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Wed, 20 Aug 2025 15:24:58 +0700 Subject: fix bug percent pie --- indoteknik_custom/models/sale_order.py | 35 ++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) (limited to 'indoteknik_custom/models/sale_order.py') diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 53be999f..5787c6ea 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -431,21 +431,27 @@ class SaleOrder(models.Model): continue for move in line.move_ids: - if move.state != 'done': - # reserve qty (draft/assigned) - if move.picking_type_id.code == 'internal': + if move.picking_type_id.code == 'internal': + if move.state != 'done': + # PICK belum done → qty reserved reserved_qty += move.reserved_availability or 0.0 - continue - - # sudah done → cek alur lokasi - if move.location_dest_id.usage == 'customer': - # barang keluar → delivered - delivered_qty += move.quantity_done - elif move.location_id.usage == 'customer': - # barang balik (return) → kurangi delivered - delivered_qty -= move.quantity_done - - # clamp biar ga minus + else: + # PICK done → qty_done masih dianggap reserved (masuk BU/OUT) + reserved_qty += move.quantity_done or 0.0 + + elif move.state == 'done': + # OUT done (customer terima) → delivered + if move.location_dest_id.usage == 'customer': + delivered_qty += move.quantity_done + # sekaligus kurangi reserved (karena udah terkirim) + reserved_qty -= move.quantity_done + # Return dari customer + elif move.location_id.usage == 'customer': + delivered_qty -= move.quantity_done + reserved_qty += move.quantity_done # balik ke reserved + + # clamp jangan sampai minus + reserved_qty = max(reserved_qty, 0) delivered_qty = max(delivered_qty, 0) order.reserved_percent = (reserved_qty / total_qty) * 100 @@ -455,6 +461,7 @@ class SaleOrder(models.Model): order.reserved_percent = order.delivered_percent = order.unreserved_percent = 0 + def _has_ccm(self): if self.id: self.ccm_id = self.env['tukar.guling'].search([('origin', 'ilike', self.name)], limit=1) -- cgit v1.2.3 From c837117a771bbefcf06706d024d4620b331192a9 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Wed, 20 Aug 2025 16:20:28 +0700 Subject: push --- indoteknik_custom/models/sale_order.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indoteknik_custom/models/sale_order.py') diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 5787c6ea..9a6f314d 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -391,9 +391,9 @@ class SaleOrder(models.Model): payment_state_custom = fields.Selection([ ('unpaid', 'Unpaid'), ('partial', 'Partially Paid'), - ('paid', 'Paid'), + ('paid', 'Full Paid'), ('no_invoice', 'No Invoice'), - ], string="Payment Status", compute="_compute_payment_state_custom", store=False) + ], string="Payment Status Invoice", compute="_compute_payment_state_custom", store=False) @api.depends('invoice_ids.payment_state', 'invoice_ids.amount_total', 'invoice_ids.amount_residual') def _compute_payment_state_custom(self): -- cgit v1.2.3 From 4b549234856b810bd99f8b1e18e01da90ccdc1e1 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Thu, 21 Aug 2025 19:07:58 +0700 Subject: fix bug percent pie --- indoteknik_custom/models/sale_order.py | 66 +++++++++++++++------------------- 1 file changed, 29 insertions(+), 37 deletions(-) (limited to 'indoteknik_custom/models/sale_order.py') diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 9a6f314d..ffb53dce 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -416,51 +416,43 @@ class SaleOrder(models.Model): else: order.payment_state_custom = 'partial' - @api.depends('order_line.move_ids.state', - 'order_line.move_ids.reserved_availability', - 'order_line.move_ids.quantity_done') + @api.depends( + 'order_line.move_ids.state', + 'order_line.move_ids.reserved_availability', + 'order_line.move_ids.quantity_done', + 'order_line.move_ids.picking_type_id' + ) def _compute_reserved_delivered_pie(self): for order in self: - total_qty = sum(order.order_line.mapped('product_uom_qty')) + order_qty = sum(order.order_line.mapped('product_uom_qty')) or 0.0 reserved_qty = delivered_qty = 0.0 - if total_qty > 0: - for line in order.order_line: - order_qty = line.product_uom_qty or 0.0 - if not order_qty: - continue + if order_qty > 0: + # Kumpulin semua moves dari order + all_moves = order.order_line.mapped('move_ids') - for move in line.move_ids: - if move.picking_type_id.code == 'internal': - if move.state != 'done': - # PICK belum done → qty reserved - reserved_qty += move.reserved_availability or 0.0 - else: - # PICK done → qty_done masih dianggap reserved (masuk BU/OUT) - reserved_qty += move.quantity_done or 0.0 - - elif move.state == 'done': - # OUT done (customer terima) → delivered - if move.location_dest_id.usage == 'customer': - delivered_qty += move.quantity_done - # sekaligus kurangi reserved (karena udah terkirim) - reserved_qty -= move.quantity_done - # Return dari customer - elif move.location_id.usage == 'customer': - delivered_qty -= move.quantity_done - reserved_qty += move.quantity_done # balik ke reserved - - # clamp jangan sampai minus - reserved_qty = max(reserved_qty, 0) - delivered_qty = max(delivered_qty, 0) + for move in all_moves: + # --- CASE 1: Move belum selesai --- + if move.state not in ('done', 'cancel'): + # Reserved qty hanya dari move yang belum selesai + reserved_qty += move.reserved_availability or 0.0 + continue - order.reserved_percent = (reserved_qty / total_qty) * 100 - order.delivered_percent = (delivered_qty / total_qty) * 100 - order.unreserved_percent = 100 - order.reserved_percent - order.delivered_percent - else: - order.reserved_percent = order.delivered_percent = order.unreserved_percent = 0 + # --- CASE 2: Move sudah done --- + if move.location_dest_id.usage == 'customer': + # Barang dikirim ke customer + delivered_qty += move.quantity_done or 0.0 + elif move.location_id.usage == 'customer': + # Barang balik dari customer (retur) + delivered_qty -= move.quantity_done or 0.0 + # Clamp supaya delivered gak minus + delivered_qty = max(delivered_qty, 0) + # Hitung persen + order.reserved_percent = min((reserved_qty / order_qty) * 100, 100) if order_qty else 0 + order.delivered_percent = min((delivered_qty / order_qty) * 100, 100) if order_qty else 0 + order.unreserved_percent = max(100 - order.reserved_percent - order.delivered_percent, 0) def _has_ccm(self): if self.id: -- cgit v1.2.3