summaryrefslogtreecommitdiff
path: root/indoteknik_custom/models
diff options
context:
space:
mode:
authorMiqdad <ahmadmiqdad27@gmail.com>2025-06-16 14:38:40 +0700
committerMiqdad <ahmadmiqdad27@gmail.com>2025-06-16 14:38:40 +0700
commita0e90200638e26ad06d1caaf2d91d0aeea3ba19d (patch)
tree34adea34676cc913273ae3a4c87845ef5df204db /indoteknik_custom/models
parent0b6109930666039ed8e12569b6a9de7cbb4ea216 (diff)
<miqdad> add tukar guling PO and move from inventory
Diffstat (limited to 'indoteknik_custom/models')
-rw-r--r--indoteknik_custom/models/tukar_guling.py211
1 files changed, 146 insertions, 65 deletions
diff --git a/indoteknik_custom/models/tukar_guling.py b/indoteknik_custom/models/tukar_guling.py
index f8cbec0a..95aa7cd6 100644
--- a/indoteknik_custom/models/tukar_guling.py
+++ b/indoteknik_custom/models/tukar_guling.py
@@ -12,66 +12,34 @@ class TukarGuling(models.Model):
date = fields.Datetime('Date', default=fields.Datetime.now, required=True)
out_num = fields.Many2one('stock.picking', 'Nomor BU/Out',
domain=[('picking_type_id.code', '=', 'outgoing')])
- in_num = fields.Many2one('stock.picking', 'Nomor BU/In', domain=[('picking_type_id.code', '=', 'incoming')])
ba_num = fields.Text('Nomor BA')
notes = fields.Text('Notes')
return_type = fields.Selection(String='Return Type', selection=[
('tukar_guling', 'Tukar Guling'), # -> barang yang sama
('revisi_so', 'Revisi SO'), # -> ganti barang ?
- ('revisi_po', 'Revisi PO'),
- ('credit_memo', 'Credit Memo'), # -> dijadiin credit memo
- ('debit_memo', 'Debit Memo')])
+ ('credit_memo', 'Credit Memo')]) # -> dijadiin credit memo
state = fields.Selection(string='Status', selection=[
('draft', 'Draft'),
- ('waiting', 'Waiting for Approval'),
+ ('approval_sales', ' Approval Sales'),
+ ('approval_logistic', 'Approval Logistic'),
+ ('approval_finance', 'Approval Finance'),
('done', 'Done'),
('cancel', 'Canceled')
], default='draft', tracking=True, required=True)
line_ids = fields.One2many('tukar.guling.line', 'tukar_guling_id', string='Product Lines')
- @api.onchange('return_type')
- def _onchange_return_type(self):
- in_domain = []
- out_domain = []
-
- if self.return_type in ['debit_memo', 'revisi_po']:
- # Hanya tampilkan BU In
- in_domain = [('picking_type_id.code', '=', 'incoming')]
- out_domain = [('id', '=', False)] # Kosongkan BU Out
- elif self.return_type in ['revisi_so', 'credit_memo']:
- # Hanya tampilkan BU Out
- in_domain = [('id', '=', False)] # Kosongkan BU In
- out_domain = [('picking_type_id.code', '=', 'outgoing')]
- elif self.return_type == 'tukar_guling':
- # Boleh pilih keduanya
- in_domain = [('picking_type_id.code', '=', 'incoming')]
- out_domain = [('picking_type_id.code', '=', 'outgoing')]
-
- return {
- 'domain': {
- 'in_num': in_domain,
- 'out_num': out_domain,
- }
- }
-
- @api.constrains('return_type', 'in_num', 'out_num')
+ @api.constrains('return_type', 'out_num')
def _check_required_bu_fields(self):
for record in self:
- if record.return_type in ['debit_memo', 'revisi_po'] and not record.in_num:
- raise ValidationError("BU/In harus diisi untuk return type Debit Memo atau Revisi PO.")
-
- if record.return_type in ['revisi_so', 'credit_memo'] and not record.out_num:
- raise ValidationError("BU/Out harus diisi untuk return type Revisi SO atau Credit Memo.")
-
- if record.return_type == 'tukar_guling' and not (record.in_num or record.out_num):
- raise ValidationError("Untuk Tukar Guling, minimal isi salah satu, BU/In atau BU/Out.")
+ if record.return_type in ['revisi_so', 'credit_memo', 'tukar_guling'] and not record.out_num:
+ raise ValidationError("BU/Out harus diisi!")
@api.constrains('line_ids', 'state')
def _check_product_lines(self):
"""Constraint: Product lines harus ada jika state bukan draft"""
for record in self:
- if record.state in ('waiting', 'done') and not record.line_ids:
+ if record.state in ('approval_sales', 'approval_logistic', 'approval_finance', 'done') and not record.line_ids:
raise ValidationError("Product lines harus diisi sebelum submit atau approve!")
def _validate_product_lines(self):
@@ -95,29 +63,29 @@ class TukarGuling(models.Model):
return True
- @api.model_create_multi
- def create(self, vals_list):
- for vals in vals_list:
- if vals.get('name', 'New') == 'New':
- vals['name'] = self.env['ir.sequence'].next_by_code('tukar.guling') or 'PTG/00001'
- return super(TukarGuling, self).create(vals_list)
+ @api.model
+ def create(self, vals):
+ if not vals.get('name') or vals['name'] == 'New':
+ vals['name'] = self.env['ir.sequence'].next_by_code('tukar.guling') or 'New'
+ return super(TukarGuling, self).create(vals)
def copy(self, default=None):
- """Override copy untuk custom behavior saat duplicate"""
if default is None:
default = {}
- # Reset fields penting saat duplicate
+ if 'name' not in default:
+ default.update({
+ 'name': self.env['ir.sequence'].next_by_code(self._name) or 'New',
+ })
+
default.update({
- 'name': 'New',
'state': 'draft',
'date': fields.Datetime.now(),
})
- # Copy record dengan default values
new_record = super(TukarGuling, self).copy(default)
- # Re-sequence line items record baru
+ # Re-sequence lines
if new_record.line_ids:
for i, line in enumerate(new_record.line_ids):
line.sequence = (i + 1) * 10
@@ -134,40 +102,153 @@ class TukarGuling(models.Model):
def action_submit(self):
self.ensure_one()
- # cek bu out sudah diisi atau blm
+
+ if self.state != 'draft':
+ raise UserError("Submit hanya bisa dilakukan dari Draft.")
+ self.state = 'approval_sales'
+
+ def action_approve(self):
+ self.ensure_one()
+
if not self.out_num:
raise UserError("BU/Out harus diisi!")
- # cek return type
- # if not self.return_type:
- # raise UserError("Return Type harus diisi!")
+ if not self.return_type:
+ raise UserError("Return Type harus diisi!")
+
+ # Cek hak akses berdasarkan state
+ if self.state == 'approval_sales':
+ if not self.env.user.has_group('indoteknik_custom.group_sales_manager'):
+ raise UserError("Hanya Sales Manager yang boleh approve tahap ini.")
+ self.state = 'approval_logistic'
+
+ elif self.state == 'approval_logistic':
+ if not self.env.user.has_group('indoteknik_custom.group_logistic'):
+ raise UserError("Hanya Logistic Manager yang boleh approve tahap ini.")
+ self.state = 'approval_finance'
+
+ elif self.state == 'approval_finance':
+ if not self.env.user.has_group('indoteknik_custom.group_finance'):
+ raise UserError("Hanya Finance Manager yang boleh approve tahap ini.")
+ self.state = 'done'
+
+ else:
+ raise UserError("Status ini tidak bisa di-approve.")
+ def action_cancel(self):
+ self.ensure_one()
+ # if self.state == 'done':
+ # raise UserError("Tidak bisa cancel jika sudah done")
+ self.state = 'cancel'
+
+class TukarGulingPO(models.Model):
+ _name = 'tukar.guling.po'
+ _inherit = 'tukar.guling'
+ _description = 'Tukar Guling PO'
+
+ # tukar_guling_id = fields.Many2one(
+ # 'tukar.guling', required=True, ondelete='cascade', string='Tukar Guling Ref'
+ # )
+
+ return_type = fields.Selection([
+ ('tukar_guling', 'Tukar Guling'),
+ ('revisi_po', 'Revisi PO'),
+ ('debit_memo', 'Debit Memo'),
+ ], string='Return Type', required=True)
+
+ @api.constrains('return_type', 'out_num')
+ def _check_required_bu_fields(self):
+ for record in self:
+ if record.return_type in ['tukar_guling', 'revisi_po', 'debit_memo'] and not record.out_num:
+ raise ValidationError("BU/Out harus diisi!")
+
+ @api.constrains('line_ids', 'state')
+ 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', 'done') and not record.line_ids:
+ raise ValidationError("Product lines harus diisi sebelum submit atau approve!")
+
+ def _validate_product_lines(self):
+ """Helper method untuk validasi product lines"""
+ self.ensure_one()
+
+ # Check ada product lines
+ if not self.line_ids:
+ raise UserError("Belum ada product lines yang ditambahkan!")
+
+ # Check product sudah diisi
+ empty_lines = self.line_ids.filtered(lambda line: not line.product_id)
+ if empty_lines:
+ raise UserError("Ada product lines yang belum diisi productnya!")
+
+ # Check quantity > 0
+ zero_qty_lines = self.line_ids.filtered(lambda line: line.product_uom_qty <= 0)
+ if zero_qty_lines:
+ raise UserError("Quantity product tidak boleh kosong atau 0!")
+ return True
+
+ @api.model
+ def create(self, vals):
+ if not vals.get('name') or vals['name'] in ('New', False):
+ vals['name'] = self.env['ir.sequence'].next_by_code('tukar.guling.po') or 'New'
+ return super(TukarGulingPO, self).create(vals)
+ def copy(self, default=None):
+ if default is None:
+ default = {}
+
+ # Generate sequence satu-satunya di sini
+ default['name'] = self.env['ir.sequence'].next_by_code('tukar.guling.po') or 'New'
+ default['state'] = 'draft'
+ default['date'] = fields.Datetime.now()
+
+ new_record = super(TukarGulingPO, self).copy(default)
+
+ # Re-sequence lines
+ if new_record.line_ids:
+ for i, line in enumerate(new_record.line_ids):
+ line.sequence = (i + 1) * 10
+
+ return new_record
+
+ def action_draft(self):
+ """Reset to draft state"""
+ for record in self:
+ if record.state == 'cancel':
+ record.write({'state': 'draft'})
+ else:
+ raise UserError("Hanya record yang di-cancel yang bisa dikembalikan ke draft")
+
+ def action_submit(self):
+ self.ensure_one()
if self.state != 'draft':
- raise UserError("Hanya status Draft saja yang bisa di submit")
- self.state = 'waiting'
+ raise UserError("Submit hanya bisa dilakukan dari Draft.")
+ self.state = 'approval_sales'
def action_approve(self):
self.ensure_one()
- # cek bu out sudah diisi atau blm
if not self.out_num:
raise UserError("BU/Out harus diisi!")
- # cek return type
if not self.return_type:
raise UserError("Return Type harus diisi!")
- if self.state != 'waiting':
- raise UserError("Hanya status Waiting saja yang bisa di approve")
- self.state = 'done'
+ if self.state == 'approval_sales':
+ self.state = 'approval_logistic'
+ elif self.state == 'approval_logistic':
+ self.state = 'approval_finance'
+ elif self.state == 'approval_finance':
+ self.state = 'done'
+ else:
+ raise UserError("Status ini tidak bisa di-approve.")
def action_cancel(self):
self.ensure_one()
- if self.state == 'done':
- raise UserError("Tidak bisa cancel jika sudah done")
+ # if self.state == 'done':
+ # raise UserError("Tidak bisa cancel jika sudah done")
self.state = 'cancel'
-
class TukarGulingLine(models.Model):
_name = 'tukar.guling.line'
_description = 'Tukar Guling Line'