summaryrefslogtreecommitdiff
path: root/indoteknik_custom/models
diff options
context:
space:
mode:
authorMiqdad <ahmadmiqdad27@gmail.com>2025-06-13 17:19:28 +0700
committerMiqdad <ahmadmiqdad27@gmail.com>2025-06-13 17:19:28 +0700
commitd2c05ac97f195e196605d91088d6f76d9312e528 (patch)
tree6968bce8655a77298efaf36f84169ac5bf9b09e3 /indoteknik_custom/models
parent860abd78b0474279f851378f0b6507fe71fd76be (diff)
<miqdad> match with meet
Diffstat (limited to 'indoteknik_custom/models')
-rw-r--r--indoteknik_custom/models/tukar_guling.py141
1 files changed, 136 insertions, 5 deletions
diff --git a/indoteknik_custom/models/tukar_guling.py b/indoteknik_custom/models/tukar_guling.py
index ca246c7f..e214e268 100644
--- a/indoteknik_custom/models/tukar_guling.py
+++ b/indoteknik_custom/models/tukar_guling.py
@@ -8,14 +8,145 @@ class TukarGuling(models.Model):
_order = 'date desc, id desc'
_rec_name = 'name'
- # Hanya 2 field seperti yang Anda inginkan
- name = fields.Char('Reference', required=True, copy=False, readonly=True, default='New')
+ name = fields.Char('Number', required=True, copy=False, readonly=True, default='New')
date = fields.Datetime('Date', default=fields.Datetime.now, required=True)
+ out_num = fields.Many2one('stock.picking', 'Nomor BU/Out', required=True,
+ domain=[('picking_type_id.code', '=', 'outgoing')])
+ ba_num = fields.Text('Nomor BA')
+ notes = fields.Text('Notes')
+ return_type = fields.Selection(String='Return Type', selection=[
+ ('tukar_guling', 'Tukar Guling'),
+ ('revisi_so', 'Revisi SO'),
+ ('revisi_po', 'Revisi PO'),
+ ('credit_memo', 'Credit Memo'),
+ ('debit_memo', 'Debit Memo'),
+ ('lain_lain', 'Lain-lain')])
+
+ # ✅ PERBAIKAN: Ganti 'states' dengan 'state'
+ state = fields.Selection(string='Status', selection=[
+ ('draft', 'Draft'),
+ ('waiting', 'Waiting for Approval'),
+ ('done', 'Done'),
+ ('cancel', 'Canceled')
+ ], default='draft', tracking=True, required=True)
+
+ # ✅ NEW: Line items
+ line_ids = fields.One2many('tukar.guling.line', 'tukar_guling_id', string='Product Lines')
+
+ @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:
+ 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
- # Sequence generator
@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 '0'
- return super(TukarGuling, self).create(vals_list) \ No newline at end of file
+ vals['name'] = self.env['ir.sequence'].next_by_code('tukar.guling') or 'PTG/00001'
+ return super(TukarGuling, self).create(vals_list)
+
+ def copy(self, default=None):
+ """Override copy untuk custom behavior saat duplicate"""
+ if default is None:
+ default = {}
+
+ # Reset fields penting saat duplicate
+ default.update({
+ 'name': 'New', # Akan auto-generate sequence baru
+ 'state': 'draft',
+ 'date': fields.Datetime.now(),
+ # ba_num dan out_num tidak di-reset, user bisa edit manual
+ })
+
+ # Copy record dengan default values
+ new_record = super(TukarGuling, self).copy(default)
+
+ # Re-sequence line items untuk record baru
+ 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'
+
+ def action_approve(self):
+ self.ensure_one()
+ if self.state != 'waiting':
+ raise UserError("Hanya status Waiting saja yang bisa di approve")
+ self.state = 'done'
+
+ def action_cancel(self):
+ self.ensure_one()
+ 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'
+ _order = 'sequence, id'
+
+ sequence = fields.Integer('Sequence', default=10, copy=False)
+ tukar_guling_id = fields.Many2one('tukar.guling', string='Tukar Guling', required=True, ondelete='cascade')
+ product_id = fields.Many2one('product.product', string='Product', required=True)
+ product_uom_qty = fields.Float('Quantity', digits='Product Unit of Measure', required=True, default=1.0)
+ product_uom = fields.Many2one('uom.uom', string='Unit of Measure')
+ name = fields.Text('Description')
+
+ @api.model_create_multi
+ def create(self, vals_list):
+ """Override create to auto-assign sequence"""
+ for vals in vals_list:
+ if 'sequence' not in vals or vals.get('sequence', 0) <= 0:
+ # Get max sequence untuk tukar_guling yang sama
+ tukar_guling_id = vals.get('tukar_guling_id')
+ if tukar_guling_id:
+ max_seq = self.search([
+ ('tukar_guling_id', '=', tukar_guling_id)
+ ], order='sequence desc', limit=1)
+ vals['sequence'] = (max_seq.sequence or 0) + 10
+ else:
+ vals['sequence'] = 10
+ return super(TukarGulingLine, self).create(vals_list)
+
+ @api.onchange('product_id')
+ def _onchange_product_id(self):
+ if self.product_id:
+ self.name = self.product_id.display_name
+ self.product_uom = self.product_id.uom_id \ No newline at end of file