summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIT Fixcomart <it@fixcomart.co.id>2025-06-04 08:25:53 +0000
committerIT Fixcomart <it@fixcomart.co.id>2025-06-04 08:25:53 +0000
commit5003a089ba5816e6e01dcd60ee4532e98eecdd18 (patch)
treeee41d03bdde03546e6932365b114c54776e10a7d
parent3882ee6c3299525eeb8924cd9c7245f65cd15a28 (diff)
parent157f7756a24fd766429cbf639c732b76b18e9c26 (diff)
Merged in fix_bug_total_margin (pull request #321)
<miqdad> Fix Total Margin Calculation
-rwxr-xr-xindoteknik_custom/models/sale_order.py221
1 files changed, 172 insertions, 49 deletions
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py
index fa570819..705d16ef 100755
--- a/indoteknik_custom/models/sale_order.py
+++ b/indoteknik_custom/models/sale_order.py
@@ -148,8 +148,8 @@ class SaleOrder(models.Model):
help="Total Margin in Sales Order Header")
total_percent_margin = fields.Float('Total Percent Margin', compute='_compute_total_percent_margin',
help="Total % Margin in Sales Order Header")
- total_margin_excl_third_party = fields.Float('Before Margin', help="Before Margin in Sales Order Header",
- compute='_compute_total_margin_excl_third_party')
+ total_margin_excl_third_party = fields.Float('Before Margin', help="Before Margin in Sales Order Header")
+
approval_status = fields.Selection([
('pengajuan1', 'Approval Manager'),
('pengajuan2', 'Approval Pimpinan'),
@@ -340,16 +340,16 @@ class SaleOrder(models.Model):
date_unhold = fields.Datetime(string='Date Unhold', tracking=True, readonly=True, help='Waktu ketika SO di Unhold'
)
- def _compute_total_margin_excl_third_party(self):
- for order in self:
- if order.amount_untaxed == 0:
- order.total_margin_excl_third_party = 0
- continue
-
- # order.total_percent_margin = round((order.total_margin / (order.amount_untaxed-delivery_amt-order.fee_third_party)) * 100, 2)
- order.total_margin_excl_third_party = round((order.total_before_margin / (order.amount_untaxed)) * 100, 2)
- # order.total_percent_margin = round((order.total_margin / (order.amount_untaxed)) * 100, 2)
-
+ # def _compute_total_margin_excl_third_party(self):
+ # for order in self:
+ # if order.amount_untaxed == 0:
+ # order.total_margin_excl_third_party = 0
+ # continue
+ #
+ # # order.total_percent_margin = round((order.total_margin / (order.amount_untaxed-delivery_amt-order.fee_third_party)) * 100, 2)
+ # order.total_margin_excl_third_party = round((order.total_before_margin / (order.amount_untaxed)) * 100, 2)
+ # # order.total_percent_margin = round((order.total_margin / (order.amount_untaxed)) * 100, 2)
+ #
def ask_retur_cancel_purchasing(self):
for rec in self:
if self.env.user.has_group('indoteknik_custom.group_role_purchasing'):
@@ -403,14 +403,14 @@ class SaleOrder(models.Model):
if len(tax_sets) > 1:
raise ValidationError("Semua produk dalam Sales Order harus memiliki kombinasi pajak yang sama.")
- # @api.constrains('fee_third_party', 'delivery_amt', 'biaya_lain_lain')
+ # @api.constrains('fee_third_party', 'delivery_amt', 'biaya_lain_lain', 'ongkir_ke_xpdc')
# def _check_total_margin_excl_third_party(self):
# for rec in self:
# if rec.fee_third_party == 0 and rec.total_margin_excl_third_party != rec.total_percent_margin:
# # Gunakan direct SQL atau flag context untuk menghindari rekursi
# self.env.cr.execute("""
- # UPDATE sale_order
- # SET total_margin_excl_third_party = %s
+ # UPDATE sale_order
+ # SET total_margin_excl_third_party = %s
# WHERE id = %s
# """, (rec.total_percent_margin, rec.id))
# self.invalidate_cache()
@@ -866,7 +866,6 @@ class SaleOrder(models.Model):
def _validate_delivery_amt(self):
is_indoteknik = self.carrier_id.id == 1 or self.shipping_cost_covered == 'indoteknik'
is_active_id = not self.env.context.get('active_id', [])
-
if is_indoteknik and is_active_id:
if self.delivery_amt == 0:
if self.carrier_id.id == 1:
@@ -1035,11 +1034,11 @@ class SaleOrder(models.Model):
line_no += 1
line.line_no = line_no
- def write(self, vals):
- if 'carrier_id' in vals:
- for picking in self.picking_ids:
- if picking.state == 'assigned':
- picking.carrier_id = self.carrier_id
+ # def write(self, vals):
+ # if 'carrier_id' in vals:
+ # for picking in self.picking_ids:
+ # if picking.state == 'assigned':
+ # picking.carrier_id = self.carrier_id
def calculate_so_status(self):
so_state = ['sale']
@@ -1157,12 +1156,12 @@ class SaleOrder(models.Model):
helper_ids_str = self.env['ir.config_parameter'].sudo().get_param('sale.order.user_helper_ids')
return helper_ids_str.split(', ')
- def write(self, values):
- helper_ids = self._get_helper_ids()
- if str(self.env.user.id) in helper_ids:
- values['helper_by_id'] = self.env.user.id
-
- return super(SaleOrder, self).write(values)
+ # def write(self, values):
+ # helper_ids = self._get_helper_ids()
+ # if str(self.env.user.id) in helper_ids:
+ # values['helper_by_id'] = self.env.user.id
+ #
+ # return super(SaleOrder, self).write(values)
def check_due(self):
"""To show the due amount and warning stage"""
@@ -1693,20 +1692,95 @@ class SaleOrder(models.Model):
total_before_margin = sum(line.item_before_margin for line in order.order_line if line.product_id)
order.total_before_margin = total_before_margin
+ # Perhitungan Lama
+ # def _compute_total_percent_margin(self):
+ # for order in self:
+ # if order.amount_untaxed == 0:
+ # order.total_percent_margin = 0
+ # continue
+ # if order.shipping_cost_covered == 'indoteknik':
+ # delivery_amt = order.delivery_amt
+ # else:
+ # delivery_amt = 0
+ #
+ # net_margin = order.total_margin - order.biaya_lain_lain
+ #
+ # order.total_percent_margin = round(
+ # (net_margin / (order.amount_untaxed - order.fee_third_party)) * 100, 2)
+
+ # order.total_percent_margin = round((order.total_margin / (order.amount_untaxed-delivery_amt-order.fee_third_party)) * 100, 2)
+ # order.total_percent_margin = round(
+ # (order.total_margin / (order.amount_untaxed - order.fee_third_party - order.biaya_lain_lain)) * 100, 2)
+ # order.total_percent_margin = round((order.total_margin / (order.amount_untaxed)) * 100, 2)
+
def _compute_total_percent_margin(self):
for order in self:
if order.amount_untaxed == 0:
order.total_percent_margin = 0
continue
+
if order.shipping_cost_covered == 'indoteknik':
delivery_amt = order.delivery_amt
else:
delivery_amt = 0
- # order.total_percent_margin = round((order.total_margin / (order.amount_untaxed-delivery_amt-order.fee_third_party)) * 100, 2)
- order.total_percent_margin = round(
- (order.total_margin / (order.amount_untaxed - order.fee_third_party - order.biaya_lain_lain)) * 100, 2)
- # order.total_percent_margin = round((order.total_margin / (order.amount_untaxed)) * 100, 2)
+ net_margin = order.total_margin - order.fee_third_party - order.biaya_lain_lain
+
+
+ if order.amount_untaxed > 0:
+ order.total_percent_margin = round((net_margin / order.amount_untaxed) * 100, 2)
+ else:
+ order.total_percent_margin = 0
+
+ # @api.onchange('biaya_lain_lain')
+ # def _onchange_biaya_lain_lain(self):
+ # """Ketika biaya_lain_lain berubah, simpan nilai margin sebelumnya"""
+ # if hasattr(self, '_origin') and self._origin.id:
+ # # Hitung margin sebelum biaya_lain_lain ditambahkan
+ # if self.amount_untaxed > 0:
+ # original_net_margin = self.total_margin # tanpa biaya_lain_lain
+ # self.total_margin_excl_third_party = round(
+ # (original_net_margin / (self.amount_untaxed - self.fee_third_party)) * 100, 2)
+
+ def _prepare_before_margin_values(self, vals):
+ margin_sebelumnya = {}
+
+ margin_affecting_fields = [
+ 'biaya_lain_lain', 'fee_third_party', 'delivery_amt',
+ 'ongkir_ke_xpdc', 'shipping_cost_covered', 'order_line'
+ ]
+
+ if not any(field in vals for field in margin_affecting_fields):
+ return {}
+
+ for order in self:
+ if order.amount_untaxed <= 0:
+ continue
+
+ current_before = order.total_margin_excl_third_party or 0
+
+ # CASE 1: Before margin masih kosong → ambil dari item_percent_margin
+ if current_before == 0:
+ line_margin = 0
+ for line in order.order_line:
+ if line.item_percent_margin is not None:
+ line_margin = line.item_percent_margin
+ break
+ margin_sebelumnya[order.id] = line_margin
+ _logger.info(f"[BEFORE] SO {order.name}: Before margin kosong, ambil dari order line: {line_margin}%")
+ else:
+ # CASE 2: Ada perubahan field yang mempengaruhi margin
+ for field in margin_affecting_fields:
+ if field in vals:
+ old_val = getattr(order, field, 0) or 0
+ new_val = vals[field] or 0
+ if old_val != new_val:
+ margin_sebelumnya[order.id] = order.total_percent_margin
+ _logger.info(
+ f"[BEFORE] SO {order.name}: {field} berubah dari {old_val} ke {new_val}, simpan {order.total_percent_margin}%")
+ break
+
+ return margin_sebelumnya
@api.onchange('sales_tax_id')
def onchange_sales_tax_id(self):
@@ -1997,23 +2071,23 @@ class SaleOrder(models.Model):
'customer_type': partner.customer_type,
})
- def write(self, vals):
- for order in self:
- if order.state in ['sale', 'cancel']:
- if 'order_line' in vals:
- new_lines = vals.get('order_line', [])
- for command in new_lines:
- if command[0] == 0: # A new line is being added
- raise UserError(
- "SO tidak dapat ditambahkan produk baru karena SO sudah menjadi sale order.")
-
- res = super(SaleOrder, self).write(vals)
- # self._check_total_margin_excl_third_party()
- if any(fields in vals for fields in ['delivery_amt', 'carrier_id', 'shipping_cost_covered']):
- self._validate_delivery_amt()
- if any(field in vals for field in ["order_line", "client_order_ref"]):
- self._calculate_etrts_date()
- return res
+ # def write(self, vals):
+ # for order in self:
+ # if order.state in ['sale', 'cancel']:
+ # if 'order_line' in vals:
+ # new_lines = vals.get('order_line', [])
+ # for command in new_lines:
+ # if command[0] == 0: # A new line is being added
+ # raise UserError(
+ # "SO tidak dapat ditambahkan produk baru karena SO sudah menjadi sale order.")
+ #
+ # res = super(SaleOrder, self).write(vals)
+ # # self._check_total_margin_excl_third_party()
+ # if any(fields in vals for fields in ['delivery_amt', 'carrier_id', 'shipping_cost_covered']):
+ # self._validate_delivery_amt()
+ # if any(field in vals for field in ["order_line", "client_order_ref"]):
+ # self._calculate_etrts_date()
+ # return res
# @api.depends('commitment_date')
def _compute_ready_to_ship_status_detail(self):
@@ -2043,4 +2117,53 @@ class SaleOrder(models.Model):
else:
order.ready_to_ship_status_detail = "On Track"
else:
- order.ready_to_ship_status_detail = 'On Track' \ No newline at end of file
+ order.ready_to_ship_status_detail = 'On Track'
+
+ def write(self, vals):
+
+ margin_sebelumnya = self._prepare_before_margin_values(vals)
+
+ for order in self:
+ if order.state in ['sale', 'cancel']:
+ if 'order_line' in vals:
+ for command in vals.get('order_line', []):
+ if command[0] == 0:
+ raise UserError(
+ "SO tidak dapat ditambahkan produk baru karena SO sudah menjadi sale order.")
+
+ if 'carrier_id' in vals:
+ for order in self:
+ for picking in order.picking_ids:
+ if picking.state == 'assigned':
+ picking.carrier_id = vals['carrier_id']
+
+ try:
+ helper_ids = self._get_helper_ids()
+ if str(self.env.user.id) in helper_ids:
+ vals['helper_by_id'] = self.env.user.id
+ except:
+ pass
+
+ res = super(SaleOrder, self).write(vals)
+
+ # Update before margin setelah write
+ if margin_sebelumnya:
+ for order_id, margin_value in margin_sebelumnya.items():
+ _logger.info(f"[UPDATE] SO ID {order_id}: Set before margin ke {margin_value}%")
+ self.env.cr.execute("""
+ UPDATE sale_order
+ SET total_margin_excl_third_party = %s
+ WHERE id = %s
+ """, (margin_value, order_id))
+
+ self.env.cr.commit()
+ self.invalidate_cache(['total_margin_excl_third_party'])
+
+ # Validasi setelah write
+ if any(field in vals for field in ['delivery_amt', 'carrier_id', 'shipping_cost_covered']):
+ self._validate_delivery_amt()
+
+ if any(field in vals for field in ["order_line", "client_order_ref"]):
+ self._calculate_etrts_date()
+
+ return res \ No newline at end of file