You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

174 lines
7.5 KiB

# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import api, fields, models, _
class SaleOrder(models.Model):
""" Extend the base Sale Order model to add custom fields and behaviors
for Sale Order Payment Status. """
_inherit = "sale.order"
_description = 'Sale order'
payment_status = fields.Char(string="Payment Status",
compute="_compute_payment_status",
help="Field to check the payment status of the"
" sale order")
payment_details = fields.Binary(string="Payment Details",
compute="_compute_payment_details",
help="Shows the payment done details "
"including date and amount")
amount_due = fields.Float(string="Amount Due",
compute='_compute_amount_due',
help="Shows the amount that in due for the "
"corresponding sale order")
invoice_state = fields.Char(string="Invoice State",
compute="_compute_invoice_state",
help="Field to check the invoice state of "
"sale order")
@api.depends('invoice_ids')
def _compute_payment_status(self):
""" The function will compute the payment status of the sale order, if
an invoice is created for the corresponding sale order.Payment status
will be either in paid,not paid,partially paid, reversed etc. """
for order in self:
order.payment_status = 'No invoice'
payment_states = order.invoice_ids.mapped('payment_state')
status_length = len(payment_states)
if 'partial' in payment_states:
order.payment_status = 'Partially Paid'
elif 'not_paid' in payment_states and any(
(True for x in ['paid', 'in_payment', 'partial'] if
x in payment_states)):
order.payment_status = 'Partially Paid'
elif 'not_paid' in payment_states and status_length == \
payment_states.count('not_paid'):
order.payment_status = 'Not Paid'
elif 'paid' in payment_states and status_length == \
payment_states.count('paid') and order.amount_due == 0:
order.payment_status = 'Paid'
elif 'paid' in payment_states and status_length == \
payment_states.count('paid') and order.amount_due != 0:
order.payment_status = 'Partially Paid'
elif 'in_payment' in payment_states and status_length == \
payment_states.count('in_payment'):
order.payment_status = 'In Payment'
elif 'reversed' in payment_states and status_length == \
payment_states.count('reversed'):
order.payment_status = 'Reversed'
else:
order.payment_status = 'No invoice'
@api.depends('invoice_ids')
def _compute_invoice_state(self):
""" The function will compute the state of the invoice , Once an invoice
is existing in a sale order. """
for rec in self:
rec.invoice_state = 'No invoice'
for order in rec.invoice_ids:
if order.state == 'posted':
rec.invoice_state = 'posted'
elif order.state != 'posted':
rec.invoice_state = 'draft'
else:
rec.invoice_state = 'No invoice'
@api.depends('invoice_ids')
def _compute_amount_due(self):
"""The function is used to compute the amount due from the invoice and
if payment is registered."""
for rec in self:
amount_due = 0
for order in rec.invoice_ids:
amount_due = amount_due + (order.amount_total -
order.amount_residual)
rec.amount_due = rec.amount_total - amount_due
def action_open_business_doc(self):
""" This method is intended to be used in the context of an
account.move record.
It retrieves the associated payment record and opens it in a new window.
:return: A dictionary describing the action to be performed.
:rtype: dict """
name = _("Journal Entry")
move = self.env['account.move'].browse(self.id)
res_model = 'account.payment'
res_id = move.payment_id.id
return {
'name': name,
'type': 'ir.actions.act_window',
'view_mode': 'form',
'views': [(False, 'form')],
'res_model': res_model,
'res_id': res_id,
'target': 'current',
}
def js_remove_outstanding_partial(self, partial_id):
""" Called by the 'payment' widget to remove a reconciled entry to the
present invoice.
:param partial_id: The id of an existing partial reconciled with the
current invoice.
"""
self.ensure_one()
partial = self.env['account.partial.reconcile'].browse(partial_id)
return partial.unlink()
@api.depends('invoice_ids')
def _compute_payment_details(self):
""" Compute the payment details from invoices and added into the sale
order form view. """
for rec in self:
payment = []
rec.payment_details = False
if rec.invoice_ids:
for line in rec.invoice_ids:
if line.invoice_payments_widget:
for pay in line.invoice_payments_widget['content']:
payment.append(pay)
for line in rec.invoice_ids:
if line.invoice_payments_widget:
payment_line = line.invoice_payments_widget
payment_line['content'] = payment
rec.payment_details = payment_line
break
rec.payment_details = False
def action_register_payment(self):
""" Open the account.payment.register wizard to pay the selected journal
entries.
:return: An action opening the account.payment.register wizard.
"""
self.ensure_one()
return {
'name': _('Register Payment'),
'res_model': 'account.payment.register',
'view_mode': 'form',
'context': {
'active_model': 'account.move',
'active_ids': self.invoice_ids.ids,
},
'target': 'new',
'type': 'ir.actions.act_window',
}