summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzka Nathan <darizkyfaz@gmail.com>2025-08-19 14:02:45 +0700
committerAzka Nathan <darizkyfaz@gmail.com>2025-08-19 14:02:45 +0700
commite2d186dd98b2c0d1bc9bab8ea9b7d80c59873046 (patch)
tree2150fbe6c6cf198da9c565777ea9d838ef8d6738
parent6fc6511bdfd530d5e1f89fd5e4cb672a632a51f0 (diff)
add percent pie on sale order
-rwxr-xr-xindoteknik_custom/models/sale_order.py41
-rw-r--r--indoteknik_custom/models/sale_order_line.py27
-rwxr-xr-xindoteknik_custom/views/sale_order.xml6
3 files changed, 74 insertions, 0 deletions
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:
diff --git a/indoteknik_custom/models/sale_order_line.py b/indoteknik_custom/models/sale_order_line.py
index 64b9f9bc..2a00bac0 100644
--- a/indoteknik_custom/models/sale_order_line.py
+++ b/indoteknik_custom/models/sale_order_line.py
@@ -54,6 +54,33 @@ class SaleOrderLine(models.Model):
desc_updatable = fields.Boolean(string='desc boolean', default=True, compute='_get_desc_updatable')
is_has_disc = fields.Boolean('Flash Sale', default=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('move_ids')
+ def _compute_reserved_delivered_pie(self):
+ for line in self:
+ order_qty = line.product_uom_qty or 0.0
+ reserved_qty = delivered_qty = 0.0
+
+ if order_qty > 0:
+ # Reserved: hanya dari BU/PICK yang masih aktif
+ 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'))
+
+ # Delivered: hanya dari BU/OUT yang sudah done
+ 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'))
+
+ line.reserved_percent = (reserved_qty / order_qty) * 100 if order_qty else 0
+ line.delivered_percent = (delivered_qty / order_qty) * 100 if order_qty else 0
+ line.unreserved_percent = 100 - line.reserved_percent - line.delivered_percent
+
def _get_outgoing_incoming_moves(self):
diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml
index 868bce7b..518bc9d6 100755
--- a/indoteknik_custom/views/sale_order.xml
+++ b/indoteknik_custom/views/sale_order.xml
@@ -290,6 +290,9 @@
<field name="note" optional="hide"/>
<field name="note_procurement" optional="hide"/>
<field name="vendor_subtotal" optional="hide"/>
+ <field name="unreserved_percent" widget="percentpie" string="Unreserved"/>
+ <field name="reserved_percent" widget="percentpie" string="Reserved"/>
+ <field name="delivered_percent" widget="percentpie" string="Delivered"/>
<field name="weight" optional="hide"/>
<field name="is_has_disc" string="Flash Sale Item?" readonly="1" optional="hide"/>
<field name="amount_voucher_disc" string="Voucher" readonly="1" optional="hide"/>
@@ -461,6 +464,9 @@
<field name="pareto_status" optional="hide"/>
<field name="shipping_method_picking" optional="hide"/>
<field name="hold_outgoing" optional="hide"/>
+ <field name="reserved_percent" widget="percentpie" string="Reserved"/>
+ <field name="delivered_percent" widget="percentpie" string="Delivered"/>
+ <field name="unreserved_percent" widget="percentpie" string="Unreserved"/>
</field>
</field>
</record>