summaryrefslogtreecommitdiff
path: root/indoteknik_custom/models/sourcing_job_order.py
diff options
context:
space:
mode:
authorHafidBuroiroh <hafidburoiroh09@gmail.com>2026-03-10 10:46:23 +0700
committerHafidBuroiroh <hafidburoiroh09@gmail.com>2026-03-10 10:46:23 +0700
commitf58fe20f96995228651a5a1a09c8c17a23e13838 (patch)
treedc6700fe931d229523c478ac6f290b3e45ae871c /indoteknik_custom/models/sourcing_job_order.py
parentd91af3da1edea3c6b8074726e5306ea42a7c0a4b (diff)
<hafid> final change request
Diffstat (limited to 'indoteknik_custom/models/sourcing_job_order.py')
-rw-r--r--indoteknik_custom/models/sourcing_job_order.py126
1 files changed, 93 insertions, 33 deletions
diff --git a/indoteknik_custom/models/sourcing_job_order.py b/indoteknik_custom/models/sourcing_job_order.py
index 6bb59c62..0e5334a8 100644
--- a/indoteknik_custom/models/sourcing_job_order.py
+++ b/indoteknik_custom/models/sourcing_job_order.py
@@ -89,11 +89,13 @@ class SourcingJobOrder(models.Model):
@api.depends('eta_sales', 'eta_complete', 'create_date', 'state')
def _compute_progress_status(self):
for rec in self:
- if rec.eta_sales:
- # Ada tanggal expected
- if rec.state == 'taken':
- rec.progress_status = '🟡 On Track'
- elif rec.state == 'done' and rec.eta_complete:
+
+ if rec.state == 'cancel':
+ rec.progress_status = '⚫ Cancelled'
+ continue
+
+ if rec.state == 'done':
+ if rec.eta_sales and rec.eta_complete:
delta = (rec.eta_complete - rec.eta_sales).days
if delta < 0:
rec.progress_status = f'🟢 Early {abs(delta)} hari'
@@ -101,22 +103,15 @@ class SourcingJobOrder(models.Model):
rec.progress_status = '🔵 Ontime'
else:
rec.progress_status = f'🔴 Delay {delta} hari'
- elif rec.state == 'cancel':
- rec.progress_status = '⚫ Cancelled'
- else:
- rec.progress_status = '🟡 On Track'
- else:
- # Tidak ada ETA, hitung durasi
- if rec.state == 'done' and rec.eta_complete:
- if rec.create_date:
- durasi = (rec.eta_complete - rec.create_date.date()).days
- rec.progress_status = f'✅ Selesai dalam {durasi} hari'
- else:
- rec.progress_status = '✅ Selesai'
- elif rec.state == 'cancel':
- rec.progress_status = '⚫ Cancelled'
+ elif rec.create_date and rec.eta_complete:
+ durasi = (rec.eta_complete - rec.create_date.date()).days
+ rec.progress_status = f'✅ Selesai dalam {durasi} hari'
else:
- rec.progress_status = '🟡 On Track'
+ rec.progress_status = '✅ Selesai'
+ continue
+
+ if rec.state in ['taken', 'partial', 'draft']:
+ rec.progress_status = '🟡 On Track'
@api.depends('line_ids.price', 'line_ids.vendor_id')
def _compute_has_price_in_lines(self):
@@ -413,6 +408,7 @@ class SourcingJobOrderLine(models.Model):
vals['show_salesperson'] = order.so_id.user_id.id
rec = super().create(vals)
+ rec._check_line_limit()
return rec
def write(self, vals):
@@ -427,8 +423,30 @@ class SourcingJobOrderLine(models.Model):
res = super().write(vals)
if 'state' in vals:
self._update_parent_state()
+ self._check_line_limit()
return res
+ def _check_line_limit(self):
+ for rec in self:
+ if not rec.order_id or not rec.order_id.so_id:
+ continue
+
+ so = rec.order_id.so_id
+
+ so_line_count = len(so.order_line)
+
+ sourcing_lines = self.search([
+ ('order_id', '=', rec.order_id.id),
+ ('state', '!=', 'cancel')
+ ])
+
+ if len(sourcing_lines) > so_line_count:
+ raise UserError(
+ f"Jumlah Sourcing Line tidak boleh melebihi Sales Order Line.\n\n"
+ f"Sales Order Line : {so_line_count}\n"
+ f"Sourcing Line : {len(sourcing_lines)}"
+ )
+
def _update_parent_state(self):
for rec in self:
order = rec.order_id
@@ -617,18 +635,40 @@ class SourcingJobOrderLine(models.Model):
if line.state != 'sourcing':
raise UserError("⚠️ Hanya line status 'Sourcing' yang bisa minta approval.")
- if (
- not line.vendor_id
- or not line.product_name_md
- or not line.brand_id
- or not line.price or line.price <= 0
- or not line.tax_id
- or not line.subtotal or line.subtotal <= 0
- or not line.product_type
- or not line.product_category
- or not line.product_class
- ):
- raise UserError("❌ Lengkapi data sebelum Ask Approval sales")
+ missing_fields = []
+
+ if not line.vendor_id:
+ missing_fields.append("Vendor")
+
+ if not line.product_name_md:
+ missing_fields.append("Product Name")
+
+ if not line.brand_id:
+ missing_fields.append("Manufactures")
+
+ if not line.price or line.price <= 0:
+ missing_fields.append("Price")
+
+ if not line.tax_id:
+ missing_fields.append("Tax")
+
+ if not line.subtotal or line.subtotal <= 0:
+ missing_fields.append("Subtotal")
+
+ if not line.product_type:
+ missing_fields.append("Product Type")
+
+ if not line.product_category:
+ missing_fields.append("Product Category")
+
+ if not line.product_class:
+ missing_fields.append("Product Class")
+
+ if missing_fields:
+ raise UserError(
+ "❌ Lengkapi data berikut sebelum Ask Approval Sales:\n- " +
+ "\n- ".join(missing_fields)
+ )
line.state = 'sent'
@@ -730,7 +770,7 @@ class SourcingJobOrderLine(models.Model):
'consu': 'consu',
}
- product = ProductProduct.create({
+ product = ProductProduct.with_context(from_sourcing_approval=True).create({
'name': rec.product_name_md,
'default_code': rec.code or False,
'description': rec.descriptions_md or '',
@@ -751,6 +791,11 @@ class SourcingJobOrderLine(models.Model):
rec.product_id = product.id
+ self.env.user.notify_success(
+ message=f"Produk baru '{product.name}' berhasil dibuat dengan SKU {product.default_code}.",
+ title="Product Created"
+ )
+
jakarta_tz = rec.order_id._get_jakarta_today()
purchase_price = PurchasePricelist.search([
@@ -830,9 +875,24 @@ class SourcingJobOrderLine(models.Model):
title="Approved"
)
+ so = self.mapped('so_id')[:1]
+ if so:
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': 'Sales Order',
+ 'res_model': 'sale.order',
+ 'view_mode': 'form',
+ 'res_id': so.id,
+ 'target': 'current',
+ }
+
return {'type': 'ir.actions.client', 'tag': 'reload'}
def action_multi_approve(self):
+ so_ids = self.mapped('so_id').ids
+
+ if len(set(so_ids)) > 1:
+ raise UserError("❌ Multi approve hanya bisa dilakukan jika semua line berasal dari Sales Order yang sama.")
self.action_approve_approval()
def action_reject_approval(self):