diff options
| author | HafidBuroiroh <hafidburoiroh09@gmail.com> | 2026-03-06 14:24:00 +0700 |
|---|---|---|
| committer | HafidBuroiroh <hafidburoiroh09@gmail.com> | 2026-03-06 14:24:00 +0700 |
| commit | f687d197ead268040d7f396eb26ea0035a6dac35 (patch) | |
| tree | a8e9cf9efa0cf38a51db89badbe383b5e0857afb /indoteknik_custom/models | |
| parent | 8d953f913aceb97faa026253b65d6159759f5a62 (diff) | |
<hafid> change request sourcing job order
Diffstat (limited to 'indoteknik_custom/models')
| -rw-r--r-- | indoteknik_custom/models/sourcing_job_order.py | 475 |
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)] |
