diff options
19 files changed, 299 insertions, 250 deletions
diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py index 08d91738..449bd90b 100644 --- a/indoteknik_custom/models/approval_payment_term.py +++ b/indoteknik_custom/models/approval_payment_term.py @@ -69,8 +69,8 @@ class ApprovalPaymentTerm(models.Model): return res def _track_changes_for_user_688(self, vals, old_values_dict): - if self.env.user.id != 688: - return + # if self.env.user.id != 688: + # return tracked_fields = {"blocking_stage", "warning_stage", "property_payment_term_id"} @@ -106,7 +106,8 @@ class ApprovalPaymentTerm(models.Model): if changes: timestamp = fields.Datetime.now().strftime('%Y-%m-%d %H:%M:%S') - rec.change_log_688 = f"{timestamp} - Perubahan oleh Widya:\n" + "\n".join(changes) + user = self.env.user + rec.change_log_688 = f"{timestamp} - Perubahan oleh {user.name}:\n" + "\n".join(changes) @staticmethod @@ -172,7 +173,7 @@ class ApprovalPaymentTerm(models.Model): 'warning_stage': self.warning_stage, 'active_limit': self.active_limit, 'property_payment_term_id': self.property_payment_term_id.id, - 'is_locked_cbd': False, + 'is_cbd_locked': False, }) self.approve_date = datetime.utcnow() self.state = 'approved' diff --git a/indoteknik_custom/models/dunning_run.py b/indoteknik_custom/models/dunning_run.py index 5a6aebac..9feea1d1 100644 --- a/indoteknik_custom/models/dunning_run.py +++ b/indoteknik_custom/models/dunning_run.py @@ -1,6 +1,6 @@ from odoo import models, api, fields from odoo.exceptions import AccessError, UserError, ValidationError -from datetime import timedelta +from datetime import timedelta, date import logging @@ -149,4 +149,5 @@ class DunningRunLine(models.Model): total_amt = fields.Float(string='Total Amount') open_amt = fields.Float(string='Open Amount') due_date = fields.Date(string='Due Date') + payment_term = fields.Many2one('account.payment.term', related='invoice_id.invoice_payment_term_id', string='Payment Term') diff --git a/indoteknik_custom/models/logbook_sj.py b/indoteknik_custom/models/logbook_sj.py index 75b2622f..0cda9c8b 100644 --- a/indoteknik_custom/models/logbook_sj.py +++ b/indoteknik_custom/models/logbook_sj.py @@ -24,6 +24,7 @@ class LogbookSJ(models.TransientModel): } report_logbook = self.env['report.logbook.sj'].create([parameters_header]) + seq=1 for line in logbook_line: picking = self.env['stock.picking'].search([('picking_code', '=', line.name)], limit=1) if not picking: @@ -43,9 +44,11 @@ class LogbookSJ(models.TransientModel): 'tracking_no': stock.delivery_tracking_no, 'partner_id': parent_id, 'report_logbook_sj_id': report_logbook.id, - 'note': line.note + 'note': line.note, + 'line_num': seq } self.env['report.logbook.sj.line'].create([data]) + seq += 1 report_logbook_ids.append(report_logbook.id) line.unlink() diff --git a/indoteknik_custom/models/manufacturing.py b/indoteknik_custom/models/manufacturing.py index aea01362..f986fd4f 100644 --- a/indoteknik_custom/models/manufacturing.py +++ b/indoteknik_custom/models/manufacturing.py @@ -4,54 +4,56 @@ import logging _logger = logging.getLogger(__name__) + class Manufacturing(models.Model): _inherit = 'mrp.production' unbuild_counter = fields.Integer(string='Unbuild Counter', default=0, help='For restrict unbuild more than once') - + def action_confirm(self): if self._name != 'mrp.production': return super(Manufacturing, self).action_confirm() if not self.env.user.is_purchasing_manager: raise UserError("Hanya bisa di confirm oleh Purchasing Manager") - + # if self.location_src_id.id != 75: # raise UserError('Component Location hanya bisa di AS/Stock') # elif self.location_dest_id.id != 75: # raise UserError('Finished Product Location hanya bisa di AS/Stock') - + result = super(Manufacturing, self).action_confirm() return result - + def button_mark_done(self): if self._name != 'mrp.production': return super(Manufacturing, self).button_mark_done() # Check product category if self.product_id.categ_id.name != 'Finish Good': raise UserError('Tidak bisa di complete karna product category bukan Unit / Finish Good') - + if self.sale_order and self.sale_order.state != 'sale': raise UserError( ('Tidak bisa Mark as Done.\nSales Order "%s" (Nomor: %s) belum dikonfirmasi.') % (self.sale_order.partner_id.name, self.sale_order.name) ) - + for line in self.move_raw_ids: # if line.quantity_done > 0 and line.quantity_done != self.product_uom_qty: # raise UserError('Qty Consume per Line tidak sama dengan Qty to Produce') if line.forecast_availability != line.product_uom_qty: - raise UserError('Qty Reserved belum sesuai dengan yang seharusnya, product: %s' % line.product_id.display_name) + raise UserError( + 'Qty Reserved belum sesuai dengan yang seharusnya, product: %s' % line.product_id.display_name) result = super(Manufacturing, self).button_mark_done() return result - + def button_unbuild(self): if self._name != 'mrp.production': return super(Manufacturing, self).button_unbuild() - + if self.unbuild_counter >= 1: raise UserError('Tidak bisa unbuild lebih dari 1 kali') - + self.unbuild_counter = self.unbuild_counter + 1 result = super(Manufacturing, self).button_unbuild() diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py index 18811b85..e7e5c382 100755 --- a/indoteknik_custom/models/purchase_order.py +++ b/indoteknik_custom/models/purchase_order.py @@ -6,6 +6,7 @@ import logging from pytz import timezone, utc import io import base64 +from odoo.tools import lazy_property try: from odoo.tools.misc import xlsxwriter except ImportError: @@ -115,6 +116,19 @@ class PurchaseOrder(models.Model): compute='_compute_complete_bu_in_count' ) + show_description = fields.Boolean( + string='Show Description' + ) + + @api.onchange('show_description') + def onchange_show_description(self): + if self.show_description == True: + for line in self.order_line: + line.show_description = True + else: + for line in self.order_line: + line.show_description = False + def _compute_complete_bu_in_count(self): for order in self: if order.state not in ['done', 'cancel']: @@ -137,7 +151,7 @@ class PurchaseOrder(models.Model): def _compute_date_planned(self): """ date_planned = the earliest date_planned across all order lines. """ for order in self: - order.date_planned = False + order.date_planned = order.date_planned @api.constrains('date_planned') def constrains_date_planned(self): @@ -1066,8 +1080,11 @@ class PurchaseOrder(models.Model): # sticky=True # ) + has_bom = self.product_bom_id.id + has_manufacturing = self.manufacturing_id.id + if not self.from_apo: - if not self.matches_so and not self.env.user.is_purchasing_manager and not self.env.user.is_leader: + if not self.matches_so and not self.env.user.is_purchasing_manager and not self.env.user.is_leader and not has_bom and not has_manufacturing: raise UserError("Tidak ada link dengan SO, harus di confirm oleh Purchasing Manager") send_email = False diff --git a/indoteknik_custom/models/purchase_order_line.py b/indoteknik_custom/models/purchase_order_line.py index 315795d5..a3c3a33b 100755 --- a/indoteknik_custom/models/purchase_order_line.py +++ b/indoteknik_custom/models/purchase_order_line.py @@ -50,6 +50,7 @@ class PurchaseOrderLine(models.Model): cost_service_per_item = fields.Float(string='Biaya Jasa Per Item', compute='_compute_doc_delivery_amt') contribution_cost_service = fields.Float(string='Contribution Cost Service', compute='_compute_doc_delivery_amt') ending_price = fields.Float(string='Ending Price', compute='_compute_doc_delivery_amt') + show_description = fields.Boolean(string='Show Description', help="Show Description when print po", default=True) def _compute_doc_delivery_amt(self): for line in self: diff --git a/indoteknik_custom/models/report_logbook_sj.py b/indoteknik_custom/models/report_logbook_sj.py index 17119c12..66edbf99 100644 --- a/indoteknik_custom/models/report_logbook_sj.py +++ b/indoteknik_custom/models/report_logbook_sj.py @@ -1,3 +1,5 @@ +from operator import index + from odoo import models, fields, api from odoo.exceptions import UserError from pytz import timezone @@ -60,9 +62,30 @@ class ReportLogbookSJ(models.Model): self.state = 'terima_semua' else: raise UserError('Hanya Accounting yang bisa Approve') - + + + def write(self, vals): + res = super(ReportLogbookSJ, self).write(vals) + if 'report_logbook_sj_line' in vals or any(f in vals for f in ()): + self._resequence_lines() + return res + + def _resequence_lines(self): + for rec in self: + lines = rec.report_logbook_sj_line.sorted(key=lambda l: (l.line_num or 0, l.id)) + for idx, line in enumerate(lines, start=1): + if line.line_num != idx: + line.line_num = idx + + @api.onchange('report_logbook_sj_line') + def _onchange_report_logbook_sj_line(self): + self._resequence_lines() + +from odoo import models, fields, api + class ReportLogbookSJLine(models.Model): _name = 'report.logbook.sj.line' + _order = 'sequence, id' # urut default di UI & ORM (drag pakai sequence) name = fields.Char(string='SJ Number') driver_id = fields.Many2one(comodel_name='res.users', string='Driver') @@ -70,10 +93,41 @@ class ReportLogbookSJLine(models.Model): arrival_date = fields.Char(string='Arrival Date') carrier_id = fields.Many2one('delivery.carrier', string='Shipping Method') tracking_no = fields.Char(string='Tracking No') - logbook_sj_id = fields.Many2one('report.logbook.sj', string='Logbook SJ') # Corrected model name + + # NOTE: field ini duplikat relasi; pakai salah satu saja. + # kamu boleh hapus logbook_sj_id kalau tidak dipakai di tempat lain. + logbook_sj_id = fields.Many2one('report.logbook.sj', string='Logbook SJ') + partner_id = fields.Many2one('res.partner', string='Customer') picking_id = fields.Many2one('stock.picking', string='Picking') sale_id = fields.Many2one('sale.order', string='Sale Order') + report_logbook_sj_id = fields.Many2one('report.logbook.sj', string='Logbook SJ') not_exist = fields.Boolean(string='Not Exist') note = fields.Char(string='Note') + + sequence = fields.Integer(string='Sequence', default=0, index=True) + + line_num = fields.Integer(string='No', compute='_compute_line_num', store=False) + + @api.depends( + 'report_logbook_sj_id.report_logbook_sj_line', + 'report_logbook_sj_id.report_logbook_sj_line.sequence' + ) + def _compute_line_num(self): + for parent in self.mapped('report_logbook_sj_id'): + lines = parent.report_logbook_sj_line.sorted(key=lambda l: (l.sequence or 0, l.id)) + for i, l in enumerate(lines, start=1): + l.line_num = i + for rec in self.filtered(lambda r: not r.report_logbook_sj_id): + rec.line_num = 0 + + @api.model + def create(self, vals): + if not vals.get('sequence') and vals.get('report_logbook_sj_id'): + last = self.search( + [('report_logbook_sj_id', '=', vals['report_logbook_sj_id'])], + order='sequence desc, id desc', limit=1 + ) + vals['sequence'] = (last.sequence or 0) + 1 + return super().create(vals) diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 76d4d7e7..136663ba 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -234,9 +234,9 @@ class SaleOrder(models.Model): customer_type = fields.Selection([ ('pkp', 'PKP'), ('nonpkp', 'Non PKP') - ], required=True, compute='_compute_partner_field') - sppkp = fields.Char(string="SPPKP", required=True, tracking=True, compute='_compute_partner_field') - npwp = fields.Char(string="NPWP", required=True, tracking=True, compute='_compute_partner_field') + ], related="partner_id.customer_type", string="Customer Type", readonly=True) + sppkp = fields.Char(string="SPPKP", related="partner_id.sppkp") + npwp = fields.Char(string="NPWP", related="partner_id.npwp") purchase_total = fields.Monetary(string='Purchase Total', compute='_compute_purchase_total') voucher_id = fields.Many2one(comodel_name='voucher', string='Voucher', copy=False) applied_voucher_id = fields.Many2one(comodel_name='voucher', string='Applied Voucher', copy=False) @@ -1674,7 +1674,7 @@ class SaleOrder(models.Model): rec.expected_ready_to_ship = eta_date @api.depends("order_line.product_id", "date_order") - def _compute_etrts_date(self): # Function to calculate Estimated Ready To Ship Date + def _compute_etrts_date(self): self._calculate_etrts_date() @@ -1844,9 +1844,9 @@ class SaleOrder(models.Model): def override_allow_create_invoice(self): if not self.env.user.is_accounting: raise UserError('Hanya Finance Accounting yang dapat klik tombol ini') - for term in self.payment_term_id.line_ids: - if term.days > 0: - raise UserError('Hanya dapat digunakan pada Cash Before Delivery') + # for term in self.payment_term_id.line_ids: + # if term.days > 0: + # raise UserError('Hanya dapat digunakan pada Cash Before Delivery') for line in self.order_line: line.qty_to_invoice = line.product_uom_qty @@ -2049,22 +2049,22 @@ class SaleOrder(models.Model): # return [('id', 'not in', order_ids)] # return ['&', ('order_line.invoice_lines.move_id.move_type', 'in', ('out_invoice', 'out_refund')), ('order_line.invoice_lines.move_id', operator, value)] - @api.depends('partner_id') - def _compute_partner_field(self): - for order in self: - partner = order.partner_id.parent_id or order.partner_id - order.npwp = partner.npwp - order.sppkp = partner.sppkp - order.customer_type = partner.customer_type + # @api.depends('partner_id') + # def _compute_partner_field(self): + # for order in self: + # partner = order.partner_id.parent_id or order.partner_id + # order.npwp = partner.npwp + # order.sppkp = partner.sppkp + # order.customer_type = partner.customer_type @api.onchange('partner_id') def onchange_partner_contact(self): parent_id = self.partner_id.parent_id parent_id = parent_id if parent_id else self.partner_id - self.npwp = parent_id.npwp - self.sppkp = parent_id.sppkp - self.customer_type = parent_id.customer_type + # self.npwp = parent_id.npwp + # self.sppkp = parent_id.sppkp + # self.customer_type = parent_id.customer_type self.email = parent_id.email self.pareto_status = parent_id.pareto_status self.user_id = parent_id.user_id @@ -2141,9 +2141,15 @@ class SaleOrder(models.Model): if self.state not in ['draft', 'sent']: raise UserError("Status harus draft atau sent") - self._validate_npwp() - def _validate_npwp(self): + if not self.npwp: + raise UserError("NPWP partner kosong, silahkan isi terlebih dahulu npwp nya di contact partner") + + if not self.customer_type: + raise UserError("Customer Type partner kosong, silahkan isi terlebih dahulu Customer Type nya di contact partner") + + if not self.sppkp: + raise UserError("SPPKP partner kosong, silahkan isi terlebih dahulu SPPKP nya di contact partner") num_digits = sum(c.isdigit() for c in self.npwp) if num_digits < 10: @@ -2157,6 +2163,7 @@ class SaleOrder(models.Model): self._validate_order() for order in self: + order._validate_npwp() order._validate_uniform_taxes() order.order_line.validate_line() @@ -2211,9 +2218,8 @@ class SaleOrder(models.Model): if self.validate_different_vendor() and not self.vendor_approval: return self._create_notification_action('Notification', 'Terdapat Vendor yang berbeda dengan MD Vendor') self.check_due() - - self._validate_order() for order in self: + order._validate_npwp() order._validate_delivery_amt() order._validate_uniform_taxes() order.order_line.validate_line() @@ -2480,6 +2486,7 @@ class SaleOrder(models.Model): order.check_data_real_delivery_address() order.sale_order_check_approve() order._validate_order() + order._validate_npwp() order.order_line.validate_line() main_parent = order.partner_id.get_main_parent() @@ -2637,7 +2644,7 @@ class SaleOrder(models.Model): if user.is_leader or user.is_sales_manager: return True - if user.id in (3401, 20, 3988): # admin (fida, nabila, ninda) + if user.id in (3401, 20, 3988, 17340): # admin (fida, nabila, ninda) return True if self.env.context.get("ask_approval") and user.id in (3401, 20, 3988): @@ -2665,23 +2672,17 @@ class SaleOrder(models.Model): def _set_sppkp_npwp_contact(self): partner = self.partner_id.parent_id or self.partner_id - if not partner.sppkp: - partner.sppkp = self.sppkp - if not partner.npwp: - partner.npwp = self.npwp + # if not partner.sppkp: + # partner.sppkp = self.sppkp + # if not partner.npwp: + # partner.npwp = self.npwp if not partner.email: partner.email = self.email - if not partner.customer_type: - partner.customer_type = self.customer_type + # if not partner.customer_type: + # partner.customer_type = self.customer_type if not partner.user_id: partner.user_id = self.user_id.id - # if not partner.sppkp or not partner.npwp or not partner.email or partner.customer_type: - # partner.customer_type = self.customer_type - # partner.npwp = self.npwp - # partner.sppkp = self.sppkp - # partner.email = self.email - def _compute_total_margin(self): for order in self: total_margin = sum(line.item_margin for line in order.order_line if line.product_id) @@ -3123,52 +3124,6 @@ class SaleOrder(models.Model): # order._update_partner_details() return order - # def write(self, vals): - # Call the super method to handle the write operation - # res = super(SaleOrder, self).write(vals) - # self._compute_etrts_date() - # Check if the update is coming from a save operation - # if any(field in vals for field in ['sppkp', 'npwp', 'email', 'customer_type']): - # self._update_partner_details() - - # return res - - def _update_partner_details(self): - for order in self: - partner = order.partner_id.parent_id or order.partner_id - if partner: - # Update partner details - partner.sppkp = order.sppkp - partner.npwp = order.npwp - partner.email = order.email - partner.customer_type = order.customer_type - - # Save changes to the partner record - partner.write({ - 'sppkp': partner.sppkp, - 'npwp': partner.npwp, - 'email': partner.email, - '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 - # @api.depends('commitment_date') def _compute_ready_to_ship_status_detail(self): def is_empty(val): diff --git a/indoteknik_custom/models/sale_order_line.py b/indoteknik_custom/models/sale_order_line.py index 47a24264..1f2ea1fb 100644 --- a/indoteknik_custom/models/sale_order_line.py +++ b/indoteknik_custom/models/sale_order_line.py @@ -71,23 +71,17 @@ class SaleOrderLine(models.Model): if order_qty > 0: for move in line.move_ids: - # --- CASE 1: Move belum selesai --- if move.state not in ('done', 'cancel'): reserved_qty += move.reserved_availability or 0.0 continue - # --- CASE 2: Move sudah done --- if move.location_dest_id.usage == 'customer': - # Barang dikirim ke customer delivered_qty += move.quantity_done or 0.0 elif move.location_id.usage == 'customer': - # Barang balik dari customer (retur) delivered_qty -= move.quantity_done or 0.0 - # Clamp supaya delivered gak minus delivered_qty = max(delivered_qty, 0) - # Hitung persen line.reserved_percent = min((reserved_qty / order_qty) * 100, 100) if order_qty else 0 line.delivered_percent = min((delivered_qty / order_qty) * 100, 100) if order_qty else 0 line.unreserved_percent = max(100 - line.reserved_percent - line.delivered_percent, 0) diff --git a/indoteknik_custom/models/tukar_guling.py b/indoteknik_custom/models/tukar_guling.py index 6e839bf0..c683f75a 100644 --- a/indoteknik_custom/models/tukar_guling.py +++ b/indoteknik_custom/models/tukar_guling.py @@ -61,7 +61,7 @@ class TukarGuling(models.Model): notes = fields.Text('Notes') return_type = fields.Selection(String='Return Type', selection=[ ('tukar_guling', 'Tukar Guling'), # -> barang yang sama - ('revisi_so', 'Revisi SO')], required=True, tracking=3) + ('retur_so', 'Retur SO')], required=True, tracking=3, help='Retur SO (ORT-SRT),\n Tukar Guling (ORT-SRT-PICK-OUT)') state = fields.Selection(string='Status', selection=[ ('draft', 'Draft'), ('approval_sales', ' Approval Sales'), @@ -169,7 +169,7 @@ class TukarGuling(models.Model): raise UserError("❌ Picking type harus BU/OUT atau BU/PICK") for rec in self: if rec.operations and rec.operations.picking_type_id.id == 30: - rec.return_type = 'revisi_so' + rec.return_type = 'retur_so' if self.operations: from_return_picking = self.env.context.get('from_return_picking', False) or \ @@ -315,7 +315,7 @@ class TukarGuling(models.Model): @api.constrains('return_type', 'operations') def _check_required_bu_fields(self): for record in self: - if record.return_type in ['revisi_so', 'tukar_guling'] and not record.operations: + if record.return_type in ['retur_so', 'tukar_guling'] and not record.operations: raise ValidationError("Operations harus diisi") @api.constrains('line_ids', 'state') @@ -352,16 +352,16 @@ class TukarGuling(models.Model): # ('state', '!=', 'cancel') # ]) > 0 - # def _check_invoice_on_revisi_so(self): + # def _check_invoice_on_retur_so(self): # for record in self: - # if record.return_type == 'revisi_so' and record.origin: + # if record.return_type == 'retur_so' and record.origin: # invoices = self.env['account.move'].search([ # ('invoice_origin', 'ilike', record.origin), # ('state', 'not in', ['draft', 'cancel']) # ]) # if invoices: # raise ValidationError( - # _("Tidak bisa memilih Return Type 'Revisi SO' karena dokumen %s sudah dibuat invoice.") % record.origin + # _("Tidak bisa memilih Return Type 'Retur SO' karena dokumen %s sudah dibuat invoice.") % record.origin # ) @@ -414,7 +414,7 @@ class TukarGuling(models.Model): self.ensure_one() if self.operations.picking_type_id.id not in [29, 30]: raise UserError("❌ Picking type harus BU/OUT atau BU/PICK") - # self._check_invoice_on_revisi_so() + # self._check_invoice_on_retur_so() operasi = self.operations.picking_type_id.id tipe = self.return_type pp = vals.get('return_type', tipe) @@ -530,7 +530,7 @@ class TukarGuling(models.Model): raise UserError( _("Qty di Koli tidak sesuai dengan qty retur untuk produk %s") % line.product_id.display_name ) - # self._check_invoice_on_revisi_so() + # self._check_invoice_on_retur_so() self._validate_product_lines() if self.state != 'draft': @@ -553,7 +553,7 @@ class TukarGuling(models.Model): self.state = 'done' # OUT revisi SO - elif self.operations.picking_type_id.id == 29 and self.return_type == 'revisi_so': + elif self.operations.picking_type_id.id == 29 and self.return_type == 'retur_so': total_ort = self.env['stock.picking'].search_count([ ('tukar_guling_id', '=', self.id), ('picking_type_id', '=', 74), @@ -567,7 +567,7 @@ class TukarGuling(models.Model): self.state = 'done' # PICK revisi SO - elif self.operations.picking_type_id.id == 30 and self.return_type == 'revisi_so': + elif self.operations.picking_type_id.id == 30 and self.return_type == 'retur_so': done_ort = self.env['stock.picking'].search([ ('tukar_guling_id', '=', self.id), ('picking_type_id', '=', 74), @@ -581,7 +581,7 @@ class TukarGuling(models.Model): def action_approve(self): self.ensure_one() self._validate_product_lines() - # self._check_invoice_on_revisi_so() + # self._check_invoice_on_retur_so() self._check_not_allow_tukar_guling_on_bu_pick() operasi = self.operations.picking_type_id.id @@ -631,7 +631,7 @@ class TukarGuling(models.Model): elif rec.state == 'approval_finance': if not rec.env.user.has_group('indoteknik_custom.group_role_fat'): raise UserError("Hanya Finance Manager yang boleh approve tahap ini.") - # rec._check_invoice_on_revisi_so() + # rec._check_invoice_on_retur_so() rec.set_opt() rec.state = 'approval_logistic' rec.date_finance = now @@ -710,7 +710,7 @@ class TukarGuling(models.Model): ### ======== SRT dari BU/OUT ========= srt_return_lines = [] - if mapping_koli: + if mapping_koli and record.operations.picking_type_id.id == 29: for prod in mapping_koli.mapped('product_id'): qty_total = sum(mk.qty_return for mk in mapping_koli.filtered(lambda m: m.product_id == prod)) move = bu_out.move_lines.filtered(lambda m: m.product_id == prod) @@ -723,7 +723,7 @@ class TukarGuling(models.Model): })) _logger.info(f"📟 SRT line: {prod.display_name} | qty={qty_total}") - elif not mapping_koli: + elif not mapping_koli and record.operations.picking_type_id.id == 29: for line in record.line_ids: move = bu_out.move_lines.filtered(lambda m: m.product_id == line.product_id) if not move: diff --git a/indoteknik_custom/models/tukar_guling_po.py b/indoteknik_custom/models/tukar_guling_po.py index f2f37606..f61b3828 100644 --- a/indoteknik_custom/models/tukar_guling_po.py +++ b/indoteknik_custom/models/tukar_guling_po.py @@ -38,9 +38,9 @@ class TukarGulingPO(models.Model): ) ba_num = fields.Char('Nomor BA', tracking=3) return_type = fields.Selection([ - ('revisi_po', 'Revisi PO'), + ('retur_po', 'Retur PO'), ('tukar_guling', 'Tukar Guling'), - ], string='Return Type', required=True, tracking=3) + ], string='Return Type', required=True, tracking=3, help='Retur PO (VRT-PRT),\n Tukar Guling (VRT-PRT-INPUT-PUT') notes = fields.Text('Notes', tracking=3) tukar_guling_po_id = fields.Many2one('tukar.guling.po', string='Tukar Guling PO', ondelete='cascade') line_ids = fields.One2many('tukar.guling.line.po', 'tukar_guling_po_id', string='Product Lines', tracking=3) @@ -143,9 +143,9 @@ class TukarGulingPO(models.Model): return res - # def _check_bill_on_revisi_po(self): + # def _check_bill_on_retur_po(self): # for record in self: - # if record.return_type == 'revisi_po' and record.origin: + # if record.return_type == 'retur_po' and record.origin: # bills = self.env['account.move'].search([ # ('invoice_origin', 'ilike', record.origin), # ('move_type', '=', 'in_invoice'), # hanya vendor bill @@ -153,7 +153,7 @@ class TukarGulingPO(models.Model): # ]) # if bills: # raise ValidationError( - # _("Tidak bisa memilih Return Type 'Revisi PO' karena PO %s sudah dibuat vendor bill. Harus Cancel Jika ingin melanjutkan") % record.origin + # _("Tidak bisa memilih Return Type 'Retur PO' karena PO %s sudah dibuat vendor bill. Harus Cancel Jika ingin melanjutkan") % record.origin # ) @api.onchange('operations') @@ -284,7 +284,7 @@ class TukarGulingPO(models.Model): @api.constrains('return_type', 'operations') def _check_required_bu_fields(self): for record in self: - if record.return_type in ['revisi_po', 'tukar_guling'] and not record.operations: + if record.return_type in ['retur_po', 'tukar_guling'] and not record.operations: raise ValidationError("Operations harus diisi") @api.constrains('line_ids', 'state') @@ -350,7 +350,7 @@ class TukarGulingPO(models.Model): def write(self, vals): if self.operations.picking_type_id.id not in [75, 28]: raise UserError("❌ Tidak bisa retur bukan BU/INPUT atau BU/PUT!") - # self._check_bill_on_revisi_po() + # self._check_bill_on_retur_po() tipe = vals.get('return_type', self.return_type) if self.operations and self.operations.picking_type_id.id == 28 and tipe == 'tukar_guling': @@ -418,7 +418,7 @@ class TukarGulingPO(models.Model): def action_submit(self): self.ensure_one() - # self._check_bill_on_revisi_po() + # self._check_bill_on_retur_po() self._validate_product_lines() self._check_not_allow_tukar_guling_on_bu_input() @@ -463,7 +463,7 @@ class TukarGulingPO(models.Model): def action_approve(self): self.ensure_one() self._validate_product_lines() - # self._check_bill_on_revisi_po() + # self._check_bill_on_retur_po() self._check_not_allow_tukar_guling_on_bu_input() if not self.operations: @@ -485,7 +485,7 @@ class TukarGulingPO(models.Model): elif rec.state == 'approval_finance': if not rec.env.user.has_group('indoteknik_custom.group_role_fat'): raise UserError("Hanya Finance yang boleh approve tahap ini.") - # rec._check_bill_on_revisi_po() + # rec._check_bill_on_retur_po() rec.set_opt() rec.state = 'approval_logistic' rec.date_finance = now @@ -501,7 +501,7 @@ class TukarGulingPO(models.Model): def update_doc_state(self): # bu input rev po - if self.operations.picking_type_id.id == 28 and self.return_type == 'revisi_po': + if self.operations.picking_type_id.id == 28 and self.return_type == 'retur_po': prt = self.env['stock.picking'].search([ ('tukar_guling_po_id', '=', self.id), ('state', '=', 'done'), @@ -510,7 +510,7 @@ class TukarGulingPO(models.Model): if self.state == 'approved' and prt: self.state = 'done' # bu put rev po - elif self.operations.picking_type_id.id == 75 and self.return_type == 'revisi_po': + elif self.operations.picking_type_id.id == 75 and self.return_type == 'retur_po': total_prt = self.env['stock.picking'].search_count([ ('tukar_guling_po_id', '=', self.id), ('picking_type_id.id', '=', 76) diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml index 9d7f4028..d0b73118 100644 --- a/indoteknik_custom/report/purchase_report.xml +++ b/indoteknik_custom/report/purchase_report.xml @@ -25,96 +25,113 @@ </t> </template> - <!-- Document Template --> -<template id="report_purchaseorder_website_document"> - <t t-call="web.external_layout"> + <template id="report_purchaseorder_website_document"> + <t t-call="web.html_container"> <t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)" /> - <div class="page"> - <!-- Header Image --> - <div class="mb16"> - <img src="https://erp.indoteknik.com/api/image/ir.attachment/datas/2498521" - style="width:100%; max-height:100px; object-fit:contain;"/> - </div> + <!-- HEADER --> + <div class="header"> + <img src="https://erp.indoteknik.com/api/image/ir.attachment/datas/2498521" + style="width:100%; display:block;"/> + </div> + + <!-- PAGE CONTENT --> + <div class="article" style="margin: 0 1.5cm 0 1.5cm; font-family:Arial, sans-serif; font-size:14px; color:#333;"> - <!-- Title --> - <h2 class="text-center mb4" style="color:#d32f2f; font-weight:bold;"> + <!-- TITLE --> + <h2 style="text-align:center; margin:8px 0 0 0; color:#d32f2f; font-weight:800; letter-spacing:1px;"> PURCHASE ORDER </h2> - <h4 class="text-center mb32"> + <h4 style="text-align:center; margin:4px 0 20px 0; font-weight:normal; color:#555;"> No. <span t-field="doc.name"/> </h4> - <!-- Top Info sejajar --> - <div class="row mb16" style="font-size:12px;"> - <div class="col-4"> - <strong>Term Of Payment:</strong> - <span t-field="doc.payment_term_id.name"/> - </div> - <div class="col-4"> - <strong>Order Date:</strong> - <span t-field="doc.date_order" t-options='{"widget": "date"}'/> - </div> - <div class="col-4"> - <strong>Responsible:</strong> - <span t-field="doc.user_id"/> - </div> - </div> + <!-- TOP INFO --> + <table style="width:100%; margin-bottom:20px; border-radius:8px; box-shadow:0 1px 4px rgba(0,0,0,0.1); overflow:hidden; border:1px solid #ddd;"> + <tr style="background:#fafafa;"> + <td style="padding:10px 12px;"><strong>Term Of Payment:</strong> <span t-field="doc.payment_term_id.name"/></td> + <td style="padding:10px 12px;"><strong>Order Date:</strong> <span t-field="doc.date_order" t-options='{"widget": "date"}'/></td> + <td style="padding:10px 12px;"><strong>Responsible:</strong> <span t-field="doc.user_id"/></td> + </tr> + </table> - <!-- Vendor & Shipping Info sejajar --> - <div class="row mb32" style="font-size:12px;"> - <div class="col-6" style="border:1px solid #ccc; padding:8px;"> - <strong>Alamat Pengiriman:</strong><br/> - PT Indoteknik (Bandengan 1 Depan)<br/> - Jl. Bandengan Utara Komp A 8 B<br/> - RT. Penjaringan, Kec. Penjaringan, Jakarta (BELAKANG INDOMARET)<br/> - JK 14440<br/> - Indonesia - </div> - <div class="col-6" style="border:1px solid #ccc; padding:8px;"> - <strong>Nama Vendor:</strong><br/> - <div t-field="doc.partner_id" - t-options='{"widget": "contact", "fields": ["address", "name", "phone"], - "no_marker": True, "phone_icons": True}'/> - </div> - </div> + <!-- VENDOR & DELIVERY --> + <table style="width:100%; margin-bottom:24px; border-spacing:16px 0;"> + <tr> + <td style="width:50%; border:1px solid #ccc; border-radius:8px; padding:10px; background:#fcfcfc; vertical-align:top;"> + <strong style="color:#d32f2f;">Alamat Pengiriman</strong><br/> + PT Indoteknik (Bandengan 1 Depan)<br/> + Jl. Bandengan Utara No. 89, RT 003<br/> + RT. Penjaringan, Kec. Penjaringan, Jakarta (BELAKANG INDOMARET)<br/> + JK 14440 - Indonesia + </td> + <td style="width:50%; border:1px solid #ccc; border-radius:8px; padding:10px; background:#fcfcfc; vertical-align:top;"> + <strong style="color:#d32f2f;">Nama Vendor</strong><br/> + <span t-field="doc.partner_id.name"/><br/> + <span t-field="doc.partner_id.street"/><br/> + <span t-field="doc.partner_id.city"/> - <span t-field="doc.partner_id.zip"/> + </td> + </tr> + </table> - <!-- Order Lines --> - <table class="table table-sm o_main_table" style="font-size:11px; border:1px solid #000; border-collapse: collapse; width:100%;"> - <thead style="display: table-row-group; background:#f5f5f5;"> - <tr> - <th style="border:1px solid #000; padding:4px;">Description</th> - <th class="text-right" style="border:1px solid #000; padding:4px;">Quantity</th> - <th class="text-right" style="border:1px solid #000; padding:4px;">Unit Price</th> - <th class="text-right" style="border:1px solid #000; padding:4px;">Taxes</th> - <th class="text-right" style="border:1px solid #000; padding:4px;">Subtotal</th> - </tr> - </thead> + <!-- ORDER LINES --> + <table style="border-collapse:collapse; width:100%; margin-top:16px; font-size:14px;"> <tbody> - <t t-foreach="doc.order_line" t-as="line"> - <!-- Main row --> - <tr> - <td style="border:1px solid #000; padding:4px;"> - <span t-field="line.name"/> + <!-- HEADER --> + <tr style="background:#e53935; color:white;"> + <th style="border:1px solid #ccc; padding:8px; text-align:left;">No. & Description</th> + <th style="border:1px solid #ccc; padding:8px; text-align:left;">Image</th> + <th style="border:1px solid #ccc; padding:8px; text-align:center;">Quantity</th> + <th style="border:1px solid #ccc; padding:8px; text-align:center;">Unit Price</th> + <th style="border:1px solid #ccc; padding:8px; text-align:center;">Taxes</th> + <th style="border:1px solid #ccc; padding:8px; text-align:center;">Subtotal</th> + </tr> + + <!-- ISI ORDER LINE --> + <t t-foreach="doc.order_line" t-as="line" t-index="line_index"> + <tr t-attf-style="background-color: #{ '#fafafa' if line_index % 2 == 0 else 'white' };"> + + <!-- NO & DESCRIPTION + IMAGE --> + <td style="border:1px solid #ccc; padding: 6px; display:flex; align-items:center; gap:10px;"> + <!-- TEKS --> + <div style="display:flex; flex-direction:column; flex:1;"> + <span style="font-weight:bold; margin-bottom:2px;"> + <t t-esc="line_index + 1"/>. <t t-esc="line.name"/> + </span> + </div> </td> - <td class="text-right" style="border:1px solid #000; padding:4px;"> - <span t-field="line.product_qty"/> - <span t-field="line.product_uom"/> + + <td style="border:1px solid #ccc; padding:6px; text-align:center;"> + <t t-if="line.image_small"> + <img t-att-src="image_data_uri(line.image_small)" + style="width:100px; height:100px; object-fit:contain; border:1px solid #ddd; border-radius:6px; background:#fff;"/> + </t> + </td> + <!-- QTY --> + <td style="border:1px solid #ccc; padding:6px; text-align:center;"> + <span t-field="line.product_qty"/> <span t-field="line.product_uom"/> </td> - <td class="text-right" style="border:1px solid #000; padding:4px;"> + + <!-- UNIT PRICE --> + <td style="border:1px solid #ccc; padding:6px; text-align:center;"> <span t-field="line.price_unit"/> </td> - <td class="text-right" style="border:1px solid #000; padding:4px;"> + + <!-- TAXES --> + <td style="border:1px solid #ccc; padding:6px; text-align:center;"> <span t-esc="', '.join(map(lambda x: (x.description or x.name), line.taxes_id))"/> </td> - <td class="text-right" style="border:1px solid #000; padding:4px;"> + + <!-- SUBTOTAL --> + <td style="border:1px solid #ccc; padding:6px; text-align:right; font-weight:bold;"> <span t-field="line.price_subtotal"/> </td> </tr> - <!-- Website Description row --> - <t t-if="line.product_id.website_description"> - <tr> - <td colspan="5" style="border:1px solid #000; padding:6px; font-size:10px; color:#555;"> + + <!-- WEBSITE DESCRIPTION --> + <t t-if="line.show_description"> + <tr t-attf-style="background-color: #{ '#fef5f5' if line_index % 2 == 0 else '#fffafa' }; "> + <td colspan="6" style="padding: 10px 14px; font-size:10px; line-height:1.3; font-style:italic; color:#555; border-left:1px solid #ccc; border-right:1px solid #ccc; border-bottom:1px solid #ccc;"> <div t-raw="line.product_id.website_description"/> </td> </tr> @@ -123,40 +140,38 @@ </tbody> </table> - <!-- Totals --> - <div class="clearfix"> - <div class="row"> - <div class="col-4 ml-auto"> - <table class="table table-sm" style="border:1px solid #000; border-collapse: collapse; width:100%;"> - <tr> - <td style="border:1px solid #000; padding:4px;"><strong>Subtotal</strong></td> - <td class="text-right" style="border:1px solid #000; padding:4px;"> - <span t-field="doc.amount_untaxed"/> - </td> - </tr> - <tr> - <td style="border:1px solid #000; padding:4px;">Taxes</td> - <td class="text-right" style="border:1px solid #000; padding:4px;"> - <span t-field="doc.amount_tax"/> - </td> - </tr> - <tr class="o_total"> - <td style="border:1px solid #000; padding:4px;"><strong>Total</strong></td> - <td class="text-right" style="border:1px solid #000; padding:4px;"> - <span t-field="doc.amount_total"/> - </td> - </tr> - </table> - </div> - </div> - </div> - <!-- Notes --> - <div class="mt32" style="font-size:11px;"> + <!-- TOTALS --> + <table style="margin-top:24px; margin-left:auto; width:40%; font-size:14px; border:1px solid #ddd; border-radius:6px; box-shadow:0 1px 3px rgba(0,0,0,0.08);"> + <tr style="background:#fafafa;"> + <td style="padding:8px;"><strong>Subtotal</strong></td> + <td style="text-align:right; padding:8px;"><span t-field="doc.amount_untaxed"/></td> + </tr> + <tr> + <td style="padding:8px;">Taxes</td> + <td style="text-align:right; padding:8px;"><span t-field="doc.amount_tax"/></td> + </tr> + <tr style="background:#fbe9e7; font-weight:bold; color:#d32f2f;"> + <td style="padding:8px;">Total</td> + <td style="text-align:right; padding:8px;"><span t-field="doc.amount_total"/></td> + </tr> + </table> + + <!-- NOTES --> + <div style="margin-top:24px; padding:12px; border-top:1px solid #ddd; font-style:italic; color:#555;"> <p t-field="doc.notes"/> </div> </div> + + <!-- STATIC FOOTER --> + <div class="footer"> + <img src="https://erp.indoteknik.com/api/image/ir.attachment/datas/2859765" + style="width:100%; display:block;"/> + </div> + </t> </template> + + </odoo> diff --git a/indoteknik_custom/views/approval_payment_term.xml b/indoteknik_custom/views/approval_payment_term.xml index 5c130f3f..b0b99689 100644 --- a/indoteknik_custom/views/approval_payment_term.xml +++ b/indoteknik_custom/views/approval_payment_term.xml @@ -7,7 +7,7 @@ <tree default_order="create_date desc"> <field name="number"/> <field name="partner_id"/> - <field name="parent_id"/> + <field name="parent_id" optional="hide"/> <field name="property_payment_term_id"/> <field name="create_date" optional="hide"/> <field name="approve_date" optional="hide"/> diff --git a/indoteknik_custom/views/dunning_run.xml b/indoteknik_custom/views/dunning_run.xml index f624c42e..51377f78 100644 --- a/indoteknik_custom/views/dunning_run.xml +++ b/indoteknik_custom/views/dunning_run.xml @@ -25,13 +25,14 @@ <field name="arch" type="xml"> <tree> <field name="partner_id"/> + <field name="reference"/> <field name="invoice_id"/> <field name="date_invoice"/> - <field name="efaktur_id"/> - <field name="reference"/> + <field name="efaktur_id" optional="hide"/> <field name="total_amt" sum="Grand Total Amount"/> <field name="open_amt"/> <field name="due_date"/> + <field name="payment_term"/> </tree> </field> </record> diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml index 821f3295..a0ac9824 100755 --- a/indoteknik_custom/views/purchase_order.xml +++ b/indoteknik_custom/views/purchase_order.xml @@ -99,6 +99,7 @@ <field name="total_delivery_amt" attrs="{'required': [('partner_id', 'in', [9688, 29712])]}"/> <field name="product_bom_id" attrs="{'invisible': [('product_bom_id', '=', None)]}"/> <field name="manufacturing_id" attrs="{'invisible': [('product_bom_id', '=', None)]}"/> + <field name="show_description" attrs="{'invisible': [('partner_id', '!=', 5571)]}" widget="boolean_toggle"/> <!-- <field name="move_id" domain="[('move_type','=','entry')]" context="{'form_view_ref': 'account.view_move_form'}" options="{'no_create': True}"/> --> </field> <field name="amount_total" position="after"> @@ -112,6 +113,7 @@ </field> <field name="product_id" position="before"> <field name="line_no" attrs="{'readonly': 1}" optional="hide"/> + <field name="show_description" optional="hide" widget="boolean_toggle"/> </field> <field name="product_id" position="attributes"> <attribute name="options">{'no_create': True}</attribute> @@ -181,19 +183,20 @@ </field> <field name="order_line" position="attributes"> - <attribute name="attrs">{'readonly': ['|', ('state', 'in', ['purchase', 'done', 'cancel']), ('has_active_invoice', '=', True)]}</attribute> + <!-- <attribute name="attrs">{'readonly': ['|', ('state', 'in', ['purchase', 'done', 'cancel']), ('has_active_invoice', '=', True)]}</attribute> --> + <attribute name="attrs">{'readonly': [('has_active_invoice', '=', True)]}</attribute> </field> <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='price_unit']" position="attributes"> - <attribute name="attrs">{'readonly': [], 'required': True}</attribute> + <attribute name="attrs">{'readonly': [('state', 'in', ['purchase', 'done', 'cancel'])], 'required': True}</attribute> </xpath> <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='taxes_id']" position="attributes"> - <attribute name="attrs">{'readonly': []}</attribute> + <attribute name="attrs">{'readonly': [('state', 'in', ['purchase', 'done', 'cancel'])]}</attribute> </xpath> <xpath expr="//form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='product_qty']" position="attributes"> - <attribute name="attrs">{'required': True}</attribute> + <attribute name="attrs">{'readonly': [('state', 'in', ['purchase', 'done', 'cancel'])], 'required': True}</attribute> </xpath> <xpath expr="//form/sheet/notebook/page[@name='purchase_delivery_invoice']" position="before"> diff --git a/indoteknik_custom/views/report_logbook_sj.xml b/indoteknik_custom/views/report_logbook_sj.xml index 94f6c2ab..2b7cfa22 100644 --- a/indoteknik_custom/views/report_logbook_sj.xml +++ b/indoteknik_custom/views/report_logbook_sj.xml @@ -21,6 +21,8 @@ <field name="model">report.logbook.sj.line</field> <field name="arch" type="xml"> <tree editable="bottom"> +<!-- <field name="sequence" widget="handle"/>--> + <field name="line_num" string="No" readonly="1"/> <field name="name"/> <field name="driver_id"/> <field name="departure_date"/> diff --git a/indoteknik_custom/views/res_partner.xml b/indoteknik_custom/views/res_partner.xml index 7d5be3b7..c32151d8 100644 --- a/indoteknik_custom/views/res_partner.xml +++ b/indoteknik_custom/views/res_partner.xml @@ -36,9 +36,9 @@ <field name="pareto_status"/> <field name="digital_invoice_tax"/> </field> - <field name="nama_wajib_pajak" position="attributes"> + <!-- <field name="nama_wajib_pajak" position="attributes"> <attribute name="required">1</attribute> - </field> + </field> --> <field name="kota_id" position="attributes"> <attribute name="required">0</attribute> </field> @@ -48,14 +48,14 @@ <field name="kelurahan_id" position="attributes"> <attribute name="required">0</attribute> </field> - <field name="npwp" position="attributes"> + <!-- <field name="npwp" position="attributes"> <attribute name="required">1</attribute> </field> <field name="alamat_lengkap_text" position="attributes"> <attribute name="required">1</attribute> - </field> + </field> --> <field name="npwp" position="before"> - <field name="customer_type" required="1"/> + <field name="customer_type"/> </field> <field name="alamat_lengkap_text" position="after"> <field name="nitku" /> diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index 326fd560..8d56bbbd 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -148,9 +148,9 @@ <field name="pareto_status"/> </field> <field name="analytic_account_id" position="after"> - <field name="customer_type" readonly="1"/> - <field name="npwp" placeholder='99.999.999.9-999.999' readonly="1"/> - <field name="sppkp" attrs="{'required': [('customer_type', '=', 'pkp')]}" readonly="1"/> + <field name="customer_type"/> + <field name="npwp" placeholder='99.999.999.9-999.999'/> + <field name="sppkp" attrs="{'required': [('customer_type', '=', 'pkp')]}"/> <field name="email" required="1"/> <field name="unreserve_id"/> <field name="due_id" readonly="1"/> @@ -297,9 +297,9 @@ <field name="note" optional="hide"/> <field name="note_procurement" optional="hide"/> <field name="vendor_subtotal" optional="hide"/> - <field name="unreserved_percent" widget="percentpie" string="Unreserved"/> - <field name="reserved_percent" widget="percentpie" string="Reserved"/> - <field name="delivered_percent" widget="percentpie" string="Delivered"/> + <field name="unreserved_percent" widget="percentpie" string="Unreserved" optional="hide"/> + <field name="reserved_percent" widget="percentpie" string="Reserved" optional="hide"/> + <field name="delivered_percent" widget="percentpie" string="Delivered" optional="hide"/> <field name="weight" optional="hide"/> <field name="is_has_disc" string="Flash Sale Item?" readonly="1" optional="hide"/> <field name="amount_voucher_disc" string="Voucher" readonly="1" optional="hide"/> diff --git a/indoteknik_custom/views/tukar_guling_po.xml b/indoteknik_custom/views/tukar_guling_po.xml index 548a209f..4a9ab25d 100644 --- a/indoteknik_custom/views/tukar_guling_po.xml +++ b/indoteknik_custom/views/tukar_guling_po.xml @@ -87,7 +87,7 @@ <!-- <field name="srt_num" readonly="1"/>--> <field name="operations" string="Operations" attrs="{ - 'required': [('return_type', 'in', ['revisi_po', 'tukar_guling'])] + 'required': [('return_type', 'in', ['retur_po', 'tukar_guling'])] }"/> <!-- <field name="origin" readonly="1"/>--> <field name="origin_po" readonly="1"/> |
