[WIP] compute folio payments from invoices

This commit is contained in:
Darío Lodeiros
2022-01-16 19:13:15 +01:00
parent 6db518adc8
commit c9cd05195d
6 changed files with 114 additions and 153 deletions

View File

@@ -5,7 +5,6 @@
from . import ir_http from . import ir_http
from . import ir_config_parameter from . import ir_config_parameter
# from . import payment_return
from . import pms_board_service_room_type from . import pms_board_service_room_type
from . import pms_property from . import pms_property
from . import res_users from . import res_users

View File

@@ -4,7 +4,6 @@ import json
from odoo import _, api, fields, models from odoo import _, api, fields, models
from odoo.exceptions import UserError from odoo.exceptions import UserError
from odoo.tools import float_is_zero
class AccountMove(models.Model): class AccountMove(models.Model):
@@ -21,12 +20,6 @@ class AccountMove(models.Model):
column2="folio_ids_id", column2="folio_ids_id",
store=True, store=True,
) )
outstanding_folios_debits_widget = fields.Text(
compute="_compute_get_outstanding_folios_JSON"
)
has_folios_outstanding = fields.Boolean(
compute="_compute_get_outstanding_folios_JSON"
)
pms_property_id = fields.Many2one( pms_property_id = fields.Many2one(
string="Property", string="Property",
help="The property associated to the account move", help="The property associated to the account move",
@@ -56,75 +49,92 @@ class AccountMove(models.Model):
elif move.line_ids and move.line_ids.sale_line_ids: elif move.line_ids and move.line_ids.sale_line_ids:
move.folio_ids = move.mapped("line_ids.sale_line_ids.folio_id.id") move.folio_ids = move.mapped("line_ids.sale_line_ids.folio_id.id")
def _compute_get_outstanding_folios_JSON(self): def _compute_payments_widget_to_reconcile_info(self):
self.ensure_one() for move in self:
self.outstanding_folios_debits_widget = json.dumps(False) if not move.line_ids.folio_line_ids:
if self.from_folio: super(AccountMove, move)._compute_payments_widget_to_reconcile_info()
payment_ids = self.folio_ids.mapped("payment_ids.id") else:
if self.state == "open": move.invoice_outstanding_credits_debits_widget = json.dumps(False)
account_partner = ( move.invoice_has_outstanding = False
self.env["res.partner"]._find_accounting_partner(self.partner_id).id
if (
move.state != "posted"
or move.payment_state not in ("not_paid", "partial")
or not move.is_invoice(include_receipts=True)
):
continue
pay_term_lines = move.line_ids.filtered(
lambda line: line.account_id.user_type_id.type
in ("receivable", "payable")
) )
domain = [ domain = [
("account_id", "=", self.account_id.id), ("account_id", "in", pay_term_lines.account_id.ids),
("partner_id", "!=", account_partner), ("parent_state", "=", "posted"),
("reconciled", "=", False), ("reconciled", "=", False),
("payment_id", "in", payment_ids),
"|", "|",
"&",
("amount_residual_currency", "!=", 0.0),
("currency_id", "!=", None),
"&",
("amount_residual_currency", "=", 0.0),
"&",
("currency_id", "=", None),
("amount_residual", "!=", 0.0), ("amount_residual", "!=", 0.0),
("amount_residual_currency", "!=", 0.0),
"|",
(
"folio_ids",
"in",
move.line_ids.mapped("folio_line_ids.folio_id.id"),
),
("partner_id", "=", move.commercial_partner_id.id),
] ]
if self.type in ("out_invoice", "in_refund"):
domain.extend([("credit", ">", 0), ("debit", "=", 0)]) payments_widget_vals = {
type_payment = _("Outstanding credits in Folio")
else:
domain.extend([("credit", "=", 0), ("debit", ">", 0)])
type_payment = _("Outstanding debits")
info = {
"title": "",
"outstanding": True, "outstanding": True,
"content": [], "content": [],
"move_id": self.id, "move_id": move.id,
} }
lines = self.env["account.move.line"].search(domain)
currency_id = self.currency_id if move.is_inbound():
if len(lines) != 0: domain.append(("balance", "<", 0.0))
for line in lines: payments_widget_vals["title"] = _("Outstanding credits")
# get the outstanding residual value in inv. currency else:
if line.currency_id and line.currency_id == self.currency_id: domain.append(("balance", ">", 0.0))
amount_to_show = abs(line.amount_residual_currency) payments_widget_vals["title"] = _("Outstanding debits")
else:
amount_to_show = line.company_id.currency_id.with_context( for line in self.env["account.move.line"].search(domain):
date=line.date
).compute(abs(line.amount_residual), self.currency_id) if line.currency_id == move.currency_id:
if float_is_zero( # Same foreign currency.
amount_to_show, precision_rounding=self.currency_id.rounding amount = abs(line.amount_residual_currency)
): else:
continue # Different foreign currencies.
if line.ref: amount = move.company_currency_id._convert(
title = "{} : {}".format(line.move_id.name, line.ref) abs(line.amount_residual),
else: move.currency_id,
title = line.move_id.name move.company_id,
info["content"].append( line.date,
{
"journal_name": line.ref or line.move_id.name,
"title": title,
"amount": amount_to_show,
"currency": currency_id.symbol,
"id": line.id,
"position": currency_id.position,
"digits": [69, self.currency_id.decimal_places],
}
) )
info["title"] = type_payment
self.outstanding_folios_debits_widget = json.dumps(info) if move.currency_id.is_zero(amount):
self.has_folio_outstanding = True continue
payments_widget_vals["content"].append(
{
"journal_name": line.ref or line.move_id.name,
"amount": amount,
"currency": move.currency_id.symbol,
"id": line.id,
"move_id": line.move_id.id,
"position": move.currency_id.position,
"digits": [69, move.currency_id.decimal_places],
"payment_date": fields.Date.to_string(line.date),
}
)
if not payments_widget_vals["content"]:
continue
move.invoice_outstanding_credits_debits_widget = json.dumps(
payments_widget_vals
)
move.invoice_has_outstanding = True
def action_folio_payments(self): def action_folio_payments(self):
self.ensure_one() self.ensure_one()

View File

@@ -19,11 +19,8 @@ class AccountMoveLine(models.Model):
column2="sale_line_id", column2="sale_line_id",
) )
folio_ids = fields.Many2many( folio_ids = fields.Many2many(
related="payment_id.folio_ids",
string="Folios", string="Folios",
comodel_name="pms.folio",
relation="payment_folio_rel",
column1="move_id",
column2="folio_id",
) )
name_changed_by_user = fields.Boolean( name_changed_by_user = fields.Boolean(
string="Custom label", string="Custom label",

View File

@@ -1,6 +1,6 @@
# Copyright 2017 Dario Lodeiros # Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models from odoo import api, fields, models
class AccountPayment(models.Model): class AccountPayment(models.Model):
@@ -11,11 +11,35 @@ class AccountPayment(models.Model):
string="Folios", string="Folios",
comodel_name="pms.folio", comodel_name="pms.folio",
ondelete="cascade", ondelete="cascade",
compute="_compute_folio_ids",
store=True,
readonly=False,
relation="account_payment_folio_rel", relation="account_payment_folio_rel",
column1="payment_id", column1="payment_id",
column2="folio_id", column2="folio_id",
) )
@api.depends("reconciled_invoice_ids", "reconciled_bill_ids")
def _compute_folio_ids(self):
for rec in self:
inv_folio_ids = rec.reconciled_invoice_ids.mapped(
"line_ids.folio_line_ids.folio_id.id"
)
bill_folio_ids = rec.reconciled_bill_ids.mapped(
"line_ids.folio_line_ids.folio_id.id"
)
folio_ids = list(set(inv_folio_ids + bill_folio_ids))
if folio_ids:
rec.write({"folio_ids": [(6, 0, folio_ids)]})
elif (
not rec.reconciled_invoice_ids
and not rec.reconciled_bill_ids
and rec.folio_ids
):
rec.folio_ids = rec.folio_ids
else:
rec.folio_ids = False
def _prepare_move_line_default_vals(self, write_off_line_vals=None): def _prepare_move_line_default_vals(self, write_off_line_vals=None):
line_vals_list = super(AccountPayment, self)._prepare_move_line_default_vals( line_vals_list = super(AccountPayment, self)._prepare_move_line_default_vals(
write_off_line_vals write_off_line_vals
@@ -29,6 +53,16 @@ class AccountPayment(models.Model):
) )
return line_vals_list return line_vals_list
def _synchronize_to_moves(self, changed_fields):
super(AccountPayment, self)._synchronize_to_moves(changed_fields)
if "folio_ids" in changed_fields:
for pay in self.with_context(skip_account_move_synchronization=True):
pay.move_id.write(
{
"folio_ids": [(6, 0, pay.folio_ids.ids)],
}
)
# Business methods # Business methods
# def modify(self): # def modify(self):

View File

@@ -1,45 +0,0 @@
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import fields, models
class PaymentReturn(models.Model):
_inherit = "payment.return"
# Fields declaration
folio_id = fields.Many2one(
string="Folio", help="Folio in payment return", comodel_name="pms.folio"
)
pms_property_id = fields.Many2one(
string="Property",
help="Property with access to the element",
store=True,
readonly=True,
comodel_name="pms.property",
related="folio_id.pms_property_id",
)
company_id = fields.Many2one(
string="Company",
help="The company for Payment Return",
check_pms_properties=True,
)
def action_confirm(self):
pay = super(PaymentReturn, self).action_confirm()
if pay:
folio_ids = []
folios = self.env["pms.folio"].browse(folio_ids)
for line in self.line_ids:
payments = self.env["account.payment"].search(
[("move_line_ids", "in", line.move_line_ids.ids)]
)
folios_line = self.env["pms.folio"].browse(
payments.mapped("folio_id.id")
)
# for folio in folios_line:
# if self.id not in folio.return_ids.ids:
# folio.update({"return_ids": [(4, self.id)]})
# msg = _("Return of %s registered") % (line.amount)
# folio.message_post(subject=_("Payment Return"), body=msg)
folios += folios_line
folios.compute_amount()

View File

@@ -110,15 +110,6 @@ class PmsFolio(models.Model):
comodel_name="res.company", comodel_name="res.company",
compute="_compute_company_id", compute="_compute_company_id",
) )
move_line_ids = fields.Many2many(
string="Payments",
help="Folio payments",
readonly=True,
comodel_name="account.move.line",
relation="payment_folio_rel",
column1="folio_id",
column2="move_id",
)
analytic_account_id = fields.Many2one( analytic_account_id = fields.Many2one(
string="Analytic Account", string="Analytic Account",
help="The analytic account related to a folio.", help="The analytic account related to a folio.",
@@ -962,10 +953,9 @@ class PmsFolio(models.Model):
"amount_total", "amount_total",
"reservation_type", "reservation_type",
"state", "state",
"move_line_ids",
"move_line_ids.parent_state",
"sale_line_ids.invoice_lines", "sale_line_ids.invoice_lines",
"sale_line_ids.invoice_lines.move_id.payment_state", "sale_line_ids.invoice_lines.move_id.payment_state",
"payment_ids",
) )
def _compute_amount(self): def _compute_amount(self):
for record in self: for record in self:
@@ -986,7 +976,7 @@ class PmsFolio(models.Model):
self.env["account.move.line"] self.env["account.move.line"]
.search( .search(
[ [
("folio_ids", "in", record.id), ("move_id.folio_ids", "in", record.id),
( (
"account_id", "account_id",
"in", "in",
@@ -1202,30 +1192,6 @@ class PmsFolio(models.Model):
action["context"] = ({"default_reservation_ids": [(6, 0, reservation_ids)]},) action["context"] = ({"default_reservation_ids": [(6, 0, reservation_ids)]},)
return action return action
# def action_return_payments(self):
# self.ensure_one()
# return_move_ids = []
# acc_pay_obj = self.env["account.payment"]
# payments = acc_pay_obj.search(
# ["|", ("move_ids", "in", self.move_ids.ids), ("folio_id", "=", self.id)]
# )
# return_move_ids += self.move_ids.filtered(
# lambda invoice: invoice.type == "out_refund"
# ).mapped("payment_move_line_ids.move_id.id")
# return_lines = self.env["payment.return.line"].search(
# [("move_line_ids", "in", payments.mapped("move_line_ids.id")),]
# )
# return_move_ids += return_lines.mapped("return_id.move_id.id")
# return {
# "name": _("Returns"),
# "view_type": "form",
# "view_mode": "tree,form",
# "res_model": "account.move",
# "type": "ir.actions.act_window",
# "domain": [("id", "in", return_move_ids)],
# }
def action_checks(self): def action_checks(self):
self.ensure_one() self.ensure_one()
rooms = self.mapped("reservation_ids.id") rooms = self.mapped("reservation_ids.id")