summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indoteknik_custom/models/partial_delivery.py117
1 files changed, 80 insertions, 37 deletions
diff --git a/indoteknik_custom/models/partial_delivery.py b/indoteknik_custom/models/partial_delivery.py
index 1204089b..4df7da1e 100644
--- a/indoteknik_custom/models/partial_delivery.py
+++ b/indoteknik_custom/models/partial_delivery.py
@@ -42,9 +42,10 @@ class PartialDeliveryWizard(models.TransientModel):
# return res
def action_select_all(self):
+ if len(self.line_ids) == 0:
+ raise UserError(_("Tidak ada produk yang dipilih."))
for line in self.line_ids:
line.selected = True
- # return action supaya wizard gak nutup
return {
'type': 'ir.actions.act_window',
'res_model': self._name,
@@ -54,9 +55,10 @@ class PartialDeliveryWizard(models.TransientModel):
}
def action_unselect_all(self):
+ if len(self.line_ids) == 0:
+ raise UserError(_("Tidak ada produk yang dipilih."))
for line in self.line_ids:
line.selected = False
- # juga reload biar tetap di wizard
return {
'type': 'ir.actions.act_window',
'res_model': self._name,
@@ -65,21 +67,40 @@ class PartialDeliveryWizard(models.TransientModel):
'target': 'new',
}
-
-
@api.onchange('picking_id')
def _onchange_picking_id(self):
"""Generate lines whenever picking_id is changed"""
- lines = []
- if self.picking_id:
- moves = self.picking_id.move_ids_without_package.filtered(lambda m: m.reserved_availability > 0)
- for move in moves:
- lines.append((0, 0, {
- 'product_id': move.product_id.id,
- 'reserved_qty': move.reserved_availability,
- 'move_id': move.id,
- }))
- self.line_ids = lines
+ if not self.picking_id:
+ self.line_ids = [(5, 0, 0)]
+ return
+
+ if self.line_ids:
+ self.line_ids.unlink()
+
+ moves = self.picking_id.move_lines or self.picking_id.move_ids_without_package
+ moves = moves.filtered(lambda m: m.product_id and m.reserved_availability > 0)
+
+ if not moves:
+ _logger.warning(f"[PartialDeliveryWizard] Tidak ada move line di picking {self.picking_id.name}")
+ return
+
+ for move in moves:
+ reserved_qty = move.reserved_availability or 0.0
+ ordered_qty = move.sale_line_id.product_uom_qty if move.sale_line_id else 0.0
+
+ self.env['partial.delivery.wizard.line'].create({
+ 'wizard_id': self.id,
+ 'product_id': move.product_id.id,
+ 'reserved_qty': reserved_qty,
+ # 'selected_qty': reserved_qty,
+ 'move_id': move.id,
+ 'sale_line_id': move.sale_line_id.id if move.sale_line_id else False,
+ })
+
+ _logger.info(
+ f"[PartialDeliveryWizard] ✅ Created line for {move.product_id.display_name} "
+ f"(reserved={reserved_qty}, move_id={move.id})"
+ )
def action_confirm_partial_delivery(self):
@@ -92,7 +113,6 @@ class PartialDeliveryWizard(models.TransientModel):
if picking.state != "assigned":
raise UserError(_("Picking harus dalam status Ready (assigned)."))
-
lines_by_qty = self.line_ids.filtered(lambda l: l.selected_qty > 0)
lines_by_selected = self.line_ids.filtered(lambda l: l.selected and not l.selected_qty)
@@ -101,6 +121,44 @@ class PartialDeliveryWizard(models.TransientModel):
if not selected_lines:
raise UserError(_("Tidak ada produk yang dipilih atau diisi jumlahnya."))
+ # 🧠 Cek apakah semua move di DO sudah muncul di wizard dan semua dipilih
+ picking_move_ids = picking.move_ids_without_package.ids
+ wizard_move_ids = self.line_ids.mapped('move_id').ids
+
+ # Semua move DO muncul di wizard, dan semua baris dipilih
+ full_selected = (
+ set(picking_move_ids) == set(wizard_move_ids)
+ and len(selected_lines) == len(self.line_ids)
+ and all(
+ (line.selected_qty or line.reserved_qty) >= line.reserved_qty
+ for line in selected_lines
+ )
+ )
+
+ if full_selected:
+ # 💡 Gak perlu bikin picking baru, langsung ubah state_reserve
+ picking.write({'state_reserve': 'partial'})
+
+ picking.message_post(
+ body=f"<b>Full Picking Confirmed</b> via wizard partial delivery oleh {self.env.user.name} (tanpa DO baru)",
+ message_type="comment",
+ subtype_xmlid="mail.mt_note",
+ )
+
+ return {
+ "type": "ir.actions.act_window",
+ "res_model": "stock.picking",
+ "view_mode": "form",
+ "res_id": picking.id,
+ "target": "current",
+ "effect": {
+ "fadeout": "slow",
+ "message": f"✅ Semua produk dari DO ini dikirim penuh — tidak dibuat DO baru.",
+ "type": "rainbow_man",
+ },
+ }
+
+ # 🧩 Kalau bukan full selected, lanjut bikin DO baru
new_picking = StockPicking.create({
'origin': picking.origin,
'partner_id': picking.partner_id.id,
@@ -117,11 +175,9 @@ class PartialDeliveryWizard(models.TransientModel):
move = line.move_id
move._do_unreserve()
- # kalau cuma selected tanpa isi qty, otomatis set selected_qty = reserved_qty
if line.selected and not line.selected_qty:
line.selected_qty = line.reserved_qty
- # MODE 1 → Prioritas kalau ada selected_qty
if line.selected_qty > 0:
if line.selected_qty > move.product_uom_qty:
raise UserError(_(
@@ -130,7 +186,6 @@ class PartialDeliveryWizard(models.TransientModel):
if line.selected_qty < move.product_uom_qty:
qty_to_keep = move.product_uom_qty - line.selected_qty
- # split move
new_move = move.copy(default={
'product_uom_qty': line.selected_qty,
'picking_id': new_picking.id,
@@ -138,35 +193,21 @@ class PartialDeliveryWizard(models.TransientModel):
})
move.write({'product_uom_qty': qty_to_keep})
else:
- # full pindah
move.write({'picking_id': new_picking.id, 'partial': True})
-
-
- # Confirm & assign DO baru
new_picking.action_confirm()
new_picking.action_assign()
-
- # Reassign DO lama biar sisa qty ke-update
picking.action_assign()
- # --- 🔢 Rename picking baru dengan format "/(Nomor urut)" ---
existing_partials = self.env['stock.picking'].search([
('origin', '=', picking.origin),
('state_reserve', '=', 'partial'),
('id', '!=', new_picking.id),
], order='name asc')
- suffix_number = len(existing_partials)
- if suffix_number == 0:
- suffix_number = 1
- else:
- suffix_number += 1
+ suffix_number = len(existing_partials) + 1
+ new_picking.name = f"{picking.name}/{suffix_number}"
- new_name = f"{picking.name}/{suffix_number}"
- new_picking.name = new_name
-
- # --- 💬 Post message ke SO ---
if picking.origin:
sale_order = self.env['sale.order'].search([('name', '=', picking.origin)], limit=1)
if sale_order:
@@ -177,7 +218,6 @@ class PartialDeliveryWizard(models.TransientModel):
subtype_xmlid="mail.mt_note",
)
- # --- 📝 Log di DO baru ---
new_picking.message_post(
body=f"<b>Partial Picking created</b> dari {picking.name} oleh {self.env.user.name}",
message_type="comment",
@@ -197,8 +237,6 @@ class PartialDeliveryWizard(models.TransientModel):
},
}
-
-
class PartialDeliveryWizardLine(models.TransientModel):
_name = 'partial.delivery.wizard.line'
_description = 'Partial Delivery Wizard Line'
@@ -212,3 +250,8 @@ class PartialDeliveryWizardLine(models.TransientModel):
sale_line_id = fields.Many2one('sale.order.line', string="SO Line", related='move_id.sale_line_id')
ordered_qty = fields.Float(related='sale_line_id.product_uom_qty', string="Ordered Qty")
+ @api.onchange('selected')
+ def onchange_selected(self):
+ if self.selected:
+ self.selected_qty = self.reserved_qty
+