diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2025-07-31 08:35:01 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2025-07-31 08:35:01 +0700 |
| commit | aeb4fc3b4b8a4c38d6628946232c236a4d2fe2a9 (patch) | |
| tree | 28db4b1dc10a10bc65f5b57a4470d39e78629ef7 /indoteknik_custom | |
| parent | 8d1af98bb7dab812f91d7d275b4004c4e5b0ff75 (diff) | |
| parent | d6bdde8fe63ff15ce8f3fee6bc5e8ae903fc78ce (diff) | |
<hapit>merge
Diffstat (limited to 'indoteknik_custom')
| -rw-r--r-- | indoteknik_custom/models/commision.py | 5 | ||||
| -rw-r--r-- | indoteknik_custom/models/mrp_production.py | 8 | ||||
| -rwxr-xr-x | indoteknik_custom/models/purchase_order.py | 146 | ||||
| -rwxr-xr-x | indoteknik_custom/models/sale_order.py | 7 | ||||
| -rw-r--r-- | indoteknik_custom/models/sale_order_line.py | 7 | ||||
| -rw-r--r-- | indoteknik_custom/models/shipment_group.py | 2 | ||||
| -rw-r--r-- | indoteknik_custom/models/stock_picking.py | 10 | ||||
| -rw-r--r-- | indoteknik_custom/models/tukar_guling.py | 128 | ||||
| -rw-r--r-- | indoteknik_custom/models/tukar_guling_po.py | 88 | ||||
| -rwxr-xr-x | indoteknik_custom/security/ir.model.access.csv | 4 | ||||
| -rwxr-xr-x | indoteknik_custom/views/purchase_order.xml | 43 | ||||
| -rw-r--r-- | indoteknik_custom/views/refund_sale_order.xml | 199 | ||||
| -rwxr-xr-x | indoteknik_custom/views/sale_order.xml | 2 | ||||
| -rw-r--r-- | indoteknik_custom/views/stock_picking.xml | 4 | ||||
| -rw-r--r-- | indoteknik_custom/views/tukar_guling.xml | 8 | ||||
| -rw-r--r-- | indoteknik_custom/views/tukar_guling_po.xml | 13 |
16 files changed, 374 insertions, 300 deletions
diff --git a/indoteknik_custom/models/commision.py b/indoteknik_custom/models/commision.py index 26b5df37..9f7df464 100644 --- a/indoteknik_custom/models/commision.py +++ b/indoteknik_custom/models/commision.py @@ -215,9 +215,8 @@ class CustomerCommision(models.Model): grouped_so_number = fields.Char(string='Group SO Number', compute='_compute_grouped_numbers') grouped_invoice_number = fields.Char(string='Group Invoice Number', compute='_compute_grouped_numbers') - sales_id = fields.Many2one('res.users', string="Sales", tracking=True, default=lambda self: self.env.user, - domain=lambda self: [ - ('groups_id', 'in', self.env.ref('sales_team.group_sale_salesman').id)]) + sales_id = fields.Many2one('res.users', string="Sales", tracking=True, required=True, + domain=[('groups_id', 'in', [94]),('id', '!=', 15710)]) date_approved_sales = fields.Datetime(string="Date Approved Sales", tracking=True) date_approved_marketing = fields.Datetime(string="Date Approved Marketing", tracking=True) diff --git a/indoteknik_custom/models/mrp_production.py b/indoteknik_custom/models/mrp_production.py index 7977bdf7..91da0597 100644 --- a/indoteknik_custom/models/mrp_production.py +++ b/indoteknik_custom/models/mrp_production.py @@ -156,7 +156,7 @@ class MrpProduction(models.Model): 'order_id': new_po.id }]) - new_po.button_confirm() + # new_po.button_confirm() self.is_po = True @@ -247,7 +247,7 @@ class CheckBomProduct(models.Model): @api.constrains('production_id', 'product_id') def _check_product_bom_validation(self): for record in self: - if record.production_id.sale_order.state not in ['sale', 'done']: + if record.production_id.sale_order and record.production_id.sale_order.state not in ['sale', 'done']: raise UserError(( "SO harus diconfirm terlebih dahulu." )) @@ -273,13 +273,13 @@ class CheckBomProduct(models.Model): if existing_lines: total_quantity = sum(existing_lines.mapped('quantity')) - if total_quantity < total_qty_in_moves: + if total_quantity > total_qty_in_moves: raise UserError(( "Quantity Product '%s' kurang dari quantity demand." ) % (record.product_id.display_name)) else: # Check if the quantity exceeds the allowed total - if record.quantity < total_qty_in_moves: + if record.quantity > total_qty_in_moves: raise UserError(( "Quantity Product '%s' kurang dari quantity demand." ) % (record.product_id.display_name)) diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py index 45134939..27aca0d1 100755 --- a/indoteknik_custom/models/purchase_order.py +++ b/indoteknik_custom/models/purchase_order.py @@ -92,6 +92,11 @@ class PurchaseOrder(models.Model): is_cab_visible = fields.Boolean(string='Tampilkan Tombol CAB', compute='_compute_is_cab_visible') + reason_change_date_planned = fields.Selection([ + ('delay', 'Delay By Vendor'), + ('urgent', 'Urgent Delivery'), + ], string='Reason Change Date Planned', tracking=True) + # picking_ids = fields.One2many('stock.picking', 'purchase_id', string='Pickings') bu_related_count = fields.Integer( @@ -100,9 +105,68 @@ class PurchaseOrder(models.Model): ) manufacturing_id = fields.Many2one('mrp.production', string='Manufacturing Orders') + complete_bu_in_count = fields.Integer( + string="Complete BU In Count", + compute='_compute_complete_bu_in_count' + ) + + def _compute_complete_bu_in_count(self): + for order in self: + if order.state not in ['done', 'cancel']: + order.complete_bu_in_count = 1 + else: + relevant_pickings = order.picking_ids.filtered( + lambda p: p.state != 'done' + and p.state != 'cancel' + and p.picking_type_code == 'incoming' + and p.origin == order.name + and p.name.startswith('BU/IN') + ) + order.complete_bu_in_count = len(relevant_pickings) + def _has_vcm(self): if self.id: self.vcm_id = self.env['tukar.guling.po'].search([('origin', '=', self.name)], limit=1) + + @api.depends('order_line.date_planned') + def _compute_date_planned(self): + """ date_planned = the earliest date_planned across all order lines. """ + for order in self: + order.date_planned = False + + @api.constrains('date_planned') + def constrains_date_planned(self): + for rec in self: + if not self.env.user.has_group('indoteknik_custom.group_role_purchasing'): + raise ValidationError("Hanya dapat diisi oleh Purchasing") + + base_bu = self.env['stock.picking'].search([ + ('name', 'ilike', 'BU/'), + ('origin', 'ilike', rec.name), + ('group_id', '=', rec.group_id.id), + ('state', 'not in', ['cancel','done']) + ]) + + for bu in base_bu: + bu.write({ + 'scheduled_date': rec.date_planned, + 'reason_change_date_planned': rec.reason_change_date_planned + }) + + rec.sync_date_planned_to_so() + + def sync_date_planned_to_so(self): + for line in self.order_sales_match_line: + other_sales_match = self.env['purchase.order.sales.match'].search([ + # ('product_id', '=', line.product_id.id), + ('sale_id', '=', line.sale_id.id), + # ('sale_line_id', '=', line.sale_line_id.id) + ]) + + dates = [d for d in other_sales_match.mapped('purchase_order_id.date_planned') if d] + if dates: + date_planned = max(dates) + line.sale_id.write({'et_products': date_planned, 'reason_change_date_planned': line.purchase_order_id.reason_change_date_planned}) @api.depends('name') def _compute_bu_related_count(self): @@ -677,13 +741,6 @@ class PurchaseOrder(models.Model): for order in self: order.has_active_invoice = any(invoice.state != 'cancel' for invoice in order.invoice_ids) - # def _compute_has_active_invoice(self): - # for order in self: - # related_invoices = order.invoice_ids.filtered( - # lambda inv: inv.purchase_order_id.id == order.id and inv.move_type == 'in_invoice' and inv.state != 'cancel' - # ) - # order.has_active_invoice = bool(related_invoices) - def add_product_to_pricelist(self): i = 0 for line in self.order_line: @@ -766,16 +823,16 @@ class PurchaseOrder(models.Model): """ purchase_pricelist.message_post(body=message, subtype_id=self.env.ref("mail.mt_note").id) - def _compute_date_planned(self): - for order in self: - if order.date_approve: - leadtime = order.partner_id.leadtime - current_time = order.date_approve - delta_time = current_time + timedelta(days=leadtime) - delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') - order.date_planned = delta_time - else: - order.date_planned = False + # def _compute_date_planned(self): + # for order in self: + # if order.date_approve: + # leadtime = order.partner_id.leadtime + # current_time = order.date_approve + # delta_time = current_time + timedelta(days=leadtime) + # delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') + # order.date_planned = delta_time + # else: + # order.date_planned = False def action_create_invoice(self): res = super(PurchaseOrder, self).action_create_invoice() @@ -959,6 +1016,9 @@ class PurchaseOrder(models.Model): if self.amount_untaxed >= 50000000 and not self.env.user.id == 21: raise UserError("Hanya Rafly Hanggara yang bisa approve") + + if not self.date_planned: + raise UserError("Receipt Date harus diisi") if self.total_percent_margin < self.total_so_percent_margin: self.env.user.notify_danger( @@ -975,7 +1035,7 @@ class PurchaseOrder(models.Model): # ) if not self.from_apo: - if (not self.matches_so or not self.sale_order_id) and not self.env.user.is_purchasing_manager and not self.env.user.is_leader and not self.manufacturing_id: + if not self.matches_so and not self.env.user.is_purchasing_manager and not self.env.user.is_leader: raise UserError("Tidak ada link dengan SO, harus di confirm oleh Purchasing Manager") send_email = False @@ -1010,10 +1070,10 @@ class PurchaseOrder(models.Model): self.approve_by = self.env.user.id # override date planned added with two days - leadtime = self.partner_id.leadtime - delta_time = current_time + timedelta(days=leadtime) - delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') - self.date_planned = delta_time + # leadtime = self.partner_id.leadtime + # delta_time = current_time + timedelta(days=leadtime) + # delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') + # self.date_planned = delta_time self.date_deadline_ref_date_planned() self.unlink_purchasing_job_state() @@ -1391,6 +1451,20 @@ class PurchaseOrder(models.Model): # Tambahkan pemanggilan method untuk handle pricelist system update self._handle_pricelist_system_update(vals) return res + + def action_open_change_date_wizard(self): + self.ensure_one() + return { + 'type': 'ir.actions.act_window', + 'res_model': 'change.date.planned.wizard', + 'view_mode': 'form', + 'target': 'new', + 'context': { + 'default_purchase_id': self.id, + 'default_new_date_planned': self.date_planned, + } + } + def _handle_pricelist_system_update(self, vals): if 'order_line' in vals or any(key in vals for key in ['state', 'approval_status']): @@ -1479,4 +1553,32 @@ class PurchaseOrderUnlockWizard(models.TransientModel): order.approval_status_unlock = 'pengajuanFinance' return {'type': 'ir.actions.act_window_close'} +class ChangeDatePlannedWizard(models.TransientModel): + _name = 'change.date.planned.wizard' + _description = 'Change Date Planned Wizard' + + purchase_id = fields.Many2one('purchase.order', string="Purchase Order", required=True) + new_date_planned = fields.Datetime(string="New Date Planned") # <- harus DTTM biar match + old_date_planned = fields.Datetime(string="Current Planned Date", related='purchase_id.date_planned', readonly=True) + reason = fields.Selection([ + ('delay', 'Delay By Vendor'), + ('urgent', 'Urgent Delivery'), + ], string='Reason') + date_changed = fields.Boolean(string="Date Changed", compute="_compute_date_changed") + + @api.depends('old_date_planned', 'new_date_planned') + def _compute_date_changed(self): + for rec in self: + rec.date_changed = ( + rec.old_date_planned and rec.new_date_planned and + rec.old_date_planned != rec.new_date_planned + ) + + def confirm_change(self): + self.purchase_id.write({ + 'date_planned': self.new_date_planned, + 'reason_change_date_planned': self.reason, + }) + + diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 7be0e8ff..4e36a9fb 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -350,7 +350,7 @@ class SaleOrder(models.Model): date_unhold = fields.Datetime(string='Date Unhold', tracking=True, readonly=True, help='Waktu ketika SO di Unhold' ) - et_products = fields.Datetime(string='ET Products', compute='_compute_et_products', help="Leadtime produk berdasarkan SLA vendor, tanpa logistik.") + et_products = fields.Datetime(string='ET Products', help="Leadtime produk berdasarkan SLA vendor, tanpa logistik.", tracking=True) eta_date_reserved = fields.Datetime( string="Date Reserved", @@ -381,6 +381,11 @@ class SaleOrder(models.Model): if self.id: self.ccm_id = self.env['tukar.guling'].search([('origin', 'ilike', self.name)], limit=1) + reason_change_date_planned = fields.Selection([ + ('delay', 'Delay By Vendor'), + ('urgent', 'Urgent Delivery'), + ], string='Reason Change Date Planned', tracking=True) + @api.depends('order_line.product_id', 'date_order') def _compute_et_products(self): jakarta = pytz.timezone("Asia/Jakarta") diff --git a/indoteknik_custom/models/sale_order_line.py b/indoteknik_custom/models/sale_order_line.py index 5e9fc362..64b9f9bc 100644 --- a/indoteknik_custom/models/sale_order_line.py +++ b/indoteknik_custom/models/sale_order_line.py @@ -1,6 +1,10 @@ from odoo import fields, models, api, _ from odoo.exceptions import UserError from datetime import datetime, timedelta +import logging +from odoo.tools.float_utils import float_compare + +_logger = logging.getLogger(__name__) class SaleOrderLine(models.Model): @@ -49,6 +53,9 @@ class SaleOrderLine(models.Model): qty_free_bu = fields.Float(string='Free BU', compute='_get_qty_free_bandengan') desc_updatable = fields.Boolean(string='desc boolean', default=True, compute='_get_desc_updatable') + is_has_disc = fields.Boolean('Flash Sale', default=False) + + def _get_outgoing_incoming_moves(self): outgoing_moves = self.env['stock.move'] incoming_moves = self.env['stock.move'] diff --git a/indoteknik_custom/models/shipment_group.py b/indoteknik_custom/models/shipment_group.py index 4969c35a..7203b566 100644 --- a/indoteknik_custom/models/shipment_group.py +++ b/indoteknik_custom/models/shipment_group.py @@ -36,6 +36,8 @@ class ShipmentGroup(models.Model): def create(self, vals): vals['number'] = self.env['ir.sequence'].next_by_code('shipment.group') or '0' result = super(ShipmentGroup, self).create(vals) + if result.shipment_line and result.shipment_line[0].partner_id: + result.partner_id = result.shipment_line[0].partner_id.id return result class ShipmentGroupLine(models.Model): diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index 3e152f10..825368de 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -303,6 +303,10 @@ class StockPicking(models.Model): approval_invoice_date_id = fields.Many2one('approval.invoice.date', string='Approval Invoice Date') last_update_date_doc_kirim = fields.Datetime(string='Last Update Tanggal Kirim', copy=False) update_date_doc_kirim_add = fields.Boolean(string='Update Tanggal Kirim Lewat ADD') + reason_change_date_planned = fields.Selection([ + ('delay', 'Delay By Vendor'), + ('urgent', 'Urgent Delivery'), + ], string='Reason Change Date Planned', tracking=True) def _get_kgx_awb_number(self): """Menggabungkan name dan origin untuk membuat AWB Number""" @@ -1380,6 +1384,12 @@ class StockPicking(models.Model): self.send_mail_bills() if 'BU/PUT' in self.name: self.automatic_reserve_product() + + if self.tukar_guling_id: + self.tukar_guling_id.update_state() + elif self.tukar_guling_po_id: + self.tukar_guling_po_id.update_state() + return res def automatic_reserve_product(self): diff --git a/indoteknik_custom/models/tukar_guling.py b/indoteknik_custom/models/tukar_guling.py index 7253afb7..5411b17c 100644 --- a/indoteknik_custom/models/tukar_guling.py +++ b/indoteknik_custom/models/tukar_guling.py @@ -5,7 +5,8 @@ from datetime import datetime _logger = logging.getLogger(__name__) -#TODO + +# TODO # 1. tracking status dokumen BU [X] # 2. ganti nama dokumen # 3. Tracking ketika create dokumen [X] @@ -16,11 +17,11 @@ _logger = logging.getLogger(__name__) class TukarGuling(models.Model): _name = 'tukar.guling' - _description = 'Tukar Guling' + _description = 'Pengajuan Retur SO' _order = 'date desc, id desc' _rec_name = 'name' _inherit = ['mail.thread', 'mail.activity.mixin'] - + partner_id = fields.Many2one('res.partner', string='Customer', readonly=True) origin = fields.Char(string='Origin SO') if_so = fields.Boolean('Is SO', default=True) @@ -62,6 +63,7 @@ class TukarGuling(models.Model): ('approval_sales', ' Approval Sales'), ('approval_finance', 'Approval Finance'), ('approval_logistic', 'Approval Logistic'), + ('approved', 'Waiting for Operations'), ('done', 'Done'), ('cancel', 'Canceled') ], default='draft', tracking=True, required=True) @@ -98,7 +100,7 @@ class TukarGuling(models.Model): @api.onchange('operations') def _onchange_operations(self): """Auto-populate lines ketika operations dipilih""" - if self.operations.picking_type_id.id not in [29,30]: + if self.operations.picking_type_id.id not in [29, 30]: 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: @@ -217,7 +219,6 @@ class TukarGuling(models.Model): self.origin = False - def action_populate_lines(self): """Manual button untuk populate lines - sebagai alternatif""" self.ensure_one() @@ -257,7 +258,7 @@ class TukarGuling(models.Model): def _check_product_lines(self): """Constraint: Product lines harus ada jika state bukan draft""" for record in self: - if record.state in ('approval_sales', 'approval_logistic', 'approval_finance', + if record.state in ('approval_sales', 'approval_logistic', 'approval_finance', 'approved', 'done') and not record.line_ids: raise ValidationError("Product lines harus diisi sebelum submit atau approve!") @@ -281,11 +282,11 @@ class TukarGuling(models.Model): return True - def _is_already_returned(self, picking): - return self.env['stock.picking'].search_count([ - ('origin', '=', 'Return of %s' % picking.name), - ('state', '!=', 'cancel') - ]) > 0 + # def _is_already_returned(self, picking): + # return self.env['stock.picking'].search_count([ + # ('origin', '=', 'Return of %s' % picking.name), + # ('state', '!=', 'cancel') + # ]) > 0 @api.constrains('return_type', 'operations') def _check_invoice_on_revisi_so(self): @@ -345,7 +346,7 @@ class TukarGuling(models.Model): def write(self, vals): self.ensure_one() - if self.operations.picking_type_id.id not in [29,30]: + 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() operasi = self.operations.picking_type_id.id @@ -376,24 +377,33 @@ class TukarGuling(models.Model): # if self.state == 'done': # raise UserError ("Tidak Boleh delete ketika sudahh done") for record in self: - if record.state == 'done': + if record.state == 'approved' or record.state == 'done': raise UserError( - "Tidak bisa hapus pengajuan jika sudah done, set ke draft terlebih dahulu jika ingin menghapus") - ongoing_bu = self.picking_ids.filtered(lambda p: p.state != 'done') + "Tidak bisa hapus pengajuan jika sudah Approved, set ke draft terlebih dahulu jika ingin menghapus") + ongoing_bu = self.picking_ids.filtered(lambda p: p.state != 'approved') for picking in ongoing_bu: picking.action_cancel() return super(TukarGuling, self).unlink() def action_view_picking(self): self.ensure_one() - action = self.env.ref('stock.action_picking_tree_all').read()[0] - pickings = self.picking_ids - if len(pickings) > 1: - action['domain'] = [('id', 'in', pickings.ids)] - elif pickings: - action['views'] = [(self.env.ref('stock.view_picking_form').id, 'form')] - action['res_id'] = pickings.id - return action + + # picking_origin = f"Return of {self.operations.name}" + returs = self.env['stock.picking'].search([ + ('tukar_guling_id', '=', self.id), + ]) + + if not returs: + raise UserError("Doc Retrun Not Found") + + return { + 'type': 'ir.actions.act_window', + 'name': 'Delivery Pengajuan Retur SO', + 'res_model': 'stock.picking', + 'view_mode': 'tree,form', + 'domain': [('id', 'in', returs.ids)], + 'target': 'current', + } def action_draft(self): """Reset to draft state""" @@ -434,8 +444,8 @@ class TukarGuling(models.Model): linked_bu_out = picking.linked_manual_bu_out if linked_bu_out and linked_bu_out.state == 'done': raise UserError("❌ Tidak bisa retur BU/PICK karena BU/OUT suda Done!") - if self._is_already_returned(self.operations): - raise UserError("BU ini sudah pernah diretur oleh dokumen lain.") + # if self._is_already_returned(self.operations): + # raise UserError("BU ini sudah pernah diretur oleh dokumen lain.") if self.operations.picking_type_id.id == 29: for line in self.line_ids: @@ -452,6 +462,47 @@ class TukarGuling(models.Model): raise UserError("Submit hanya bisa dilakukan dari Draft.") self.state = 'approval_sales' + def update_state(self): + # OUT tukar guling + if self.operations.picking_type_id.id == 29 and self.return_type == 'tukar_guling': + total_out = self.env['stock.picking'].search_count([ + ('tukar_guling_id', '=', self.id), + ('picking_type_id', '=', 29), + ]) + done_out = self.env['stock.picking'].search_count([ + ('tukar_guling_id', '=', self.id), + ('picking_type_id', '=', 29), + ('state', '=', 'done'), + ]) + if self.state == 'approved' and total_out > 0 and done_out == total_out: + self.state = 'done' + + # OUT revisi SO + elif self.operations.picking_type_id.id == 29 and self.return_type == 'revisi_so': + total_ort = self.env['stock.picking'].search_count([ + ('tukar_guling_id', '=', self.id), + ('picking_type_id', '=', 74), + ]) + done_ort = self.env['stock.picking'].search_count([ + ('tukar_guling_id', '=', self.id), + ('picking_type_id', '=', 74), + ('state', '=', 'done'), + ]) + if self.state == 'approved' and total_ort > 0 and done_ort == total_ort: + self.state = 'done' + + # PICK revisi SO + elif self.operations.picking_type_id.id == 30 and self.return_type == 'revisi_so': + done_ort = self.env['stock.picking'].search([ + ('tukar_guling_id', '=', self.id), + ('picking_type_id', '=', 74), + ('state', '=', 'done'), + ]) + if self.state == 'approved' and done_ort: + self.state = 'done' + else: + raise UserError("Tidak bisa menentukan jenis retur.") + def action_approve(self): self.ensure_one() self._validate_product_lines() @@ -501,7 +552,7 @@ class TukarGuling(models.Model): elif rec.state == 'approval_logistic': if not rec.env.user.has_group('indoteknik_custom.group_role_logistic'): raise UserError("Hanya Logistic Manager yang boleh approve tahap ini.") - rec.state = 'done' + rec.state = 'approved' rec._create_pickings() rec.date_logistic = now @@ -597,7 +648,8 @@ class TukarGuling(models.Model): ### ======== ORT dari BU/PICK ========= ort_pickings = [] is_retur_from_bu_pick = record.operations.picking_type_id.id == 30 - picks_to_return = [record.operations] if is_retur_from_bu_pick else mapping_koli.mapped('pick_id') or line.product_uom_qty + picks_to_return = [record.operations] if is_retur_from_bu_pick else mapping_koli.mapped( + 'pick_id') or line.product_uom_qty for pick in picks_to_return: ort_return_lines = [] @@ -613,7 +665,8 @@ class TukarGuling(models.Model): 'quantity': line.product_uom_qty, 'move_id': move.id, })) - _logger.info(f"📟 ORT (BU/PICK langsung) | {pick.name} | {line.product_id.display_name} | qty={line.product_uom_qty}") + _logger.info( + f"📟 ORT (BU/PICK langsung) | {pick.name} | {line.product_id.display_name} | qty={line.product_uom_qty}") else: # Ambil dari mapping koli for mk in mapping_koli.filtered(lambda m: m.pick_id == pick): @@ -626,7 +679,8 @@ class TukarGuling(models.Model): 'quantity': mk.qty_return, 'move_id': move.id, })) - _logger.info(f"📟 ORT (mapping koli) | {pick.name} | {mk.product_id.display_name} | qty={mk.qty_return}") + _logger.info( + f"📟 ORT (mapping koli) | {pick.name} | {mk.product_id.display_name} | qty={mk.qty_return}") if ort_return_lines: ort_wizard = self.env['stock.return.picking'].with_context({ @@ -808,18 +862,17 @@ class StockPicking(models.Model): message = _( "📦 <b>%s</b> Validated by <b>%s</b> Status Changed <b>%s</b> at <b>%s</b>." ) % ( - picking.name, - # picking.picking_type_id.name, - picking.env.user.name, - picking.state, - fields.Datetime.now().strftime("%d/%m/%Y %H:%M") - ) + picking.name, + # picking.picking_type_id.name, + picking.env.user.name, + picking.state, + fields.Datetime.now().strftime("%d/%m/%Y %H:%M") + ) picking.tukar_guling_id.message_post(body=message) return res - class TukarGulingMappingKoli(models.Model): _name = 'tukar.guling.mapping.koli' _description = 'Mapping Koli di Tukar Guling' @@ -830,6 +883,7 @@ class TukarGulingMappingKoli(models.Model): qty_done = fields.Float(string='Qty Done BU PICK') qty_return = fields.Float(string='Qty diretur') sequence = fields.Integer(string='Sequence', default=10) + @api.constrains('qty_return') def _check_qty_return_editable(self): for rec in self: @@ -840,4 +894,4 @@ class TukarGulingMappingKoli(models.Model): for rec in self: if rec.tukar_guling_id and rec.tukar_guling_id.state not in ['draft', 'cancel']: raise UserError("Tidak bisa menghapus Mapping Koli karena status Tukar Guling bukan Draft atau Cancel.") - return super(TukarGulingMappingKoli, self).unlink()
\ No newline at end of file + return super(TukarGulingMappingKoli, self).unlink() diff --git a/indoteknik_custom/models/tukar_guling_po.py b/indoteknik_custom/models/tukar_guling_po.py index 7c9680f8..23ca1923 100644 --- a/indoteknik_custom/models/tukar_guling_po.py +++ b/indoteknik_custom/models/tukar_guling_po.py @@ -10,7 +10,7 @@ _logger = logging.getLogger(__name__) class TukarGulingPO(models.Model): _name = 'tukar.guling.po' - _description = 'Tukar Guling PO' + _description = 'Pengajuan Retur PO' _inherit = ['mail.thread', 'mail.activity.mixin'] vendor_id = fields.Many2one('res.partner', string='Vendor Name', readonly=True) @@ -49,6 +49,7 @@ class TukarGulingPO(models.Model): ('approval_purchase', 'Approval Purchasing'), ('approval_finance', 'Approval Finance'), ('approval_logistic', 'Approval Logistic'), + ('approved', 'Waiting for Operations'), ('done', 'Done'), ('cancel', 'Cancel'), ], string='Status', default='draft', tracking=3) @@ -245,12 +246,12 @@ class TukarGulingPO(models.Model): return True - def _is_already_returned(self, picking): - return self.env['stock.picking'].search_count([ - ('origin', '=', 'Return of %s' % picking.name), - # ('returned_from_id', '=', picking.id), - ('state', 'not in', ['cancel', 'draft']), - ]) > 0 + # def _is_already_returned(self, picking): + # return self.env['stock.picking'].search_count([ + # ('origin', '=', 'Return of %s' % picking.name), + # # ('returned_from_id', '=', picking.id), + # ('state', 'not in', ['cancel', 'draft']), + # ]) > 0 def copy(self, default=None): if default is None: @@ -311,7 +312,7 @@ class TukarGulingPO(models.Model): def unlink(self): for record in self: - if record.state == 'done': + if record.state == 'done' or record.state == 'approved': raise UserError("Tidak bisa hapus pengajuan jika sudah done, set ke draft terlebih dahulu") ongoing_bu = self.po_picking_ids.filtered(lambda p: p.state != 'done') for picking in ongoing_bu: @@ -320,14 +321,23 @@ class TukarGulingPO(models.Model): def action_view_picking(self): self.ensure_one() - action = self.env.ref('stock.action_picking_tree_all').read()[0] - pickings = self.po_picking_ids - if len(pickings) > 1: - action['domain'] = [('id', 'in', pickings.ids)] - elif pickings: - action['views'] = [(self.env.ref('stock.view_picking_form').id, 'form')] - action['res_id'] = pickings.id - return action + + # picking_origin = f"Return of {self.operations.name}" + returs = self.env['stock.picking'].search([ + ('tukar_guling_po_id', '=', self.id), + ]) + + if not returs: + raise UserError("Doc Retrun Not Found") + + return { + 'type': 'ir.actions.act_window', + 'name': 'Delivery Pengajuan Retur PO', + 'res_model': 'stock.picking', + 'view_mode': 'tree,form', + 'domain': [('id', 'in', returs.ids)], + 'target': 'current', + } def action_draft(self): """Reset to draft state""" @@ -365,8 +375,8 @@ class TukarGulingPO(models.Model): if pick_id not in [75, 28]: raise UserError("❌ Tidak bisa retur bukan BU/INPUT atau BU/PUT!") - if self._is_already_returned(self.operations): - raise UserError("BU ini sudah pernah diretur oleh dokumen lain.") + # if self._is_already_returned(self.operations): + # raise UserError("BU ini sudah pernah diretur oleh dokumen lain.") if self.state != 'draft': raise UserError("Submit hanya bisa dilakukan dari Draft.") @@ -403,12 +413,50 @@ class TukarGulingPO(models.Model): elif rec.state == 'approval_logistic': if not rec.env.user.has_group('indoteknik_custom.group_role_logistic'): raise UserError("Hanya Logistic Manager yang boleh approve tahap ini.") - rec.state = 'done' + rec.state = 'approved' rec._create_pickings() rec.date_logistic = now else: raise UserError("Status ini tidak bisa di-approve.") + def update_stae(self): + # bu input rev po + if self.operations.picking_type_id.id == 28 and self.return_type == 'revisi_po': + prt = self.env['stock.picking'].search([ + ('tukar_guling_po_id', '=', self.id), + ('state', '=', 'done'), + ('picking_type_id.id', '=', 76) + ]) + if self.state == 'aproved' and prt: + self.state = 'done' + # bu put rev po + elif self.operations.picking_type_id.id == 75 and self.return_type == 'revisi_po': + total_prt = self.env['stock.picking'].search_count([ + ('tukar_guling_po_id', '=', self.id), + ('picking_type_id.id', '=', 76) + ]) + prt = self.env['stock.picking'].search_count([ + ('tukar_guling_po_id', '=', self.id), + ('state', '=', 'done'), + ('picking_type_id.id', '=', 76) + ]) + if self.state == 'aproved' and total_prt > 0 and prt == total_prt: + self.state = 'done' + # bu put tukar guling + elif self.operations.picking_type_id.id == 75 and self.return_type == 'tukar_guling': + total_put = self.env['stock.picking'].search_count([ + ('tukar_guling_po_id', '=', self.id), + ('picking_type_id.id', '=', 75) + ]) + put = self.env['stock.picking'].search_count([ + ('tukar_guling_po_id', '=', self.id), + ('state', '=', 'done'), + ('picking_type_id.id', '=', 75) + ]) + if self.state == 'aproved' and total_put > 0 and put == total_put: + self.state = 'done' + + def action_cancel(self): self.ensure_one() # if self.state == 'done': @@ -629,7 +677,7 @@ class TukarGulingLinePO(models.Model): @api.constrains('product_uom_qty') def _check_qty_change_allowed(self): for rec in self: - if rec.tukar_guling_id and rec.tukar_guling_po_id.state not in ['draft', 'cancel']: + if rec.tukar_guling_po_id and rec.tukar_guling_po_id.state not in ['draft', 'cancel']: raise ValidationError("Tidak bisa mengubah Quantity karena status dokumen bukan Draft atau Cancel.") def unlink(self): diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 0ac3e86c..9b43bf2a 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -161,6 +161,7 @@ access_konfirm_koli,access.konfirm.koli,model_konfirm_koli,,1,1,1,1 access_stock_immediate_transfer,access.stock.immediate.transfer,model_stock_immediate_transfer,,1,1,1,1 access_coretax_faktur,access.coretax.faktur,model_coretax_faktur,,1,1,1,1 access_purchase_order_unlock_wizard,access.purchase.order.unlock.wizard,model_purchase_order_unlock_wizard,,1,1,1,1 +access_change_date_planned_wizard,access.change.date.planned.wizard,model_change_date_planned_wizard,,1,1,1,1 access_sales_order_koli,access.sales.order.koli,model_sales_order_koli,,1,1,1,1 access_stock_backorder_confirmation,access.stock.backorder.confirmation,model_stock_backorder_confirmation,,1,1,1,1 access_warning_modal_wizard,access.warning.modal.wizard,model_warning_modal_wizard,,1,1,1,1 @@ -183,8 +184,7 @@ access_production_purchase_match,access.production.purchase.match,model_producti access_image_carousel,access.image.carousel,model_image_carousel,,1,1,1,1 access_v_sale_notin_matchpo,access.v.sale.notin.matchpo,model_v_sale_notin_matchpo,,1,1,1,1 access_approval_payment_term,access.approval.payment.term,model_approval_payment_term,,1,1,1,1 -access_refund_sale_order,access.refund.sale.order,model_refund_sale_order,base.group_user,1,1,1,1 -access_refund_sale_order_line,access.refund.sale.order.line,model_refund_sale_order_line,base.group_user,1,1,1,1 + access_purchasing_job_seen,purchasing.job.seen,model_purchasing_job_seen,,1,1,1,1 access_tukar_guling_all_users,tukar.guling.all.users,model_tukar_guling,base.group_user,1,1,1,1 diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml index ff223125..fedcb4f9 100755 --- a/indoteknik_custom/views/purchase_order.xml +++ b/indoteknik_custom/views/purchase_order.xml @@ -75,11 +75,13 @@ </field> <field name="partner_id" position="after"> <field name="purchase_order_count"/> + <field name="complete_bu_in_count" invisible="1"/> </field> <field name="incoterm_id" position="after"> <field name="amount_total_without_service"/> <field name="delivery_amt"/> <field name="approve_by"/> + <field name="reason_change_date_planned"/> </field> <field name="currency_id" position="after"> <field name="summary_qty_po"/> @@ -106,9 +108,16 @@ <field name="product_id" position="attributes"> <attribute name="options">{'no_create': True}</attribute> </field> - <field name="date_planned" position="attributes"> - <attribute name="invisible">1</attribute> - </field> + <xpath expr="//field[@name='date_planned']" position="replace"> + <field name="date_planned" readonly="1"/> + </xpath> + <xpath expr="//field[@name='date_planned']" position="after"> + <button name="action_open_change_date_wizard" + type="object" + string="Change Receipt Date" + class="btn-primary" + attrs="{'invisible': ['|', ('state', '=', 'cancel'), ('complete_bu_in_count', '=', 0)]}"/> + </xpath> <field name="product_qty" position="before"> <field name="is_edit_product_qty" readonly="1" optional="hide"/> <field name="qty_onhand" readonly="1" optional="hide"/> @@ -225,6 +234,34 @@ </data> <data> + <record id="view_change_date_planned_wizard_form" model="ir.ui.view"> + <field name="name">change.date.planned.wizard.form</field> + <field name="model">change.date.planned.wizard</field> + <field name="arch" type="xml"> + <form string="Change Date Planned"> + <group> + <field name="purchase_id" readonly="1"/> + <field name="old_date_planned" readonly="1"/> + <field name="date_changed" invisible="1"/> + <field name="new_date_planned"/> + <field name="reason" + attrs="{ + 'invisible': ['|', ('old_date_planned', '=', False), ('date_changed', '=', False)], + 'required': [('date_changed', '=', True)] + }"/> + </group> + + <footer> + <button name="confirm_change" type="object" string="Confirm" class="btn-primary"/> + <button string="Cancel" class="btn-secondary" special="cancel"/> + </footer> + </form> + </field> + </record> + </data> + + + <data> <record id="rfq_order_tree_view_inherit" model="ir.ui.view"> <field name="name">Purchase</field> <field name="model">purchase.order</field> diff --git a/indoteknik_custom/views/refund_sale_order.xml b/indoteknik_custom/views/refund_sale_order.xml deleted file mode 100644 index 4f791722..00000000 --- a/indoteknik_custom/views/refund_sale_order.xml +++ /dev/null @@ -1,199 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<odoo> - <!-- Tree View --> - <record id="view_refund_sale_order_tree" model="ir.ui.view"> - <field name="name">refund.sale.order.tree</field> - <field name="model">refund.sale.order</field> - <field name="arch" type="xml"> - <tree string="Refund Sales Orders"> - <field name="name" readonly="1"/> - <field name="created_date" readonly="1"/> - <field name="partner_id" readonly="1"/> - <field name="sale_order_ids" widget="many2many_tags" readonly="1"/> - <field name="uang_masuk" readonly="1"/> - <field name="ongkir" readonly="1"/> - <field name="total_invoice" readonly="1"/> - <field name="amount_refund" readonly="1"/> - <field name="status" - decoration-info="status == 'draft'" - decoration-danger="status == 'reject'" - decoration-success="status == 'refund'" - decoration-warning="status == 'pengajuan1' or status == 'pengajuan2' or status == 'pengajuan3'" - widget="badge" - readonly="1"/> - <field name="status_payment" - decoration-info="status_payment == 'pending'" - decoration-danger="status_payment == 'reject'" - decoration-success="status_payment == 'done'" - widget="badge" - readonly="1"/> - <field name="refund_date" readonly="1"/> - <field name="amount_refund_text" readonly="1" optional="hide"/> - <field name="invoice_ids" readonly="1" optional="hide"/> - <field name="refund_type" readonly="1" optional="hide"/> - <field name="user_ids" readonly="1" optional="hide"/> - </tree> - </field> - </record> - - <!-- Form View --> - <record id="view_refund_sale_order_form" model="ir.ui.view"> - <field name="name">refund.sale.order.form</field> - <field name="model">refund.sale.order</field> - <field name="arch" type="xml"> - <form string="Refund Sales Order"> - <header> - <button name="action_ask_approval" - type="object" - string="Ask Approval" - attrs="{'invisible': [('status', '!=', 'draft')]}"/> - - <button name="action_approve_flow" - type="object" - string="Approve" - class="oe_highlight" - attrs="{'invisible': [('status', 'in', ['refund', 'reject', 'draft'])]}"/> - <button name="action_trigger_cancel" - type="object" - string="Cancel" - attrs="{'invisible': ['|', ('status_payment', '!=', 'pending'), ('status', '=', 'reject')]}" /> - <button name="action_confirm_refund" - type="object" - string="Confirm Refund" - class="btn-primary" - attrs="{'invisible': ['|', ('status', 'not in', ['pengajuan3','refund']), ('status_payment', '!=', 'pending')]}"/> - <button name="action_create_journal_refund" - string="Journal Refund" - type="object" - class="oe_highlight" - attrs="{'invisible': ['|', ('status', 'not in', ['pengajuan3','refund']), ('journal_refund_state', '=', 'posted')]}"/> - - <field name="status" - widget="statusbar" - statusbar_visible="draft,pengajuan1,pengajuan2,pengajuan3,reject" - attrs="{'invisible': [('status', '!=', 'reject')]}" /> - - <field name="status" - widget="statusbar" - statusbar_visible="draft,pengajuan1,pengajuan2,pengajuan3,refund" - attrs="{'invisible': [('status', '=', 'reject')]}" /> - </header> - <sheet> - <div class="oe_button_box" name="button_box"> - <button name="action_open_journal_refund" - type="object" - class="oe_stat_button" - icon="fa-book" - width="250px" - attrs="{'invisible': ['|', ('journal_refund_move_id', '=', False), ('journal_refund_state', '!=', 'posted')]}"> - <field name="journal_refund_move_id" string="Journal Refund" widget="statinfo"/> - </button> - </div> - <widget name="web_ribbon" - title="PAID" - bg_color="bg-success" - attrs="{'invisible': [('status_payment', '!=', 'done')]}"/> - - <widget name="web_ribbon" - title="CANCEL" - bg_color="bg-danger" - attrs="{'invisible': [('status_payment', '!=', 'reject')]}"/> - <h1> - <field name="name" readonly="1"/> - </h1> - <group col="2"> - <group> - <field name="is_locked" invisible="1"/> - <field name="status_payment" invisible="1"/> - <field name="journal_refund_state" invisible="1"/> - - <field name="partner_id" attrs="{'readonly': [('is_locked', '=', True)]}"/> - <field name="sale_order_ids" widget="many2many_tags" attrs="{'readonly': [('is_locked', '=', True)]}"/> - <field name="invoice_ids" widget="many2many_tags" readonly="1"/> - <field name="invoice_names" widget="html" readonly="1"/> - <field name="so_names" widget="html" readonly="1"/> - <field name="advance_move_names" widget="html" readonly="1"/> - <field name="refund_type" attrs="{'readonly': [('is_locked', '=', True)]}"/> - <field name="note_refund" attrs="{'readonly': [('is_locked', '=', True)]}"/> - </group> - <group> - <field name="uang_masuk" attrs="{'readonly': [('is_locked', '=', True)]}"/> - <field name="total_invoice" attrs="{'readonly': [('is_locked', '=', True)]}"/> - <field name="ongkir" attrs="{'readonly': [('is_locked', '=', True)]}"/> - <field name="amount_refund" attrs="{'readonly': [('is_locked', '=', True)]}"/> - <field name="amount_refund_text" readonly="1"/> - <field name="uang_masuk_type" required="1" attrs="{'readonly': [('is_locked', '=', True)]}"/> - <field name="bukti_uang_masuk_image" widget="image" - attrs="{'invisible': [('uang_masuk_type', '=', 'pdf')], 'readonly': [('is_locked', '=', True)]}"/> - <field name="bukti_uang_masuk_pdf" widget="pdf_viewer" - attrs="{'invisible': [('uang_masuk_type', '=', 'image')], 'readonly': [('is_locked', '=', True)]}"/> - </group> - </group> - - <notebook> - <page string="Produk Line"> - <field name="line_ids" attrs="{'readonly': [('is_locked', '=', True)]}"> - <tree editable="bottom"> - <field name="product_id"/> - <field name="quantity"/> - <field name="reason"/> - </tree> - </field> - </page> - - <page string="Other Info"> - <group col="2"> - <group> - <field name="user_ids" widget="many2many_tags" readonly="1"/> - <field name="created_date" readonly="1"/> - <field name="refund_date" attrs="{'readonly': [('status', 'not in', ['pengajuan3','refund'])]}"/> - </group> - <group> - <field name="bank" attrs="{'readonly': [('is_locked', '=', True)]}"/> - <field name="account_name" attrs="{'readonly': [('is_locked', '=', True)]}"/> - <field name="account_no" attrs="{'readonly': [('is_locked', '=', True)]}"/> - </group> - </group> - </page> - - <page string="Finance Note"> - <group col="2"> - <group> - <field name="finance_note" attrs="{'readonly': [('is_locked', '=', True)]}"/> - </group> - <group> - <field name="bukti_refund_type" reqiured="1" attrs="{'readonly': [('is_locked', '=', True)]}"/> - <field name="bukti_transfer_refund_pdf" widget="pdf_viewer" attrs="{'invisible': [('bukti_refund_type', '=', 'image')]}"/> - <field name="bukti_transfer_refund_image" widget="image" attrs="{'invisible': [('bukti_refund_type', '=', 'pdf')]}"/> - </group> - </group> - </page> - - <page string="Cancel Reason" attrs="{'invisible': [('status', '=', 'refund')]}"> - <group> - <field name="reason_reject"/> - </group> - </page> - </notebook> - </sheet> - <div class="oe_chatter"> - <field name="message_follower_ids" widget="mail_followers"/> - <field name="message_ids" widget="mail_thread"/> - </div> - </form> - </field> - </record> - <!-- Action --> - <record id="action_refund_sale_order" model="ir.actions.act_window"> - <field name="name">Refund Sales Order</field> - <field name="res_model">refund.sale.order</field> - <field name="view_mode">tree,form</field> - </record> - - <!-- Menu --> - <menuitem id="menu_refund_sale_order" - name="Refund" - parent="sale.sale_order_menu" - sequence="10" - action="action_refund_sale_order"/> -</odoo> diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index c1f1fe61..e8f41ca3 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -172,6 +172,7 @@ <xpath expr="//page[@name='other_information']/group/group[@name='sale_reporting']" position="after"> <group string="ETA"> <field name="et_products"/> + <field name="reason_change_date_planned" readonly="1"/> <field name="eta_date_reserved"/> <field name="expected_ready_to_ship"/> <field name="eta_date_start"/> @@ -290,6 +291,7 @@ <field name="note_procurement" optional="hide"/> <field name="vendor_subtotal" 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"/> <field name="order_promotion_id" string="Promotion" readonly="1" optional="hide"/> </xpath> diff --git a/indoteknik_custom/views/stock_picking.xml b/indoteknik_custom/views/stock_picking.xml index f9200dfa..b3f0ce9f 100644 --- a/indoteknik_custom/views/stock_picking.xml +++ b/indoteknik_custom/views/stock_picking.xml @@ -129,6 +129,9 @@ <field name="date_done" position="after"> <field name="arrival_time"/> </field> + <field name="scheduled_date" position="attributes"> + <attribute name="readonly">1</attribute> + </field> <field name="origin" position="after"> <!-- <field name="show_state_approve_md" invisible="1" optional="hide"/>--> <field name="state_approve_md" widget="badge"/> @@ -165,6 +168,7 @@ <field name="approval_receipt_status"/> <field name="approval_return_status"/> <field name="so_lama"/> + <field name="reason_change_date_planned" readonly="1"/> </field> <field name="product_id" position="before"> <field name="line_no" attrs="{'readonly': 1}" optional="hide"/> diff --git a/indoteknik_custom/views/tukar_guling.xml b/indoteknik_custom/views/tukar_guling.xml index a79f8b55..c23995d3 100644 --- a/indoteknik_custom/views/tukar_guling.xml +++ b/indoteknik_custom/views/tukar_guling.xml @@ -23,16 +23,18 @@ <field name="arch" type="xml"> <tree create="1" delete="1" default_order="create_date desc"> <field name="name"/> - <field name="date"/> + <field name="partner_id" string="Customer"/> <field name="origin" string="SO Number"/> <field name="operations" string="Operations"/> <field name="return_type" string="Return Type"/> <field name="state" widget="badge" decoration-info="state in ('draft', 'approval_sales', 'approval_finance','approval_logistic')" + decoration-warning="state == 'approved'" decoration-success="state == 'done'" decoration-muted="state == 'cancel'" /> <field name="ba_num" string="Nomor BA"/> + <field name="date"/> <field name="date_logistic" string="Approved Date"/> </tree> </field> @@ -57,7 +59,7 @@ class="btn-secondary" attrs="{'invisible': [('state', '!=', 'cancel')]}"/> <field name="state" widget="statusbar" readonly="1" - statusbar_visible="draft,approval_sales,approval_logistic,approval_finance,done"/> + statusbar_visible="draft,approval_sales,approval_logistic,approval_finance,approved,done"/> </header> <sheet> <div class="oe_button_box"> @@ -65,7 +67,7 @@ type="object" class="oe_stat_button" icon="fa-truck" - attrs="{'invisible': [('picking_ids', '=', False), ('state', 'in', ['draft', 'approval_sales', 'approval_logistic', 'approval_finance'])]}"> + attrs="{'invisible': [('picking_ids', '=', False), ('state', 'in', ['draft', 'approval_sales', 'approval_logistic', 'approval_finance', 'approved', 'done', 'cancel'])]}"> <field name="picking_ids" widget="statinfo" string="Delivery"/> </button> </div> diff --git a/indoteknik_custom/views/tukar_guling_po.xml b/indoteknik_custom/views/tukar_guling_po.xml index 77feb05f..accf7dbc 100644 --- a/indoteknik_custom/views/tukar_guling_po.xml +++ b/indoteknik_custom/views/tukar_guling_po.xml @@ -23,18 +23,19 @@ <field name="arch" type="xml"> <tree create="1" delete="1" default_order="create_date desc"> <field name="name"/> - <field name="date"/> - <field name="origin" string="PO Number"/> + <field name="vendor_id" string="Customer"/> + <field name="origin" string="SO Number"/> <field name="operations" string="Operations"/> <field name="return_type" string="Return Type"/> - <field name="ba_num" string="Nomor BA"/> - <field name="return_type" string="Return Type"/> <field name="state" widget="badge" decoration-info="state in ('draft', 'approval_purchase', 'approval_finance','approval_logistic')" + decoration-warning="state == 'approved'" decoration-success="state == 'done'" decoration-muted="state == 'cancel'" /> - <field name="date_logistic" string="Approved Date"/> + <field name="ba_num" string="Nomor BA"/> + <field name="date"/> + <field name="date_logistic" string="Approved Date"/> </tree> </field> </record> @@ -60,7 +61,7 @@ attrs="{'invisible': [('state', '!=', 'cancel')]}" confirm="Are you sure you want to reset this record to draft?"/> <field name="state" widget="statusbar" readonly="1" - statusbar_visible="draft,approval_purchase,approval_logistic,approval_finance,done"/> + statusbar_visible="draft,approval_purchase,approval_logistic,approval_finance,approved,done"/> </header> <sheet> <div class="oe_button_box"> |
