mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
[WIP] compute folio payments from invoices
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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()
|
|
||||||
@@ -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")
|
||||||
|
|||||||
Reference in New Issue
Block a user