From 35d01765f9b925467b6ac20d2ff83c81f49e4d3e Mon Sep 17 00:00:00 2001 From: Miqdad Date: Thu, 2 Oct 2025 16:03:44 +0700 Subject: fix cannot apply voucher when cart has promotion item --- indoteknik_custom/models/sale_order.py | 65 +++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 12 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 663cba58..3aaae12d 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -2871,6 +2871,7 @@ class SaleOrder(models.Model): def action_apply_voucher(self): for line in self.order_line: if line.order_promotion_id: + _logger.warning(f"[CHECKOUT FAILED] Produk promo ditemukan: {line.product_id.display_name}") raise UserError('Voucher tidak dapat digabung dengan promotion program') voucher = self.voucher_id @@ -2913,42 +2914,82 @@ class SaleOrder(models.Model): self.apply_voucher_shipping() def apply_voucher(self): + def _is_promo_line(line): + # TRUE jika baris tidak boleh kena voucher + if getattr(line, 'order_promotion_id', False): + return True # baris dari program promo + if (line.price_unit or 0.0) == 0.0: + return True # free item + if getattr(line, 'is_has_disc', False): + return True # sudah promo/flashsale/berdiskon + if (line.discount or 0.0) >= 100.0: + return True # safety + return False + + # --- LOOP 1: susun input untuk voucher.apply() --- order_line = [] for line in self.order_line: + if _is_promo_line(line): + continue order_line.append({ 'product_id': line.product_id, 'price': line.price_unit, 'discount': line.discount, 'qty': line.product_uom_qty, - 'subtotal': line.price_subtotal + 'subtotal': line.price_subtotal, }) + + if not order_line: + return + voucher = self.voucher_id.apply(order_line) + # --- LOOP 2: tulis hasilnya HANYA ke non-promo --- for line in self.order_line: + if _is_promo_line(line): + continue + line.initial_discount = line.discount voucher_type = voucher['type'] - used_total = voucher['total'][voucher_type] - used_discount = voucher['discount'][voucher_type] + total_map = voucher['total'][voucher_type] + discount_map = voucher['discount'][voucher_type] - manufacture_id = line.product_id.x_manufacture.id if voucher_type == 'brand': - used_total = used_total.get(manufacture_id) - used_discount = used_discount.get(manufacture_id) + m_id = line.product_id.x_manufacture.id + used_total = (total_map or {}).get(m_id) + used_discount = (discount_map or {}).get(m_id) + else: + used_total = total_map + used_discount = discount_map - if not used_total or not used_discount: + if not used_total or not used_discount or (line.product_uom_qty or 0.0) == 0.0: continue line_contribution = line.price_subtotal / used_total line_voucher = used_discount * line_contribution - line_voucher_item = line_voucher / line.product_uom_qty + per_item_voucher = line_voucher / line.product_uom_qty - line_price_unit = line.price_unit / 1.11 if any(tax.id == 23 for tax in line.tax_id) else line.price_unit - line_discount_item = line_price_unit * line.discount / 100 + line_voucher_item - line_voucher_item = line_discount_item / line_price_unit * 100 + has_ppn_11 = any(tax.id == 23 for tax in line.tax_id) + base_unit = line.price_unit / 1.11 if has_ppn_11 else line.price_unit + + new_disc_value = base_unit * line.discount / 100 + per_item_voucher + new_disc_pct = (new_disc_value / base_unit) * 100 line.amount_voucher_disc = line_voucher - line.discount = line_voucher_item + line.discount = new_disc_pct + + _logger.info( + "[VOUCHER_APPLIED] SO=%s voucher=%s type=%s line_id=%s product=%s qty=%s discount_pct=%.2f amount_voucher=%s", + self.name, + getattr(self.voucher_id, "code", None), + voucher.get("type"), + line.id, + line.product_id.display_name, + line.product_uom_qty, + line.discount, + line.amount_voucher_disc, + ) self.amount_voucher_disc = voucher['discount']['all'] self.applied_voucher_id = self.voucher_id -- cgit v1.2.3 From c5642f4f6c4f0969475d863bee7243a83b9290dc Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Wed, 8 Oct 2025 14:55:04 +0700 Subject: partial --- indoteknik_custom/models/sale_order.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 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 3aaae12d..57217894 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -1813,10 +1813,10 @@ class SaleOrder(models.Model): # rec.commitment_date = rec.expected_ready_to_ship - @api.onchange('expected_ready_to_ship') #Hangle Onchange form Expected Ready to Ship + @api.onchange('expected_ready_to_ship') def _onchange_expected_ready_ship_date(self): self._validate_expected_ready_ship_date() - + def _set_etrts_date(self): for order in self: if order.state in ('done', 'cancel', 'sale'): @@ -2241,7 +2241,7 @@ class SaleOrder(models.Model): raise UserError("Payment Term pada Master Data Customer harus diisi") if not partner.active_limit and term_days > 0: raise UserError("Credit Limit pada Master Data Customer harus diisi") - if order.payment_term_id != partner.property_payment_term_id: + if order.payment_term_id != partner.property_payment_term_id and not order.partner_id.id == 29179: raise UserError("Payment Term berbeda pada Master Data Customer") if (partner.customer_type == 'pkp' or order.customer_type == 'pkp') and order.npwp != partner.npwp: raise UserError("NPWP berbeda pada Master Data Customer") @@ -2324,7 +2324,7 @@ class SaleOrder(models.Model): raise UserError("Payment Term pada Master Data Customer harus diisi") if not partner.active_limit and term_days > 0: raise UserError("Credit Limit pada Master Data Customer harus diisi") - if order.payment_term_id != partner.property_payment_term_id: + if order.payment_term_id != partner.property_payment_term_id and not order.partner_id.id == 29179: raise UserError("Payment Term berbeda pada Master Data Customer") if (partner.customer_type == 'pkp' or order.customer_type == 'pkp') and order.npwp != partner.npwp: raise UserError("NPWP berbeda pada Master Data Customer") @@ -3328,12 +3328,15 @@ class SaleOrder(models.Model): for order in self: partner = order.partner_id.parent_id or order.partner_id customer_payment_term = partner.property_payment_term_id - if vals['payment_term_id'] != customer_payment_term.id: + if vals['payment_term_id'] != customer_payment_term.id and not order.partner_id.id == 29179: raise UserError( f"Payment Term berbeda pada Master Data Customer. " f"Harap ganti ke '{customer_payment_term.name}' " f"sesuai dengan payment term yang terdaftar pada customer." ) + + if order.partner_id.id == 29179 and vals['payment_term_id'] not in [25,28]: + raise UserError(_("Pilih payment term 60 hari atau 30 hari.")) res = super(SaleOrder, self).write(vals) -- cgit v1.2.3 From 7b17ded8576c86470c56e5ccf961d0378b3a820f Mon Sep 17 00:00:00 2001 From: Miqdad Date: Wed, 8 Oct 2025 15:24:43 +0700 Subject: remove approval status api SO --- indoteknik_custom/models/sale_order.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 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 57217894..4a7203a1 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -1984,10 +1984,10 @@ class SaleOrder(models.Model): # raise UserError('Kelurahan Real Delivery Address harus diisi') def generate_payment_link_midtrans_sales_order(self): - # midtrans_url = 'https://app.sandbox.midtrans.com/snap/v1/transactions' # dev - sandbox - # midtrans_auth = 'Basic U0ItTWlkLXNlcnZlci1uLVY3ZDJjMlpCMFNWRUQyOU95Q1dWWXA6' # dev - sandbox - midtrans_url = 'https://app.midtrans.com/snap/v1/transactions' # production - midtrans_auth = 'Basic TWlkLXNlcnZlci1SbGMxZ2gzWGpSVW5scl9JblZzTV9OTnU6' # production + midtrans_url = 'https://app.sandbox.midtrans.com/snap/v1/transactions' # dev - sandbox + midtrans_auth = 'Basic U0ItTWlkLXNlcnZlci1uLVY3ZDJjMlpCMFNWRUQyOU95Q1dWWXA6' # dev - sandbox + # midtrans_url = 'https://app.midtrans.com/snap/v1/transactions' # production + # midtrans_auth = 'Basic TWlkLXNlcnZlci1SbGMxZ2gzWGpSVW5scl9JblZzTV9OTnU6' # production so_number = self.name so_number = so_number.replace('/', '-') @@ -2000,8 +2000,8 @@ class SaleOrder(models.Model): } # ==== ENV ==== - # check_url = f'https://api.sandbox.midtrans.com/v2/{so_number}/status' # dev - sandbox - check_url = f'https://api.midtrans.com/v2/{so_number}/status' # production + check_url = f'https://api.sandbox.midtrans.com/v2/{so_number}/status' # dev - sandbox + # check_url = f'https://api.midtrans.com/v2/{so_number}/status' # production # ============================================= check_response = requests.get(check_url, headers=headers) -- cgit v1.2.3 From 40c66acf47f900ecd776358758ac053347c078c7 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 13 Oct 2025 11:21:04 +0700 Subject: set back to pengajuan1 when CO from website and change SO line behavior onchange vendor_id --- indoteknik_custom/models/sale_order.py | 1 + 1 file changed, 1 insertion(+) (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 4a7203a1..2d2d71b3 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -3230,6 +3230,7 @@ class SaleOrder(models.Model): # order._auto_set_shipping_from_website() order._compute_etrts_date() order._validate_expected_ready_ship_date() + order.onchange_vendor_id() # order._validate_delivery_amt() # order._check_total_margin_excl_third_party() # order._update_partner_details() -- cgit v1.2.3 From dab2cdebb698b817b979efd2087175060f9b8f03 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 13 Oct 2025 13:01:35 +0700 Subject: change SO line behavior onchange vendor_id --- indoteknik_custom/models/sale_order.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (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 2d2d71b3..3bd1ca59 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -3230,7 +3230,10 @@ class SaleOrder(models.Model): # order._auto_set_shipping_from_website() order._compute_etrts_date() order._validate_expected_ready_ship_date() - order.onchange_vendor_id() + for line in order.order_line: + updated_vals = line._update_purchase_info() + if updated_vals: + line.write(updated_vals) # order._validate_delivery_amt() # order._check_total_margin_excl_third_party() # order._update_partner_details() @@ -3362,6 +3365,12 @@ class SaleOrder(models.Model): if any(field in vals for field in ["order_line", "client_order_ref"]): self._calculate_etrts_date() + for order in self: + for line in order.order_line: + updated_vals = line._update_purchase_info() + if updated_vals: + line.write(updated_vals) + return res def button_refund(self): -- cgit v1.2.3 From b6bf4c8b58b9311c6a6cf7f745cb42b025159759 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Wed, 15 Oct 2025 12:08:34 +0700 Subject: SO line onchange vendor id --- indoteknik_custom/models/sale_order.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 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 3bd1ca59..a5e2f7c4 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -3230,10 +3230,10 @@ class SaleOrder(models.Model): # order._auto_set_shipping_from_website() order._compute_etrts_date() order._validate_expected_ready_ship_date() - for line in order.order_line: - updated_vals = line._update_purchase_info() - if updated_vals: - line.write(updated_vals) + # for line in order.order_line: + # updated_vals = line._update_purchase_info() + # if updated_vals: + # line.write(updated_vals) # order._validate_delivery_amt() # order._check_total_margin_excl_third_party() # order._update_partner_details() @@ -3365,11 +3365,11 @@ class SaleOrder(models.Model): if any(field in vals for field in ["order_line", "client_order_ref"]): self._calculate_etrts_date() - for order in self: - for line in order.order_line: - updated_vals = line._update_purchase_info() - if updated_vals: - line.write(updated_vals) + # for order in self: + # for line in order.order_line: + # updated_vals = line._update_purchase_info() + # if updated_vals: + # line.write(updated_vals) return res -- cgit v1.2.3