summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorit-fixcomart <it@fixcomart.co.id>2025-08-22 11:08:08 +0700
committerit-fixcomart <it@fixcomart.co.id>2025-08-22 11:08:08 +0700
commita70798e97805e6c0befb6835abf6637dbac1dd8c (patch)
tree1d7cbcf2a0a7c78b806300b5f14b607f0182f2f3
parentbbc454fd6e13d12e9674769a555264f2c2343b5b (diff)
<hafid> ngambil bu out untuk retur
-rw-r--r--indoteknik_custom/models/refund_sale_order.py148
-rw-r--r--indoteknik_custom/views/refund_sale_order.xml9
2 files changed, 106 insertions, 51 deletions
diff --git a/indoteknik_custom/models/refund_sale_order.py b/indoteknik_custom/models/refund_sale_order.py
index 2dc72f0f..4f41a002 100644
--- a/indoteknik_custom/models/refund_sale_order.py
+++ b/indoteknik_custom/models/refund_sale_order.py
@@ -141,6 +141,7 @@ class RefundSaleOrder(models.Model):
string="Sisa Uang Masuk",
help="Sisa uang masuk yang masih bisa direfund (hanya berlaku untuk 1 SO)",
)
+ show_return_alert = fields.Boolean(compute="_compute_show_return_alert")
@api.model
def create(self, vals):
@@ -155,6 +156,8 @@ class RefundSaleOrder(models.Model):
if vals.get('name', 'New') == 'New':
vals['name'] = self.env['ir.sequence'].next_by_code('refund.sale.order') or 'New'
+
+ res = super().create(vals)
vals['created_date'] = fields.Date.context_today(self)
vals['create_uid'] = self.env.user.id
@@ -176,11 +179,11 @@ class RefundSaleOrder(models.Model):
refund_type = vals.get('refund_type')
invoice_ids_data = vals.get('invoice_ids', [])
invoice_ids = invoice_ids_data[0][2] if invoice_ids_data and invoice_ids_data[0][0] == 6 else []
- if invoice_ids and refund_type and refund_type not in ['uang', 'barang_kosong_sebagian', 'barang_kosong', 'retur_half']:
- raise UserError("Refund type Hanya Bisa Lebih Bayar, Barang Kosong Sebagian, atau Retur Sebagian jika ada invoice")
+ if invoice_ids and refund_type and refund_type not in ['uang', 'barang_kosong_sebagian', 'barang_kosong', 'retur_half', 'retur']:
+ raise UserError("Refund type Hanya Bisa Lebih Bayar, Barang Kosong Sebagian, atau Retur jika ada invoice")
- if not invoice_ids and refund_type and refund_type in ['uang', 'barang_kosong_sebagian', 'retur_half']:
- raise UserError("Refund type Lebih Bayar, Barang Kosong Sebagian, atau Retur Sebagian Hanya Bisa dipilih Jika Ada Invoice")
+ if not invoice_ids and refund_type and refund_type in ['uang', 'barang_kosong_sebagian']:
+ raise UserError("Refund type Lebih Bayar dan Barang Kosong Sebagian Hanya Bisa dipilih Jika Ada Invoice")
if refund_type in ['barang_kosong', 'barang_kosong_sebagian'] and so_ids:
sale_orders = self.env['sale.order'].browse(so_ids)
@@ -200,23 +203,9 @@ class RefundSaleOrder(models.Model):
raise UserError("❌ Tidak ada barang yang tidak Terkirim/Kosong di SO yang dipilih.")
- if not so_ids and refund_type != 'lainnya':
- raise ValidationError("Jika tidak ada Sales Order yang dipilih, maka Tipe Refund hanya boleh 'Lainnya'.")
-
- refund = refund_type in ['retur', 'retur_half']
- if refund and so_ids:
- so = self.env['sale.order'].browse(so_ids)
- pickings = self.env['stock.picking'].search([
- ('state', '=', 'done'),
- ('picking_type_id', '=', 73),
- ('sale_id', 'in', so_ids)
- ])
- if not pickings:
- raise ValidationError(f"SO {', '.join(so.mapped('name'))} tidak melakukan retur barang.")
-
- if refund_type == 'retur_half' and not invoice_ids:
- raise ValidationError(f"SO {', '.join(so.mapped('name'))} belum memiliki invoice untuk Retur Sebagian.")
-
+ if not so_ids and refund_type != 'salah_transfer':
+ raise ValidationError("Jika tidak ada Sales Order yang dipilih, maka Tipe Refund hanya boleh 'Salah Transfer'.")
+
if refund_type == 'barang_kosong_sebagian' and so_ids:
sale_orders = self.env['sale.order'].browse(so_ids)
vals['uang_masuk'] = sum(sale_orders.mapped('amount_total'))
@@ -229,8 +218,7 @@ class RefundSaleOrder(models.Model):
total_uang_muka = sum(moves.mapped('amount_total_signed'))
uang_masuk = total_uang_muka if moves else sum(self.env['sale.order'].browse(so_ids).mapped('gross_amount'))
- vals['uang_masuk'] = uang_masuk
- ongkir = vals.get('ongkir', 0.0)
+ vals['uang_masuk'] = uang_masuk
total_invoice = sum(self.env['account.move'].browse(invoice_ids).mapped('amount_total_signed')) if invoice_ids else 0.0
vals['total_invoice'] = total_invoice
@@ -320,26 +308,12 @@ class RefundSaleOrder(models.Model):
else:
invoice_ids = rec.invoice_ids.ids
- if invoice_ids and vals.get('refund_type', rec.refund_type) not in ['uang', 'barang_kosong_sebagian', 'barang_kosong', 'retur_half']:
- raise UserError("Refund type Hanya Bisa Lebih Bayar, Barang Kosong Sebagian, atau Retur Sebagian jika ada invoice")
+ if invoice_ids and vals.get('refund_type', rec.refund_type) not in ['uang', 'barang_kosong_sebagian', 'barang_kosong', 'retur_half', 'retur']:
+ raise UserError("Refund type Hanya Bisa Lebih Bayar, Barang Kosong Sebagian, atau Retur jika ada invoice")
- if not invoice_ids and vals.get('refund_type', rec.refund_type) in ['uang', 'barang_kosong_sebagian', 'retur_half']:
- raise UserError("Refund type Lebih Bayar, Barang Kosong Sebagian, atau Retur Sebagian Hanya Bisa dipilih Jika Ada Invoice")
+ if not invoice_ids and vals.get('refund_type', rec.refund_type) in ['uang', 'barang_kosong_sebagian']:
+ raise UserError("Refund type Lebih Bayar, Barang Kosong Sebagian, atau Retur Hanya Bisa dipilih Jika Ada Invoice")
- if refund_type in ['retur', 'retur_half'] and so_ids:
- so = self.env['sale.order'].browse(so_ids)
- pickings = self.env['stock.picking'].search([
- ('state', '=', 'done'),
- ('picking_type_id', '=', 73),
- ('sale_id', 'in', so_ids)
- ])
-
- if not pickings:
- raise ValidationError(f"SO {', '.join(so.mapped('name'))} tidak melakukan retur barang.")
-
- if refund_type == 'retur_half' and not invoice_ids:
- raise ValidationError(f"SO {', '.join(so.mapped('name'))} belum memiliki invoice untuk retur sebagian.")
-
if any(field in vals for field in ['uang_masuk', 'invoice_ids', 'ongkir', 'sale_order_ids', 'amount_refund']):
total_invoice = sum(self.env['account.move'].browse(invoice_ids).mapped('amount_total_signed'))
vals['total_invoice'] = total_invoice
@@ -491,19 +465,53 @@ class RefundSaleOrder(models.Model):
line_vals = []
StockPicking = self.env['stock.picking']
for so in self.sale_order_ids:
- pickings = StockPicking.search([
+ # BU/SRT
+ pickings_srt = StockPicking.search([
('state', '=', 'done'),
('picking_type_id', '=', 73),
('sale_id', 'in', so.ids)
])
-
- for picking in pickings:
- for move in picking.move_lines:
- line_vals.append((0, 0, {
- 'product_id': move.product_id.id,
- 'quantity': move.product_uom_qty,
- 'reason': '',
- }))
+ # BU/ORT
+ pickings_ort = StockPicking.search([
+ ('state', '=', 'done'),
+ ('picking_type_id', '=', 74),
+ ('sale_id', 'in', so.ids)
+ ])
+ if not pickings_ort and not pickings_srt:
+ # BU/OUT
+ product_out = StockPicking.search([
+ ('state', '=', 'done'),
+ ('picking_type_id', '=', 29),
+ ('sale_id', 'in', so.ids)
+ ])
+ for picking in product_out:
+ for move in picking.move_lines:
+ line_vals.append((0, 0, {
+ 'product_id': move.product_id.id,
+ 'product_from': picking.name,
+ 'quantity': move.product_uom_qty,
+ 'reason': '',
+ }))
+
+ has_bu_pick = any(p.picking_type_id.id == 30 for p in so.picking_ids)
+ if not has_bu_pick:
+ for picking in pickings_srt:
+ for move in picking.move_lines:
+ line_vals.append((0, 0, {
+ 'product_id': move.product_id.id,
+ 'product_from': picking.name,
+ 'quantity': move.product_uom_qty,
+ 'reason': '',
+ }))
+ else:
+ for picking in pickings_ort:
+ for move in picking.move_lines:
+ line_vals.append((0, 0, {
+ 'product_id': move.product_id.id,
+ 'product_from': picking.name,
+ 'quantity': move.product_uom_qty,
+ 'reason': '',
+ }))
self.line_ids = line_vals
@@ -598,6 +606,18 @@ class RefundSaleOrder(models.Model):
def action_ask_approval(self):
for rec in self:
+ if rec.refund_type in ['retur', 'retur_half']:
+ so = rec.sale_order_ids
+ if so:
+ retur_done = self.env['stock.picking'].search_count([
+ ('sale_id', '=', so.id),
+ ('picking_type_id', 'in', [73, 74]),
+ ('state', '=', 'done')
+ ])
+ if retur_done == 0:
+ raise ValidationError(
+ f"⚠️ SO {so.name} memiliki refund tipe Retur. Selesaikan pengajuan retur untuk melanjutkan refund"
+ )
if rec.status == 'draft':
rec.status = 'pengajuan1'
@@ -611,6 +631,19 @@ class RefundSaleOrder(models.Model):
now = datetime.now(jakarta_tz).replace(tzinfo=None)
for rec in self:
+ if rec.refund_type in ['retur', 'retur_half']:
+ so = rec.sale_order_ids
+ if so:
+ retur_done = self.env['stock.picking'].search_count([
+ ('sale_id', '=', so.id),
+ ('picking_type_id', 'in', [73, 74]),
+ ('state', '=', 'done')
+ ])
+ if retur_done == 0:
+ raise ValidationError(
+ f"⚠️ SO {so.name} memiliki refund tipe Retur. Selesaikan retur untuk melanjutkan refund"
+ )
+
user_name = self.env.user.name
if not rec.status or rec.status == 'draft':
@@ -824,6 +857,21 @@ class RefundSaleOrder(models.Model):
for rec in self:
rec.sale_order_count = len(rec.sale_order_ids)
+ def _compute_show_return_alert(self):
+ for rec in self:
+ retur_ort = self.env['stock.picking'].search([
+ ('state', '=', 'done'),
+ ('picking_type_id', '=', 74),
+ ('sale_id', 'in', rec.sale_order_ids.ids)
+ ])
+
+ retur_srt = self.env['stock.picking'].search([
+ ('state', '=', 'done'),
+ ('picking_type_id', '=', 73),
+ ('sale_id', 'in', rec.sale_order_ids.ids)
+ ])
+ rec.show_return_alert = not retur_ort and not retur_srt
+
class RefundSaleOrderLine(models.Model):
_name = 'refund.sale.order.line'
_description = 'Refund Sales Order Line'
diff --git a/indoteknik_custom/views/refund_sale_order.xml b/indoteknik_custom/views/refund_sale_order.xml
index dd47c2ab..3c60cc57 100644
--- a/indoteknik_custom/views/refund_sale_order.xml
+++ b/indoteknik_custom/views/refund_sale_order.xml
@@ -79,6 +79,13 @@
statusbar_visible="draft,pengajuan1,pengajuan2,pengajuan3,refund"
attrs="{'invisible': [('status', '=', 'reject')]}" />
</header>
+ <xpath expr="//sheet" position="inside">
+ <field name="show_return_alert" invisible="1"/>
+ <div class="alert alert-info" role="alert"
+ attrs="{'invisible': [('show_return_alert', '=', False)]}">
+ ⚠️ SO belum melakukan retur barang. Silakan buat pengajuan retur.
+ </div>
+ </xpath>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_open_journal_refund"
@@ -118,7 +125,7 @@
<field name="note_refund" attrs="{'readonly': [('is_locked', '=', True)]}"/>
</group>
<group>
- <field name="uang_masuk" readonly="1"/>
+ <field name="uang_masuk" attrs="{'readonly': [('refund_type', '!=', 'salah_transfer')]}"/>
<field name="total_invoice" readonly="1"/>
<field name="ongkir" attrs="{'readonly': [('is_locked', '=', True)]}"/>
<field name="amount_refund" attrs="{'readonly': [('is_locked', '=', True)]}"/>