Skip to content

Commit

Permalink
[WIP]pms: basic flow folio invoice
Browse files Browse the repository at this point in the history
  • Loading branch information
DarioLodeiros committed Oct 4, 2024
1 parent ae11a64 commit 863c1be
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 132 deletions.
240 changes: 116 additions & 124 deletions pms/models/account_move.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import itertools as it
import json

from odoo import _, api, fields, models
from odoo.exceptions import UserError, ValidationError
Expand Down Expand Up @@ -97,101 +96,101 @@ def _compute_origin_agency_id(self):
if agencies:
move.origin_agency_id = agencies[0]

def _compute_payments_widget_to_reconcile_info(self):
for move in self:
if not move.line_ids.folio_line_ids:
super(AccountMove, move)._compute_payments_widget_to_reconcile_info()
else:
move.invoice_outstanding_credits_debits_widget = json.dumps(False)
move.invoice_has_outstanding = False
# def _compute_payments_widget_to_reconcile_info(self):
# for move in self:
# if not move.line_ids.folio_line_ids:
# super(AccountMove, move)._compute_payments_widget_to_reconcile_info()
# else:
# move.invoice_outstanding_credits_debits_widget = json.dumps(False)
# move.invoice_has_outstanding = False

if (
move.state != "posted"
or move.payment_state not in ("not_paid", "partial")
or not move.is_invoice(include_receipts=True)
):
continue
# 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")
)
# pay_term_lines = move.line_ids.filtered(
# lambda line: line.account_id.account_type
# in ("asset_receivable", "payable")
# )

payments_widget_vals = {
"outstanding": True,
"content": [],
"move_id": move.id,
}
# payments_widget_vals = {
# "outstanding": True,
# "content": [],
# "move_id": move.id,
# }

if move.is_inbound():
domain = [("balance", "<", 0.0)]
payments_widget_vals["title"] = _("Outstanding credits")
else:
domain = [("balance", ">", 0.0)]
payments_widget_vals["title"] = _("Outstanding debits")
# if move.is_inbound():
# domain = [("balance", "<", 0.0)]
# payments_widget_vals["title"] = _("Outstanding credits")
# else:
# domain = [("balance", ">", 0.0)]
# payments_widget_vals["title"] = _("Outstanding debits")

domain.extend(
[
("account_id", "in", pay_term_lines.account_id.ids),
("parent_state", "=", "posted"),
("reconciled", "=", False),
"|",
("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),
]
)
# domain.extend(
# [
# ("account_id", "in", pay_term_lines.account_id.ids),
# ("parent_state", "=", "posted"),
# ("reconciled", "=", False),
# "|",
# ("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),
# ]
# )

for line in self.env["account.move.line"].search(domain):
if line.currency_id == move.currency_id:
# Same foreign currency.
amount = abs(line.amount_residual_currency)
else:
# Different foreign currencies.
amount = move.company_currency_id._convert(
abs(line.amount_residual),
move.currency_id,
move.company_id,
line.date,
)
# for line in self.env["account.move.line"].search(domain):
# if line.currency_id == move.currency_id:
# # Same foreign currency.
# amount = abs(line.amount_residual_currency)
# else:
# # Different foreign currencies.
# amount = move.company_currency_id._convert(
# abs(line.amount_residual),
# move.currency_id,
# move.company_id,
# line.date,
# )

if move.currency_id.is_zero(amount):
continue
# if move.currency_id.is_zero(amount):
# 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),
}
)
# 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
# if not payments_widget_vals["content"]:
# continue

move.invoice_outstanding_credits_debits_widget = json.dumps(
payments_widget_vals
)
move.invoice_has_outstanding = True
# move.invoice_outstanding_credits_debits_widget = json.dumps(
# payments_widget_vals
# )
# move.invoice_has_outstanding = True

def _search_default_journal(self, journal_types):
def _search_default_journal(self):
"""
Search for the default journal based on the journal type and property,
the parent method is overwritten to add the property filter if
default_pms_property_id is set in context
"""
journal = super(AccountMove, self)._search_default_journal(journal_types)
journal = super(AccountMove, self)._search_default_journal()
company_id = self._context.get("default_company_id", self.env.company.id)
company = self.env["res.company"].browse(company_id)
pms_property_id = self.env.context.get(
Expand All @@ -204,38 +203,31 @@ def _search_default_journal(self, journal_types):
if pms_property:
domain = [
("company_id", "=", pms_property.company_id.id),
("type", "in", journal_types),
("pms_property_ids", "in", pms_property.id),
]
journal = self.env["account.journal"].search(domain, limit=1)
if not journal:
domain = [
("company_id", "=", pms_property.company_id.id),
("type", "in", journal_types),
("pms_property_ids", "=", False),
]
journal = self.env["account.journal"].search(domain, limit=1)
else:
domain = [
("company_id", "=", company_id),
("type", "in", journal_types),
("pms_property_ids", "=", False),
]
journal = self.env["account.journal"].search(domain, limit=1)
if not journal:
if pms_property:
error_msg = _(
"""No journal could be found in property %(property_name)s
for any of those types: %(journal_types)s""",
"No journal could be found in property %(property_name)s",
property_name=pms_property.display_name,
journal_types=", ".join(journal_types),
)
else:
error_msg = _(
"""No journal could be found in company %(company_name)s
for any of those types: %(journal_types)s""",
"No journal could be found in company %(company_name)s",
company_name=company.display_name,
journal_types=", ".join(journal_types),
)
raise UserError(error_msg)
return journal
Expand All @@ -250,41 +242,41 @@ def _compute_suitable_journal_ids(self):
or move.pms_property_id.id in j.pms_property_ids.ids
)

def _autoreconcile_folio_payments(self):
"""
Reconcile payments with the invoice
"""
# TODO: Add setting option to enable automatic payment reconciliation
for move in self.filtered(lambda m: m.state == "posted"):
if move.is_invoice(include_receipts=True) and move.folio_ids:
to_reconcile_payments_widget_vals = json.loads(
move.invoice_outstanding_credits_debits_widget
)
if not to_reconcile_payments_widget_vals:
continue
current_amounts = {
vals["move_id"]: vals["amount"]
for vals in to_reconcile_payments_widget_vals["content"]
}
pay_term_lines = move.line_ids.filtered(
lambda line: line.account_id.user_type_id.type
in ("receivable", "payable")
)
to_propose = (
self.env["account.move"]
.browse(list(current_amounts.keys()))
.line_ids.filtered(
lambda line: line.account_id == pay_term_lines.account_id
and line.folio_ids in move.folio_ids
)
)
to_reconcile = self.match_pays_by_amount(
payments=to_propose, invoice=move
)
if to_reconcile:
(pay_term_lines + to_reconcile).reconcile()
# def _autoreconcile_folio_payments(self):
# """
# Reconcile payments with the invoice
# """
# # TODO: Add setting option to enable automatic payment reconciliation
# for move in self.filtered(lambda m: m.state == "posted"):
# if move.is_invoice(include_receipts=True) and move.folio_ids:
# to_reconcile_payments_widget_vals = json.loads(
# move.invoice_outstanding_credits_debits_widget
# )
# if not to_reconcile_payments_widget_vals:
# continue
# current_amounts = {
# vals["move_id"]: vals["amount"]
# for vals in to_reconcile_payments_widget_vals["content"]
# }
# pay_term_lines = move.line_ids.filtered(
# lambda line: line.account_id.user_type_id.type
# in ("receivable", "payable")
# )
# to_propose = (
# self.env["account.move"]
# .browse(list(current_amounts.keys()))
# .line_ids.filtered(
# lambda line: line.account_id == pay_term_lines.account_id
# and line.folio_ids in move.folio_ids
# )
# )
# to_reconcile = self.match_pays_by_amount(
# payments=to_propose, invoice=move
# )
# if to_reconcile:
# (pay_term_lines + to_reconcile).reconcile()

return True
# return True

def _post(self, soft=True):
"""
Expand All @@ -293,7 +285,7 @@ def _post(self, soft=True):
for record in self:
record._check_pms_valid_invoice(record)
res = super(AccountMove, self)._post(soft)
self._autoreconcile_folio_payments()
# self._autoreconcile_folio_payments()
return res

def match_pays_by_amount(self, payments, invoice):
Expand Down
5 changes: 3 additions & 2 deletions pms/models/folio_sale_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -1073,7 +1073,6 @@ def _prepare_invoice_line(self, qty=False, **optional_values):
else:
name = self.name
res = {
"display_type": self.display_type,
"sequence": self.sequence,
"name": name,
"product_id": self.product_id.id,
Expand All @@ -1082,11 +1081,13 @@ def _prepare_invoice_line(self, qty=False, **optional_values):
"discount": self.discount,
"price_unit": self.price_unit,
"tax_ids": [(6, 0, self.tax_ids.ids)],
"analytic_account_id": self.folio_id.analytic_account_id.id,
# "analytic_account_id": self.folio_id.analytic_account_id.id,
# "analytic_tag_ids": [(6, 0, self.analytic_tag_ids.ids)],
"folio_line_ids": [(6, 0, [self.id])],
"name_changed_by_user": False,
}
if self.display_type:
res["display_type"] = self.display_type
if optional_values:
res.update(optional_values)
if self.display_type:
Expand Down
9 changes: 3 additions & 6 deletions pms/models/pms_folio.py
Original file line number Diff line number Diff line change
Expand Up @@ -699,10 +699,6 @@ def get_invoice_vals_list(
)
invoice_lines_vals.append(invoice_down_payment_vals)

if not any(
new_line["display_type"] is False for new_line in invoice_lines_vals
):
raise self._nothing_to_invoice_error()
invoice_vals["invoice_line_ids"] = [
(0, 0, invoice_line_id) for invoice_line_id in invoice_lines_vals
]
Expand Down Expand Up @@ -2103,7 +2099,7 @@ def _prepare_invoice(self, partner_invoice_id=False):
default_company_id=self.company_id.id,
default_pms_property_id=self.pms_property_id.id,
)
._get_default_journal()
._search_default_journal()
)
if not journal:
raise UserError(
Expand Down Expand Up @@ -2136,7 +2132,8 @@ def _prepare_invoice(self, partner_invoice_id=False):
"payment_reference": self.name,
"fiscal_position_id": self.env["account.fiscal.position"]
.with_company(self.company_id.id)
.get_fiscal_position(partner_invoice_id),
._get_fiscal_position(self.env["res.partner"].browse(partner_invoice_id))
.id,
}
return invoice_vals

Expand Down

0 comments on commit 863c1be

Please sign in to comment.