summaryrefslogtreecommitdiff
path: root/indoteknik_custom/models
diff options
context:
space:
mode:
authorHafidBuroiroh <hafidburoiroh09@gmail.com>2026-03-06 14:24:00 +0700
committerHafidBuroiroh <hafidburoiroh09@gmail.com>2026-03-06 14:24:00 +0700
commitf687d197ead268040d7f396eb26ea0035a6dac35 (patch)
treea8e9cf9efa0cf38a51db89badbe383b5e0857afb /indoteknik_custom/models
parent8d953f913aceb97faa026253b65d6159759f5a62 (diff)
<hafid> change request sourcing job order
Diffstat (limited to 'indoteknik_custom/models')
-rw-r--r--indoteknik_custom/models/sourcing_job_order.py475
1 files changed, 317 insertions, 158 deletions
diff --git a/indoteknik_custom/models/sourcing_job_order.py b/indoteknik_custom/models/sourcing_job_order.py
index e015eaaa..6bb59c62 100644
--- a/indoteknik_custom/models/sourcing_job_order.py
+++ b/indoteknik_custom/models/sourcing_job_order.py
@@ -158,7 +158,6 @@ class SourcingJobOrder(models.Model):
if self.env.uid != self.create_uid.id and not self.env.user.has_group('indoteknik_custom.group_role_merchandiser'):
raise UserError("❌ Hanya Sales dan Merchandiser yang boleh mengedit Sourcing Job.")
- # --- Simpan data lama sebelum write (buat pembanding)
old_data = {}
for rec in self:
old_data[rec.id] = {
@@ -179,18 +178,15 @@ class SourcingJobOrder(models.Model):
for rec in self:
rec._log_product_assets_upload()
- # --- Bandingkan setelah write dan buat log
for rec in self:
changes = []
old = old_data.get(rec.id, {})
- # === Perubahan di field parent ===
if old.get('state') != rec.state:
changes.append(f"State: <b>{old.get('state')}</b> → <b>{rec.state}</b>")
if old.get('approval_sales') != rec.approval_sales:
changes.append(f"Approval Status: <b>{old.get('approval_sales')}</b> → <b>{rec.approval_sales}</b>")
- # === Perubahan di line ===
old_lines = old.get('line_data', {})
for line in rec.line_ids:
old_line = old_lines.get(line.id)
@@ -221,7 +217,6 @@ class SourcingJobOrder(models.Model):
joined = "<br/>".join(sub_changes)
changes.append(f"<b>{line.product_name}</b>:<br/>{joined}")
- # Post ke chatter
if changes:
message = "<br/><br/>".join(changes)
rec.message_post(
@@ -278,11 +273,16 @@ class SourcingJobOrderLine(models.Model):
order_id = fields.Many2one('sourcing.job.order', string='Job Order', ondelete='cascade')
product_id = fields.Many2one('product.product', string='Product', ondelete='cascade')
md_person_ids = fields.Many2one('res.users', string='MD Person', ondelete='cascade')
- product_name = fields.Char(string='Nama Barang', required=True)
+ brand_id = fields.Many2one('x_manufactures', string='Manufactures', ondelete='cascade')
+ so_id = fields.Many2one('sale.order', string='SO Number', tracking=True, readonly=True)
+ product_name_md = fields.Char(string='Nama Barang')
+ descriptions_md = fields.Text(string='Deskripsi Barang')
+
+ product_name = fields.Char(string='Nama Barang')
+ brand = fields.Char(string='Brand')
code = fields.Char(string='SKU')
budget = fields.Char(string='Expected Price')
note = fields.Text(string='Note Sourcing')
- brand = fields.Char(string='Brand')
attachment_type = fields.Selection([
('none', 'None'),
('pdf', '.PDF'),
@@ -293,6 +293,7 @@ class SourcingJobOrderLine(models.Model):
product_attachment_img = fields.Binary(string="Product Attachment")
product_attachment_other = fields.Binary(string="Product Attachment")
product_attachment_filename = fields.Char(string="Filename")
+
descriptions = fields.Text(string='Deskripsi / Spesifikasi')
reason = fields.Text(string='Reason Unavailable')
sla = fields.Char(string='SLA Product')
@@ -309,8 +310,7 @@ class SourcingJobOrderLine(models.Model):
('draft', 'Unsource'),
('sourcing', 'On Sourcing'),
('sent', 'Approval Sent'),
- ('approve', 'Approved'),
- ('done', 'Done Sourcing'),
+ ('approve', 'Done Sourcing'),
('cancel', 'Unavailable')
], default='draft', tracking=True)
product_type = fields.Selection([
@@ -323,16 +323,68 @@ class SourcingJobOrderLine(models.Model):
string="Show for Sales",
compute="_compute_show_for_sales",
)
+ show_salesperson = fields.Many2one(
+ 'res.users',
+ string="Salesperson",
+ )
+
+ so_state = fields.Selection(
+ [
+ ('draft', 'Draft'),
+ ('cancel', 'Cancel'),
+ ('sale', 'Sale')
+ ],
+ string="SO State",
+ compute="_compute_so_data"
+ )
+
+ so_name = fields.Char(
+ string="SO Number",
+ compute="_compute_so_data"
+ )
+ is_md_person = fields.Boolean(
+ string="Is MD Person",
+ compute="_compute_is_md_person"
+ )
+ is_receiver = fields.Boolean(
+ string="Is MD Receiver",
+ compute="_compute_is_md_person"
+ )
+
+ is_given = fields.Boolean(string='Is Given', tracking=True)
+ given_to_id = fields.Many2one('res.users', string='Given To')
+ previous_md_id = fields.Many2one('res.users', string='Previous MD')
@api.depends('quantity', 'price', 'tax_id')
def _compute_subtotal(self):
- """Menghitung subtotal termasuk pajak."""
for line in self:
subtotal = (line.quantity or 0.0) * (line.price or 0.0)
+
if line.tax_id:
- subtotal += subtotal * (line.tax_id.amount / 100)
+ tax = line.tax_id.amount / 100
+
+ if line.tax_id.price_include:
+ subtotal = subtotal / (1 + tax)
+
line.subtotal = subtotal
+ @api.depends('order_id.so_id.user_id', 'order_id.so_id.state', 'order_id.so_id.name')
+ def _compute_so_data(self):
+ for rec in self:
+ so = rec.order_id.so_id
+ if so:
+ rec.so_state = so.state if so.state in ['draft', 'sale'] else False
+ rec.so_name = so.name
+ else:
+ rec.so_state = False
+ rec.so_name = False
+
+ def _compute_is_md_person(self):
+ current_user = self.env.user
+ for rec in self:
+ rec.is_md_person = bool(rec.md_person_ids == current_user)
+ rec.is_receiver = bool(rec.given_to_id == current_user)
+
@api.constrains('product_type', 'product_category', 'product_class')
def _check_required_fields_for_md(self):
for rec in self:
@@ -356,6 +408,9 @@ class SourcingJobOrderLine(models.Model):
order = self.env['sourcing.job.order'].browse(order_id)
if order.state == 'taken' and order.line_ids.md_person_ids != self.env.user:
raise UserError("❌ SJO sudah taken. Tidak boleh tambah line.")
+ if order.so_id:
+ vals['so_id'] = order.so_id.id
+ vals['show_salesperson'] = order.so_id.user_id.id
rec = super().create(vals)
return rec
@@ -388,7 +443,7 @@ class SourcingJobOrderLine(models.Model):
if total == 1:
line = lines[0]
- if line.state == 'done':
+ if line.state == 'approve':
order.state = 'done'
elif line.state == 'cancel':
order.state = 'cancel'
@@ -399,9 +454,9 @@ class SourcingJobOrderLine(models.Model):
states = lines.mapped('state')
all_cancel = all(s == 'cancel' for s in states)
- all_done_or_cancel = all(s in ['done', 'cancel'] for s in states)
- any_done = any(s == 'done' for s in states)
- any_progress = any(s not in ['done', 'cancel', 'draft'] for s in states)
+ all_done_or_cancel = all(s in ['approve', 'cancel'] for s in states)
+ any_done = any(s == 'approve' for s in states)
+ any_progress = any(s not in ['approve', 'cancel', 'draft'] for s in states)
if all_cancel:
order.state = 'cancel'
@@ -496,10 +551,12 @@ class SourcingJobOrderLine(models.Model):
for line in self:
if line.state != 'sourcing':
- raise UserError(f"⚠️ Produk '{line.product_name}' bukan status Sourcing.")
+ raise UserError(f"⚠️ Produk '{line.product_name_md}' bukan status Sourcing.")
if (
not line.vendor_id
+ or not line.product_name_md
+ or not brand_id
or not line.price or line.price <= 0
or not line.tax_id
or not line.subtotal or line.subtotal <= 0
@@ -507,7 +564,7 @@ class SourcingJobOrderLine(models.Model):
or not line.product_category
or not line.product_class
):
- raise UserError(f"❌ Data produk '{line.product_name}' belum lengkap.")
+ raise UserError(f"❌ Data produk '{line.product_name_md}' belum lengkap.")
activity_type = self.env.ref('mail.mail_activity_data_todo')
@@ -519,10 +576,10 @@ class SourcingJobOrderLine(models.Model):
line.activity_schedule(
activity_type_id=activity_type.id,
user_id=job.create_uid.id,
- note=f"{self.env.user.name} meminta approval untuk produk '{line.product_name}' di SJO '{job.name}'.",
+ note=f"{self.env.user.name} meminta approval untuk produk '{line.product_name_md}' di SJO '{job.name}'.",
)
- approved_lines_text += f"<li>{line.product_name} - {line.price or 0}</li>"
+ approved_lines_text += f"<li>{line.product_name_md} - {line.price or 0}</li>"
line.message_post(
body=f"📤 <b>Request approval dikirim (Multi)</b>",
@@ -543,7 +600,7 @@ class SourcingJobOrderLine(models.Model):
title="Multi Request Sent"
)
- return {'type': 'ir.actions.client', 'tag': 'reload'}
+ # return {'type': 'ir.actions.client', 'tag': 'reload'}
def action_ask_approval(self):
@@ -562,6 +619,8 @@ class SourcingJobOrderLine(models.Model):
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
@@ -578,14 +637,14 @@ class SourcingJobOrderLine(models.Model):
line.activity_schedule(
activity_type_id=activity_type.id,
user_id=job.create_uid.id,
- note=f"{self.env.user.name} meminta approval untuk produk '{line.product_name}' di SJO '{job.name}'.",
+ note=f"{self.env.user.name} meminta approval untuk produk '{line.product_name_md}' di SJO '{job.name}'.",
)
line.message_post(
body=(
f"📤 <b>Request approval dikirim</b><br/>"
f"Kepada: <b>{job.create_uid.name}</b><br/>"
- f"Produk: <b>{line.product_name}</b>"
+ f"Produk: <b>{line.product_name_md}</b>"
),
subtype_xmlid="mail.mt_comment"
)
@@ -594,7 +653,7 @@ class SourcingJobOrderLine(models.Model):
body=(
f"📤 <b>Request approval line</b><br/>"
f"<ul>"
- f"<li><b>Produk:</b> {line.product_name}</li>"
+ f"<li><b>Produk:</b> {line.product_name_md}</li>"
f"<li><b>MD:</b> {self.env.user.name}</li>"
f"<li><b>Vendor:</b> {line.vendor_id.display_name if line.vendor_id else '-'}</li>"
f"<li><b>Harga:</b> {line.price or 0}</li>"
@@ -604,7 +663,7 @@ class SourcingJobOrderLine(models.Model):
)
self.env.user.notify_success(
- message=f"Request approval untuk '{line.product_name}' dikirim ke {job.create_uid.name}",
+ message=f"Request approval untuk '{line.product_name_md}' dikirim ke {job.create_uid.name}",
title="Request Sent",
)
@@ -615,7 +674,7 @@ class SourcingJobOrderLine(models.Model):
msg_text = (
f"📢 <b>Request Approval Produk</b>\n\n"
f"🧾 <b>Sourcing Job:</b> <a href='{url}'>📎 {job.name}</a>\n"
- f"📦 <b>Produk:</b> {line.product_name}\n"
+ f"📦 <b>Produk:</b> {line.product_name_md}\n"
f"👤 <b>MD:</b> {self.env.user.name}\n"
f"💰 <b>Harga:</b> {line.price or 0}\n"
f"📅 <b>Tanggal:</b> {fields.Datetime.now().strftime('%d-%m-%Y %H:%M')}\n\n"
@@ -637,13 +696,101 @@ class SourcingJobOrderLine(models.Model):
return {'type': 'ir.actions.client', 'tag': 'reload'}
def action_approve_approval(self):
+ ProductProduct = self.env['product.product']
+ PurchasePricelist = self.env['purchase.pricelist']
+ SaleOrderLine = self.env['sale.order.line']
+
for rec in self:
job = rec.order_id
if job.create_uid != self.env.user:
raise UserError("❌ Hanya pembuat Sourcing Job yang bisa approve.")
- rec.state = 'approve'
+ rec.write({'state': 'approve'})
+
+ product = False
+ if rec.code:
+ product = ProductProduct.search([
+ ('default_code', '=', rec.code),
+ ('active', '=', True)
+ ], limit=1)
+
+ if product:
+ rec.product_id = product.id
+
+ self.env.user.notify_warning(
+ message=f"SKU {rec.code} sudah ada. Tidak dibuat ulang.",
+ title="SKU Exists"
+ )
+
+ else:
+ type_map = {
+ 'servis': 'service',
+ 'product': 'product',
+ 'consu': 'consu',
+ }
+
+ product = ProductProduct.create({
+ 'name': rec.product_name_md,
+ 'default_code': rec.code or False,
+ 'description': rec.descriptions_md or '',
+ 'type': type_map.get(rec.product_type, 'product'),
+ 'categ_id': rec.product_category.id if rec.product_category else False,
+ 'x_manufacture': rec.brand_id.id if rec.brand_id else False,
+ 'standard_price': rec.price or 0,
+ 'public_categ_ids': [(6, 0, rec.product_class.ids)] if rec.product_class else False,
+ 'active': True,
+ 'sourcing_job_id': job.id if job else False,
+ })
+
+ if not rec.code:
+ padded_id = str(product.id).zfill(7)
+ sku_auto = f"IT.{padded_id}"
+ product.default_code = sku_auto
+ rec.code = sku_auto
+
+ rec.product_id = product.id
+
+ jakarta_tz = rec.order_id._get_jakarta_today()
+
+ purchase_price = PurchasePricelist.search([
+ ('product_id', '=', product.id),
+ ('vendor_id', '=', rec.vendor_id.id),
+ ], order="human_last_update desc", limit=1)
+
+ pricelist_vals = {
+ 'product_id': product.id,
+ 'vendor_id': rec.vendor_id.id,
+ 'product_price': rec.price or 0,
+ 'include_price': rec.price or 0,
+ 'taxes_product_id': rec.tax_id.id if rec.tax_id else False,
+ 'brand_id': product.x_manufacture.id if product.x_manufacture else False,
+ 'human_last_update': jakarta_tz,
+ 'is_winner': True,
+ }
+
+ if not purchase_price:
+ PurchasePricelist.create(pricelist_vals)
+
+ elif purchase_price.product_price != (rec.price or 0):
+ purchase_price.write(pricelist_vals)
+
+ if rec.so_id and not rec.exported_to_so:
+ so = rec.so_id
+
+ so_line_new = SaleOrderLine.new({
+ "order_id": so.id,
+ "product_id": product.id,
+ "product_uom_qty": rec.quantity or 1,
+ "price_unit": rec.price or 0,
+ "name": rec.product_name_md,
+ })
+
+ so_line_new.product_id_change()
+ vals = SaleOrderLine._convert_to_write(so_line_new._cache)
+ SaleOrderLine.create(vals)
+
+ rec.exported_to_so = True
activities = self.env['mail.activity'].search([
('res_model', '=', rec._name),
@@ -663,7 +810,7 @@ class SourcingJobOrderLine(models.Model):
body=(
f"✅ <b>Approval produk disetujui</b><br/>"
f"<ul>"
- f"<li><b>Produk:</b> {rec.product_name}</li>"
+ f"<li><b>Produk:</b> {rec.product_name_md}</li>"
f"<li><b>Vendor:</b> {rec.vendor_id.display_name if rec.vendor_id else '-'}</li>"
f"<li><b>Harga:</b> {rec.price or 0}</li>"
f"<li><b>Disetujui oleh:</b> {self.env.user.name}</li>"
@@ -674,17 +821,20 @@ class SourcingJobOrderLine(models.Model):
if rec.md_person_ids:
rec.md_person_ids.notify_success(
- message=f"Produk '{rec.product_name}' telah di-approve sales.",
+ message=f"Produk '{rec.product_name_md}' telah di-approve sales.",
title="Approval Approved"
)
self.env.user.notify_success(
- message=f"Produk '{rec.product_name}' berhasil di-approve.",
+ message=f"Produk '{rec.product_name_md}' berhasil di-approve.",
title="Approved"
)
return {'type': 'ir.actions.client', 'tag': 'reload'}
+ def action_multi_approve(self):
+ self.action_approve_approval()
+
def action_reject_approval(self):
self.ensure_one()
@@ -703,132 +853,6 @@ class SourcingJobOrderLine(models.Model):
}
}
- def action_convert(self):
- ProductProduct = self.env['product.product']
- PurchasePricelist = self.env['purchase.pricelist']
-
- for line in self:
- job = line.order_id
-
- if line.md_person_ids and line.md_person_ids != self.env.user:
- raise UserError("❌ Hanya MD Person pada line ini yang bisa convert.")
-
- if line.state != 'approve':
- raise UserError("⚠️ Convert hanya bisa setelah sales approve.")
-
- existing = False
- if line.code:
- existing = ProductProduct.search([('default_code', '=', line.code)], limit=1)
-
- if existing:
- line.product_id = existing.id
- line.state = 'done'
-
- job.message_post(
- body=f"ℹ️ SKU <b>{line.code}</b> sudah ada. Produk existing dipakai.",
- subtype_xmlid="mail.mt_comment",
- )
-
- line.message_post(
- body=(
- f"ℹ️ <b>SKU sudah ada di sistem</b><br/>"
- f"Produk existing: <b>{existing.name}</b><br/>"
- f"Tidak dibuat ulang, langsung linked."
- ),
- subtype_xmlid="mail.mt_comment",
- )
-
- self.env.user.notify_warning(
- message=f"SKU {line.code} sudah ada. Tidak dibuat ulang.",
- title="SKU Exists"
- )
- continue
-
- type_map = {
- 'servis': 'service',
- 'product': 'product',
- 'consu': 'consu',
- }
-
- manufactures = self.env['x_manufactures']
- if line.brand:
- manufactures = manufactures.search([('x_name', 'ilike', line.brand)], limit=1)
-
- new_product = ProductProduct.create({
- 'name': line.product_name,
- 'default_code': line.code or False,
- 'description': line.descriptions or '',
- 'type': type_map.get(line.product_type, 'product'),
- 'categ_id': line.product_category.id if line.product_category else False,
- 'x_manufacture': manufactures.id if manufactures else False,
- 'standard_price': line.price or 0,
- 'public_categ_ids': [(6, 0, line.product_class.ids)] if line.product_class else False,
- 'active': True,
- 'sourcing_job_id': job.id if job else False,
- })
-
- if not line.code:
- padded_id = str(new_product.id).zfill(7)
- sku_auto = f"IT.{padded_id}"
- new_product.default_code = sku_auto
- line.code = sku_auto
-
- line.product_id = new_product.id
-
- jakarta_tz = line.order_id._get_jakarta_today()
-
- pricelist_vals = {
- 'product_id': new_product.id,
- 'vendor_id': line.vendor_id.id,
- 'system_price': line.price or 0,
- 'product_price': line.price or 0,
- 'include_price': line.price or 0,
- 'taxes_system_id': line.tax_id.id if line.tax_id else False,
- 'taxes_product_id': line.tax_id.id if line.tax_id else False,
- 'brand_id': new_product.x_manufacture.id if new_product.x_manufacture else False,
- 'system_last_update': jakarta_tz,
- 'human_last_update': jakarta_tz,
- 'is_winner': True,
- }
-
- PurchasePricelist.create(pricelist_vals)
-
- job.message_post(
- body=(
- f"🆕 <b>Produk berhasil dibuat dari sourcing line</b><br/>"
- f"<ul>"
- f"<li><b>Produk:</b> {new_product.name}</li>"
- f"<li><b>SKU:</b> {line.code}</li>"
- f"<li><b>Vendor:</b> {line.vendor_id.display_name if line.vendor_id else '-'}</li>"
- f"<li><b>Harga:</b> {line.price or 0}</li>"
- f"</ul>"
- f"<i>Produk sudah masuk ke master product & pricelist.</i>"
- ),
- subtype_xmlid="mail.mt_comment"
- )
- line.message_post(
- body=(
- f"✅ <b>Produk berhasil dikonversi</b><br/>"
- f"<ul>"
- f"<li><b>Nama Produk:</b> {new_product.name}</li>"
- f"<li><b>SKU:</b> {line.code}</li>"
- f"<li><b>Vendor:</b> {line.vendor_id.display_name if line.vendor_id else '-'}</li>"
- f"<li><b>Harga Beli:</b> {line.price or 0}</li>"
- f"</ul>"
- f"<i>Produk sudah masuk ke master product & pricelist.</i>"
- ),
- subtype_xmlid="mail.mt_comment"
- )
-
- line.state = 'done'
-
- self.env.user.notify_success(
- message=f"Produk {new_product.name} berhasil dikonversi.",
- title="Convert Success"
- )
-
- return {'type': 'ir.actions.client', 'tag': 'reload'}
-
def action_cancel(self):
for rec in self:
if self.env.user != rec.md_person_ids:
@@ -872,11 +896,24 @@ class SourcingJobOrderLine(models.Model):
if not product:
return
template = product.product_tmpl_id
+ attribute_values = product.product_template_attribute_value_ids.mapped(
+ 'product_attribute_value_id.name'
+ )
+ attribute_values_str = ', '.join(attribute_values) if attribute_values else ''
+
+ # generate line name
+ line_name = (
+ ('[' + product.default_code + '] ' if product.default_code else '') +
+ (product.name or '') +
+ (' (' + attribute_values_str + ')' if attribute_values_str else '') +
+ (' ' + product.short_spesification if product.short_spesification else '')
+ )
rec.code = product.default_code or rec.code
- rec.product_name = product.name or rec.product_name
+ rec.product_name_md = product.name or rec.product_name_md
+ rec.descriptions_md = line_name.strip() or rec.descriptions_md
rec.product_type = template.type or rec.product_type
- rec.brand = product.x_manufacture.x_name or rec.brand
+ rec.brand_id = product.x_manufacture.id or rec.brand_id
rec.product_category = template.categ_id.id or rec.product_category
rec.product_class = [(6, 0, template.public_categ_ids.ids)] if template.public_categ_ids else []
@@ -946,6 +983,128 @@ class SourcingJobOrderLine(models.Model):
}
}
+ def action_open_give_wizard(self):
+ self.ensure_one()
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': 'Give To MD',
+ 'res_model': 'sjo.give.wizard',
+ 'view_mode': 'form',
+ 'target': 'new',
+ 'context': {
+ 'default_line_id': self.id,
+ }
+ }
+
+ def action_open_reject_given_wizard(self):
+ self.ensure_one()
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': 'Reject Request Give SJO Line',
+ 'res_model': 'sjo.reject.give.wizard',
+ 'view_mode': 'form',
+ 'target': 'new',
+ 'context': {
+ 'default_line_id': self.id,
+ }
+ }
+
+ def action_take_given(self):
+ for rec in self:
+ if self.env.user != rec.given_to_id:
+ raise UserError("Hanya MD yang diberikan Request yang bisa Take Sourcing")
+
+ old_owner = rec.previous_md_id.name
+ new_owner = rec.given_to_id.name
+ receiver = rec.given_to_id
+
+ rec.with_context(bypass_md_check=True).write({
+ 'md_person_ids': rec.given_to_id.id,
+ 'given_to_id': False,
+ 'previous_md_id': False,
+ 'is_given': False,
+ })
+
+ rec._unlink_give_activity(receiver)
+ rec.message_post(
+ body=f"<b>{new_owner}<b/> Menerima Request Sourcing dari <b>{old_owner}<b/>"
+ )
+
+class SjoGiveWizard(models.TransientModel):
+ _name = 'sjo.give.wizard'
+ _description = 'Give SJO Line Wizard'
+
+ line_id = fields.Many2one('sourcing.job.order.line')
+ md_id = fields.Many2one('res.users', string='Give To', required=True, domain=lambda self: [
+ ('groups_id', 'in', self.env.ref('base.group_user').ids),
+ ('groups_id', 'in', self.env.ref('indoteknik_custom.group_role_merchandiser').ids),
+ ('active', '=', True)
+ ])
+
+ def action_confirm(self):
+ self.ensure_one()
+
+ line = self.line_id
+
+ if self.env.user != line.md_person_ids:
+ raise UserError("Hanya Md Target yang bisa Confirm Give Sourcing")
+
+ old_owner = line.md_person_ids.name
+ new_owner = self.md_id.name
+
+ line.write({
+ 'previous_md_id': line.md_person_ids.id,
+ 'given_to_id': self.md_id.id,
+ 'is_given': True,
+ })
+
+ activity_type = self.env.ref('mail.mail_activity_data_todo')
+ line.activity_schedule(
+ activity_type_id=activity_type.id,
+ user_id=self.md_id.id,
+ note="SJO Line diberikan ke Anda. Silakan Take atau Reject.",
+ )
+
+ line.message_post(
+ body=f"""
+ <b>MD {old_owner}</b> Mengirim Request Peralihan Sourcing Ke <b>{new_owner}</b>
+ """,
+ subtype_xmlid="mail.mt_comment"
+ )
+
+class SjoRejectGiveWizard(models.TransientModel):
+ _name = 'sjo.reject.give.wizard'
+ _description = 'Reject Given SJO Line Wizard'
+
+ line_id = fields.Many2one('sourcing.job.order.line', required=True)
+ reason = fields.Text(string="Reject Reason", required=True)
+
+ def action_confirm(self):
+ self.ensure_one()
+ line = self.line_id
+
+ if self.env.user != line.given_to_id:
+ raise UserError("Hanya Penerima Request yang bisa Reject Give")
+
+ from_md = line.previous_md_id.name or "-"
+ receiver = line.given_to_id
+ rejector = self.env.user.name
+
+ line._unlink_give_activity(receiver)
+
+ line.with_context(bypass_md_check=True).write({
+ 'given_to_id': False,
+ 'is_given': False,
+ })
+
+ line.message_post(
+ body=f"""
+ Request Peralihan dari <b>{from_md}</b> Rejected by <b>{rejector}</b><br/>
+ Alasan: {self.reason}
+ """,
+ subtype_xmlid="mail.mt_comment"
+ )
+
class WizardExportSJOtoSO(models.TransientModel):
_name = "wizard.export.sjo.to.so"
_description = "Wizard Export SJO Products to SO"
@@ -970,7 +1129,7 @@ class WizardExportSJOtoSO(models.TransientModel):
("order_id", "=", sjo_id),
("product_id", "!=", False),
("exported_to_so", "=", False),
- ("state", "=", "done"), # optional: cuma yg done
+ ("state", "=", "approve"), # optional: cuma yg done
])
res["line_ids"] = [(6, 0, lines.ids)]