diff options
Diffstat (limited to 'indoteknik_custom/models/sale_order.py')
| -rwxr-xr-x | indoteknik_custom/models/sale_order.py | 57 |
1 files changed, 47 insertions, 10 deletions
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) |
