Skip to content

Commit

Permalink
BAH-4140 | Added. Stock return and updation process has be… (#190)
Browse files Browse the repository at this point in the history
* [Karthi] | BAH-4140 | Added. Stock return and updation process has been added for customer return form confirm stage

* [Karthi] | BAH-4140 | Added. Return stock issue fixes and credit note has been moved

* [Karthi] | BAH-4140 | Added. Credit note form discount field has been added

* [Karthi] | BAH-4140 | Added. Default Return Location has been added
  • Loading branch information
karthikeyansp91 authored Dec 18, 2024
1 parent b01a024 commit 2c5f05c
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 5 deletions.
145 changes: 141 additions & 4 deletions bahmni_customer_return/models/bahmni_customer_return.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,20 @@ class BahmniCustomerReturn(models.Model):

name = fields.Char(string="Return No")
entry_date = fields.Datetime('Entry Date',default=fields.Datetime.now)
location_id = fields.Many2one('stock.location', 'Return Location',domain=[('active', '=', True),('usage', '=', 'internal')])
location_id = fields.Many2one('stock.location', 'Return Location',
default=lambda self: self.env['stock.picking.type'].search([('code', '=', 'incoming'),('sequence_code', '=', 'IN'),('barcode', '=', 'WH-RETURNS')], limit=1).default_location_dest_id.id,
domain=[('active', '=', True),('usage', '=', 'internal')])
customer_id = fields.Many2one('res.partner', 'Customer',domain=[('active', '=', True),('customer_rank', '>', 0)])

status = fields.Selection(selection=CUSTOM_STATUS, string="Status", copy=False, default="draft", readonly=True, store=True, tracking=True)
remarks = fields.Text(string="Remarks", copy=False)
company_id = fields.Many2one('res.company', copy=False, default=lambda self: self.env.company, ondelete='restrict', readonly=True, required=True)
currency_id = fields.Many2one('res.currency', string="Currency", copy=False, default=lambda self: self.env.company.currency_id.id, ondelete='restrict', readonly=True, tracking=True)

tot_amt = fields.Float(string="Return Amount", store=True, compute='_compute_all_line')
product_ids = fields.Many2many('product.product','customer_returns_products','return_id','product_id','Products',domain=[('active', '=', True),('type','=','product')])
tot_amt = fields.Float(string="Total Amount", store=True, compute='_compute_all_line')
discount_value = fields.Float(string="Dicount Amount", store=True, compute='_compute_all_line')
return_amt = fields.Float(string="Return Amount", store=True, compute='_compute_all_line')
product_ids = fields.Many2many('product.product','customer_returns_products','return_id','product_id','Products',domain=[('active', '=', True)])


active = fields.Boolean(string="Visible", default=True)
Expand Down Expand Up @@ -108,7 +112,16 @@ def onchange_product_ids(self):
@api.depends('line_ids')
def _compute_all_line(self):
for data in self:
data.tot_amt = sum(line.sub_total for line in data.line_ids)
cumulative_discount_value = 0
for line in self.line_ids:
total_sale_value_with_tax = line.sale_order_id.amount_untaxed + line.sale_order_id.amount_tax
applied_discount_percentage = (line.sale_order_id.discount / total_sale_value_with_tax) * 100
line_discount_value = (line.sub_total * applied_discount_percentage) / 100
cumulative_discount_value += line_discount_value

data.discount_value = cumulative_discount_value
data.tot_amt = sum(line.sub_total for line in data.line_ids)
data.return_amt = (sum(line.sub_total for line in data.line_ids) - cumulative_discount_value )


def display_warnings(self, warning_msg, kw):
Expand Down Expand Up @@ -144,9 +157,133 @@ def validations(self, **kw):
return self.display_warnings(warning_msg, kw)


@api.model
def auto_return_stock(self):
"""Automatically create a stock return picking."""

picking_vals = {
'partner_id': self.customer_id.id, # Customer
'picking_type_id': self.env['stock.picking.type'].search([('code', '=', 'incoming'),('sequence_code', '=', 'IN'),('barcode', '=', 'WH-RETURNS')], limit=1).id,
'location_id': self.env['stock.location'].search([('usage', '=', 'customer')], limit=1).id,
'location_dest_id': self.location_id.id,
'move_type': 'direct',
'scheduled_date': time.strftime(TIME_FORMAT),
}

return_picking = self.env['stock.picking'].create(picking_vals)

for order in self.line_ids:

# Create a stock.move entry
move = self.env['stock.move'].create({
'name': order.product_id.name,
'product_id': order.product_id.id,
'product_uom_qty': order.qty,
'product_uom': order.sale_order_line_id.product_uom.id,
'picking_id': return_picking.id,
'location_id': return_picking.location_id.id,
'location_dest_id': return_picking.location_dest_id.id,
})

# Get the associated outgoing delivery picking
picking = order.sale_order_id.picking_ids.filtered(
lambda p: p.state == 'done' and p.picking_type_id.code == 'outgoing'
)
if not picking:
raise UserError("No completed delivery order found for this sale order.")

# Find the move line matching the given lot
if order.product_id.detailed_type =='product' and order.product_id.tracking == 'lot':
move_line = picking.move_line_ids.filtered(lambda ml: ml.lot_id.id == order.lot_id.id)
if not move_line:
raise UserError("The specified lot is not found in the delivery order.")
return_lot_id = order.lot_id.id
else:
return_lot_id = False

# Create a stock.move.line entry
move_line = self.env['stock.move.line'].create({
'move_id': move.id,
'picking_id': return_picking.id,
'product_id': order.product_id.id,
'product_uom_id': order.sale_order_line_id.product_uom.id,
'qty_done': order.qty,
'location_id': return_picking.location_id.id,
'location_dest_id': return_picking.location_dest_id.id,
'lot_id': return_lot_id,
})

##validate picking
return_picking.with_context(validation_confirmed=True).button_validate()


@api.model
def create_partial_credit_note(self):

# Prepare line items for the credit note
line_items = []
cumulative_discount_value = 0.00
for line in self.line_ids:
invoice = line.sale_order_id.invoice_ids.filtered(lambda inv: inv.state == 'posted' and inv.move_type == 'out_invoice')

if not invoice:
raise ValueError(_("No valid invoice found for the selected Sale Order."))

line_items.append((0, 0, {
'product_id': line.sale_order_line_id.product_id.id,
'name': line.sale_order_line_id.product_id.display_name or 'Product',
'quantity': line.qty,
'price_unit': line.sale_order_line_id.price_unit,
'account_id': line.sale_order_line_id.product_id.categ_id.property_account_income_categ_id.id or self.env['ir.property']._get('property_account_income_categ_id', 'product.category').id,
}))
if self.discount_value > 0:
line_items.append((0, 0, {
'product_id': self.env['product.product'].search([('default_code', '=', 'DISC')], limit=1).id,
'name': self.env['product.product'].search([('default_code', '=', 'DISC')], limit=1).display_name or 'Product',
'quantity': 1,
'price_unit': -abs(self.discount_value),
'account_id': self.env['product.product'].search([('default_code', '=', 'DISC')], limit=1).categ_id.property_account_income_categ_id.id or self.env['ir.property']._get('property_account_income_categ_id', 'product.category').id,
}))

# Create the credit note
credit_note = self.env['account.move'].create({
'move_type': 'out_refund',
'partner_id': self.customer_id.id,
'invoice_date': fields.Date.today(),
'ref': self.name,
'invoice_line_ids': line_items,
})

# Post the credit note
credit_note.action_post()

def entry_confirm(self):
if self.status in ('draft'):
self.validations()

for record in self.line_ids:
### Return Entry Process Start here
# Search for existing return lines for the same sale order line
return_lines = self.env['bahmni.customer.return.line'].search([
('sale_order_line_id', '=', record.sale_order_line_id.id)])

# Calculate the total return quantity for this sale order line
total_return_qty = sum(line.qty for line in return_lines)

# Minus the current record's quantity to the total qty
already_done_return_qty = total_return_qty - record.qty

# Validation: check if total return quantity exceeds the sale order quantity
if total_return_qty > record.sale_order_line_id.product_uom_qty:
raise UserError(f"Sale Order Ref {record.sale_order_id.name} - Already Return quantity {already_done_return_qty} for the product {record.sale_order_line_id.product_id.name} "
f"cannot exceed the total order quantity ({record.sale_order_line_id.product_uom_qty}).")
self.auto_return_stock()

### Return Entry Process End

### Credit Note Entry Process Start here
self.create_partial_credit_note()

self.name = self.env['ir.sequence'].next_by_code('bahmni.customer.return.sequence') or 'New'
self.write({'status': 'confirm',
'confirm_user_id': self.env.user.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@

<br></br>
<group class="oe_subtotal_footer oe_right">
<field name="tot_amt" widget='monetary' readonly = "1" force_save="1" string="Total Amount"
<field name="tot_amt" widget='monetary' readonly = "1" force_save="1"
options="{'currency_field': 'currency_id'}"/>
<field name="discount_value" widget='monetary' readonly = "1" force_save="1"
options="{'currency_field': 'currency_id'}"/>
<field name="return_amt" widget='monetary' readonly = "1" force_save="1"
options="{'currency_field': 'currency_id'}"/>
</group>

Expand Down

0 comments on commit 2c5f05c

Please sign in to comment.