summaryrefslogtreecommitdiff
path: root/indoteknik_custom/models/tukar_guling.py
diff options
context:
space:
mode:
authorIndoteknik . <it@fixcomart.co.id>2025-08-09 14:45:48 +0700
committerIndoteknik . <it@fixcomart.co.id>2025-08-09 14:45:48 +0700
commit979ffc90fffe2f09788016376d71a940a28f8fed (patch)
treea5408296eb204a0a5066578664ed0acb13174f27 /indoteknik_custom/models/tukar_guling.py
parent33621956bdb9d807b480eda44ce7f2152f508695 (diff)
parentdf5ff0fc9bcd45c19b74288d8e5cfee018ba5bdd (diff)
Merge branch 'odoo-backup' of https://bitbucket.org/altafixco/indoteknik-addons into pum-v2
Diffstat (limited to 'indoteknik_custom/models/tukar_guling.py')
-rw-r--r--indoteknik_custom/models/tukar_guling.py348
1 files changed, 249 insertions, 99 deletions
diff --git a/indoteknik_custom/models/tukar_guling.py b/indoteknik_custom/models/tukar_guling.py
index 43bc156e..6aedb70e 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]
@@ -20,7 +21,7 @@ class TukarGuling(models.Model):
_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)
@@ -31,7 +32,7 @@ class TukarGuling(models.Model):
'tukar_guling_id',
string='Transfers'
)
- # origin_so = fields.Many2one('sale.order', string='Origin SO')
+ origin_so = fields.Many2one('sale.order', string='Origin SO', compute='_compute_origin_so')
name = fields.Char('Number', required=True, copy=False, readonly=True, default='New')
date = fields.Datetime('Date', default=fields.Datetime.now, required=True)
operations = fields.Many2one(
@@ -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)
@@ -72,6 +74,47 @@ class TukarGuling(models.Model):
date_sales = fields.Datetime('Approved Date Sales', tracking=3, readonly=True)
date_logistic = fields.Datetime('Approved Date Logistic', tracking=3, readonly=True)
+ val_inv_opt = fields.Selection([
+ ('tanpa_cancel', 'Tanpa Cancel Invoice'),
+ ('cancel_invoice', 'Cancel Invoice'),
+ ], tracking=3, string='Invoice Option')
+
+ is_has_invoice = fields.Boolean('Has Invoice?', compute='_compute_is_has_invoice', readonly=True, default=False)
+
+ invoice_id = fields.Many2many('account.move', string='Invoice Ref', readonly=True)
+
+ @api.depends('origin', 'operations')
+ def _compute_origin_so(self):
+ for rec in self:
+ rec.origin_so = False
+ origin_str = rec.origin or rec.operations.origin
+ if origin_str:
+ so = self.env['sale.order'].search([('name', '=', origin_str)], limit=1)
+ rec.origin_so = so.id if so else False
+
+ @api.depends('origin')
+ def _compute_is_has_invoice(self):
+ for rec in self:
+ invoices = self.env['account.move'].search([
+ ('invoice_origin', 'ilike', rec.origin),
+ ('move_type', '=', 'out_invoice'), # hanya invoice
+ ('state', 'not in', ['draft', 'cancel'])
+ ])
+ if invoices:
+ rec.is_has_invoice = True
+ rec.invoice_id = invoices
+ else:
+ rec.is_has_invoice = False
+
+ def set_opt(self):
+ if not self.val_inv_opt and self.is_has_invoice == True:
+ raise UserError("Kalau sudah ada invoice Return Invoice Option harus diisi!")
+ for rec in self:
+ if rec.val_inv_opt == 'cancel_invoice' and self.is_has_invoice == True:
+ raise UserError("Tidak bisa mengubah Return karena sudah ada invoice dan belum di cancel.")
+ elif rec.val_inv_opt == 'tanpa_cancel' and self.is_has_invoice == True:
+ continue
+
# @api.onchange('operations')
# def get_partner_id(self):
# if self.operations and self.operations.partner_id and self.operations.partner_id.name:
@@ -98,7 +141,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:
@@ -110,8 +153,6 @@ class TukarGuling(models.Model):
if self.line_ids and from_return_picking:
# Hanya update origin, jangan ubah lines
- if self.operations.origin:
- self.origin = self.operations.origin
_logger.info("📌 Menggunakan product lines dari return wizard, tidak populate ulang.")
# 🚀 Tapi tetap populate mapping koli jika BU/OUT
@@ -143,6 +184,7 @@ class TukarGuling(models.Model):
# Set origin dari operations
if self.operations.origin:
self.origin = self.operations.origin
+ self.origin_so = self.operations.group_id.id
# Auto-populate lines dari move_ids operations
lines_data = []
@@ -217,7 +259,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 +298,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,36 +322,38 @@ 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
+
+ # def _check_invoice_on_revisi_so(self):
+ # for record in self:
+ # if record.return_type == 'revisi_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
+ # )
- @api.constrains('return_type', 'operations')
- def _check_invoice_on_revisi_so(self):
- for record in self:
- if record.return_type == 'revisi_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
- )
@api.model
def create(self, vals):
- # Generate sequence number
if not vals.get('name') or vals['name'] == 'New':
vals['name'] = self.env['ir.sequence'].next_by_code('tukar.guling')
- # Auto-fill origin from operations
- if not vals.get('origin') and vals.get('operations'):
+ if vals.get('operations'):
picking = self.env['stock.picking'].browse(vals['operations'])
if picking.origin:
vals['origin'] = picking.origin
+ # Find matching SO
+ so = self.env['sale.order'].search([('name', '=', picking.origin)], limit=1)
+ if so:
+ vals['origin_so'] = so.id
if picking.partner_id:
vals['partner_id'] = picking.partner_id.id
@@ -318,6 +361,10 @@ class TukarGuling(models.Model):
res.message_post(body=_("CCM Created By %s") % self.env.user.name)
return res
+ res = super(TukarGuling, self).create(vals)
+ res.message_post(body=_("CCM Created By %s") % self.env.user.name)
+ return res
+
def copy(self, default=None):
if default is None:
default = {}
@@ -345,9 +392,9 @@ 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()
+ # self._check_invoice_on_revisi_so()
operasi = self.operations.picking_type_id.id
tipe = self.return_type
pp = vals.get('return_type', tipe)
@@ -376,24 +423,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,40 +490,100 @@ 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:
- mapping_lines = self.mapping_koli_ids.filtered(lambda x: x.product_id == line.product_id)
- total_qty = sum(l.qty_return for l in mapping_lines)
- if total_qty != line.product_uom_qty:
- raise UserError(
- _("Qty di Koli tidak sesuai dengan qty retur untuk produk %s") % line.product_id.display_name)
-
- self._check_invoice_on_revisi_so()
+ # Cek apakah ada BU/PICK di origin
+ origin = self.operations.origin
+ has_bu_pick = self.env['stock.picking'].search_count([
+ ('origin', '=', origin),
+ ('picking_type_id', '=', 30),
+ ('state', '!=', 'cancel')
+ ]) > 0
+
+ if has_bu_pick:
+ for line in self.line_ids:
+ mapping_lines = self.mapping_koli_ids.filtered(lambda x: x.product_id == line.product_id)
+ total_qty = sum(l.qty_return for l in mapping_lines)
+ if total_qty != line.product_uom_qty:
+ 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._validate_product_lines()
if self.state != 'draft':
raise UserError("Submit hanya bisa dilakukan dari Draft.")
self.state = 'approval_sales'
+ def update_doc_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()
- self._check_invoice_on_revisi_so()
+ # self._check_invoice_on_revisi_so()
self._check_not_allow_tukar_guling_on_bu_pick()
operasi = self.operations.picking_type_id.id
tipe = self.return_type
if self.operations.picking_type_id.id == 29:
- for line in self.line_ids:
- mapping_lines = self.mapping_koli_ids.filtered(lambda x: x.product_id == line.product_id)
- total_qty = sum(l.qty_return for l in mapping_lines)
- if total_qty != line.product_uom_qty:
- raise UserError(
- _("Qty di Koli tidak sesuai dengan qty retur untuk produk %s") % line.product_id.display_name)
+ # Cek apakah ada BU/PICK di origin
+ origin = self.operations.origin
+ has_bu_pick = self.env['stock.picking'].search_count([
+ ('origin', '=', origin),
+ ('picking_type_id', '=', 30),
+ ('state', '!=', 'cancel')
+ ]) > 0
+
+ if has_bu_pick:
+ for line in self.line_ids:
+ mapping_lines = self.mapping_koli_ids.filtered(lambda x: x.product_id == line.product_id)
+ total_qty = sum(l.qty_return for l in mapping_lines)
+ if total_qty != line.product_uom_qty:
+ raise UserError(
+ _("Qty di Koli tidak sesuai dengan qty retur untuk produk %s") % line.product_id.display_name
+ )
if operasi == 30 and self.operations.linked_manual_bu_out.state == 'done':
raise UserError("❌ Tidak bisa retur BU/PICK karena BU/OUT sudah done")
@@ -495,13 +611,15 @@ 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.set_opt()
rec.state = 'approval_logistic'
rec.date_finance = now
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
@@ -533,6 +651,23 @@ class TukarGuling(models.Model):
def _create_pickings(self):
_logger.info("🛠 Starting _create_pickings()")
+
+ def _force_locations(picking, from_loc, to_loc):
+ picking.write({
+ 'location_id': from_loc,
+ 'location_dest_id': to_loc,
+ })
+ for move in picking.move_lines:
+ move.write({
+ 'location_id': from_loc,
+ 'location_dest_id': to_loc,
+ })
+ for move_line in move.move_line_ids:
+ move_line.write({
+ 'location_id': from_loc,
+ 'location_dest_id': to_loc,
+ })
+
for record in self:
if not record.operations:
raise UserError("BU/OUT dari field operations tidak ditemukan.")
@@ -555,36 +690,53 @@ class TukarGuling(models.Model):
### ======== SRT dari BU/OUT =========
srt_return_lines = []
- 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)
- if not move:
- raise UserError(f"Move BU/OUT tidak ditemukan untuk produk {prod.display_name}")
- srt_return_lines.append((0, 0, {
- 'product_id': prod.id,
- 'quantity': qty_total,
- 'move_id': move.id,
- }))
- _logger.info(f"📟 SRT line: {prod.display_name} | qty={qty_total}")
+ if mapping_koli:
+ 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)
+ if not move:
+ raise UserError(f"Move BU/OUT tidak ditemukan untuk produk {prod.display_name}")
+ srt_return_lines.append((0, 0, {
+ 'product_id': prod.id,
+ 'quantity': qty_total,
+ 'move_id': move.id,
+ }))
+ _logger.info(f"📟 SRT line: {prod.display_name} | qty={qty_total}")
+
+ elif not mapping_koli:
+ for line in record.line_ids:
+ move = bu_out.move_lines.filtered(lambda m: m.product_id == line.product_id)
+ if not move:
+ raise UserError(f"Move BU/OUT tidak ditemukan untuk produk {line.product_id.display_name}")
+ srt_return_lines.append((0, 0, {
+ 'product_id': line.product_id.id,
+ 'quantity': line.product_uom_qty,
+ 'move_id': move.id,
+ }))
+ _logger.info(
+ f"📟 SRT line (fallback line_ids): {line.product_id.display_name} | qty={line.product_uom_qty}")
srt_picking = None
if srt_return_lines:
+ # Tentukan tujuan lokasi berdasarkan ada/tidaknya mapping_koli
+ dest_location_id = BU_OUTPUT_LOCATION_ID if mapping_koli else BU_STOCK_LOCATION_ID
+
srt_wizard = self.env['stock.return.picking'].with_context({
'active_id': bu_out.id,
'default_location_id': PARTNER_LOCATION_ID,
- 'default_location_dest_id': BU_OUTPUT_LOCATION_ID,
+ 'default_location_dest_id': dest_location_id,
'from_ui': False,
}).create({
'picking_id': bu_out.id,
'location_id': PARTNER_LOCATION_ID,
- 'original_location_id': BU_OUTPUT_LOCATION_ID,
'product_return_moves': srt_return_lines
})
+
srt_vals = srt_wizard.create_returns()
srt_picking = self.env['stock.picking'].browse(srt_vals['res_id'])
+ _force_locations(srt_picking, PARTNER_LOCATION_ID, dest_location_id)
+
srt_picking.write({
- 'location_id': PARTNER_LOCATION_ID,
- 'location_dest_id': BU_OUTPUT_LOCATION_ID,
'group_id': bu_out.group_id.id,
'tukar_guling_id': record.id,
'sale_order': record.origin
@@ -597,12 +749,11 @@ 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')
for pick in picks_to_return:
ort_return_lines = []
if is_retur_from_bu_pick:
- # Ambil dari tukar.guling.line
for line in record.line_ids:
move = pick.move_lines.filtered(lambda m: m.product_id == line.product_id)
if not move:
@@ -613,9 +764,9 @@ 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):
move = pick.move_lines.filtered(lambda m: m.product_id == mk.product_id)
if not move:
@@ -626,7 +777,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({
@@ -637,27 +789,27 @@ class TukarGuling(models.Model):
}).create({
'picking_id': pick.id,
'location_id': BU_OUTPUT_LOCATION_ID,
- 'original_location_id': BU_STOCK_LOCATION_ID,
'product_return_moves': ort_return_lines
})
+
ort_vals = ort_wizard.create_returns()
ort_picking = self.env['stock.picking'].browse(ort_vals['res_id'])
+ _force_locations(ort_picking, BU_OUTPUT_LOCATION_ID, BU_STOCK_LOCATION_ID)
+
ort_picking.write({
- 'location_id': BU_OUTPUT_LOCATION_ID,
- 'location_dest_id': BU_STOCK_LOCATION_ID,
'group_id': bu_out.group_id.id,
'tukar_guling_id': record.id,
'sale_order': record.origin
})
+
created_returns.append(ort_picking)
ort_pickings.append(ort_picking)
_logger.info(f"✅ ORT created: {ort_picking.name}")
record.message_post(
body=f"📦 <b>{ort_picking.name}</b> created by <b>{self.env.user.name}</b> (state: <b>{ort_picking.state}</b>)")
- ### ======== Tukar Guling: BU/OUT dan BU/PICK baru ========
+ ### ======== BU/PICK & BU/OUT Baru dari SRT/ORT ========
if record.return_type == 'tukar_guling':
-
# BU/PICK Baru dari ORT
for ort_p in ort_pickings:
return_lines = []
@@ -683,19 +835,18 @@ class TukarGuling(models.Model):
}).create({
'picking_id': ort_p.id,
'location_id': BU_STOCK_LOCATION_ID,
- 'original_location_id': BU_OUTPUT_LOCATION_ID,
'product_return_moves': return_lines
})
bu_pick_vals = bu_pick_wizard.create_returns()
new_pick = self.env['stock.picking'].browse(bu_pick_vals['res_id'])
+ _force_locations(new_pick, BU_STOCK_LOCATION_ID, BU_OUTPUT_LOCATION_ID)
+
new_pick.write({
- 'location_id': BU_STOCK_LOCATION_ID,
- 'location_dest_id': BU_OUTPUT_LOCATION_ID,
'group_id': bu_out.group_id.id,
'tukar_guling_id': record.id,
'sale_order': record.origin
})
- new_pick.action_assign() # Penting agar bisa trigger check koli
+ new_pick.action_assign()
new_pick.action_confirm()
created_returns.append(new_pick)
_logger.info(f"✅ BU/PICK Baru dari ORT created: {new_pick.name}")
@@ -723,14 +874,13 @@ class TukarGuling(models.Model):
}).create({
'picking_id': srt_picking.id,
'location_id': BU_OUTPUT_LOCATION_ID,
- 'original_location_id': PARTNER_LOCATION_ID,
'product_return_moves': return_lines
})
bu_out_vals = bu_out_wizard.create_returns()
new_out = self.env['stock.picking'].browse(bu_out_vals['res_id'])
+ _force_locations(new_out, BU_OUTPUT_LOCATION_ID, PARTNER_LOCATION_ID)
+
new_out.write({
- 'location_id': BU_OUTPUT_LOCATION_ID,
- 'location_dest_id': PARTNER_LOCATION_ID,
'group_id': bu_out.group_id.id,
'tukar_guling_id': record.id,
'sale_order': record.origin
@@ -808,18 +958,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 +979,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 +990,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()