Initial commit: OCA Financial packages (186 packages)

This commit is contained in:
Ernad Husremovic 2025-08-29 15:43:04 +02:00
commit 3e0e8473fb
8757 changed files with 947473 additions and 0 deletions

View file

@ -0,0 +1,5 @@
from . import statement_common
from . import activity_statement_wizard
from . import detailed_activity_statement_wizard
from . import outstanding_statement_wizard
from . import res_config_settings

View file

@ -0,0 +1,62 @@
# Copyright 2018 ForgeFlow, S.L. (http://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models
class ActivityStatementWizard(models.TransientModel):
"""Activity Statement wizard."""
_inherit = "statement.common.wizard"
_name = "activity.statement.wizard"
_description = "Activity Statement Wizard"
@api.model
def _get_date_start(self):
return (
fields.Date.context_today(self).replace(day=1) - relativedelta(days=1)
).replace(day=1)
date_start = fields.Date(required=True, default=_get_date_start)
@api.onchange("aging_type")
def onchange_aging_type(self):
res = super().onchange_aging_type()
if self.aging_type == "months":
self.date_start = self.date_end.replace(day=1)
else:
self.date_start = self.date_end - relativedelta(months=1)
return res
def _prepare_statement(self):
res = super()._prepare_statement()
res.update(
{
"date_start": self.date_start,
"is_activity": True,
}
)
return res
def _print_report(self, report_type):
self.ensure_one()
data = self._prepare_statement()
if report_type == "xlsx":
report_name = "p_s.report_activity_statement_xlsx"
else:
report_name = "partner_statement.activity_statement"
partners = self.env["res.partner"].browse(data["partner_ids"])
return (
self.env["ir.actions.report"]
.search(
[("report_name", "=", report_name), ("report_type", "=", report_type)],
limit=1,
)
.report_action(partners, data=data)
)
def _export(self, report_type):
"""Default export is PDF."""
return self._print_report(report_type)

View file

@ -0,0 +1,41 @@
# Copyright 2018 ForgeFlow, S.L. (http://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class DetailedActivityStatementWizard(models.TransientModel):
"""Detailed Activity Statement wizard."""
_inherit = "activity.statement.wizard"
_name = "detailed.activity.statement.wizard"
_description = "Detailed Activity Statement Wizard"
show_aging_buckets = fields.Boolean(default=False)
show_balance = fields.Boolean(string="Show Balance column")
def _prepare_statement(self):
res = super()._prepare_statement()
res.update(
{
"is_detailed": True,
}
)
return res
def _print_report(self, report_type):
self.ensure_one()
data = self._prepare_statement()
if report_type == "xlsx":
report_name = "p_s.report_detailed_activity_statement_xlsx"
else:
report_name = "partner_statement.detailed_activity_statement"
partners = self.env["res.partner"].browse(data["partner_ids"])
return (
self.env["ir.actions.report"]
.search(
[("report_name", "=", report_name), ("report_type", "=", report_type)],
limit=1,
)
.report_action(partners, data=data)
)

View file

@ -0,0 +1,42 @@
# Copyright 2018 ForgeFlow, S.L. (http://www.forgeflow.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import models
class OutstandingStatementWizard(models.TransientModel):
"""Outstanding Statement wizard."""
_name = "outstanding.statement.wizard"
_inherit = "statement.common.wizard"
_description = "Outstanding Statement Wizard"
def _prepare_statement(self):
res = super()._prepare_statement()
res.update(
{
"is_outstanding": True,
}
)
return res
def _print_report(self, report_type):
self.ensure_one()
data = self._prepare_statement()
if report_type == "xlsx":
report_name = "p_s.report_outstanding_statement_xlsx"
else:
report_name = "partner_statement.outstanding_statement"
partners = self.env["res.partner"].browse(data["partner_ids"])
return (
self.env["ir.actions.report"]
.search(
[("report_name", "=", report_name), ("report_type", "=", report_type)],
limit=1,
)
.report_action(partners, data=data)
)
def _export(self, report_type):
"""Default export is PDF."""
return self._print_report(report_type)

View file

@ -0,0 +1,59 @@
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"
group_activity_statement = fields.Boolean(
"Enable OCA Activity & Detailed Activity Statements",
group="account.group_account_invoice",
implied_group="partner_statement.group_activity_statement",
)
default_aging_type = fields.Selection(
[("days", "Age by Days"), ("months", "Age by Months")],
string="Aging Method",
required=True,
default="days",
default_model="statement.common.wizard",
)
default_show_aging_buckets = fields.Boolean(
string="Show Aging Buckets", default_model="statement.common.wizard"
)
default_filter_partners_non_due = fields.Boolean(
string="Exclude partners with no due entries",
default_model="statement.common.wizard",
)
default_filter_negative_balances = fields.Boolean(
"Exclude Negative Balances", default_model="statement.common.wizard"
)
group_outstanding_statement = fields.Boolean(
"Enable OCA Outstanding Statements",
group="account.group_account_invoice",
implied_group="partner_statement.group_outstanding_statement",
)
def set_values(self):
self = self.with_context(active_test=False)
# default values fields
IrDefault = self.env["ir.default"].sudo()
for name, field in self._fields.items():
if (
name.startswith("default_")
and field.default_model == "statement.common.wizard"
):
if isinstance(self[name], models.BaseModel):
if self._fields[name].type == "many2one":
value = self[name].id
else:
value = self[name].ids
else:
value = self[name]
IrDefault.set("activity.statement.wizard", name[8:], value)
IrDefault.set("outstanding.statement.wizard", name[8:], value)
IrDefault.set("detailed.activity.statement.wizard", name[8:], value)
return super().set_values()

View file

@ -0,0 +1,122 @@
# Copyright 2018 Graeme Gellatly
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models
from odoo.osv import expression
class StatementCommon(models.AbstractModel):
_name = "statement.common.wizard"
_description = "Statement Reports Common Wizard"
name = fields.Char()
company_id = fields.Many2one(
comodel_name="res.company",
default=lambda self: self.env.company,
string="Company",
required=True,
)
date_end = fields.Date(required=True, default=fields.Date.context_today)
show_aging_buckets = fields.Boolean(default=True)
show_only_overdue = fields.Boolean(
help="Show only lines due before the selected date",
)
number_partner_ids = fields.Integer(
default=lambda self: len(self._context["active_ids"])
)
filter_partners_non_due = fields.Boolean(
string="Don't show partners with no due entries", default=True
)
filter_negative_balances = fields.Boolean("Exclude Negative Balances", default=True)
aging_type = fields.Selection(
[("days", "Age by Days"), ("months", "Age by Months")],
string="Aging Method",
default="days",
required=True,
)
account_type = fields.Selection(
[("asset_receivable", "Receivable"), ("liability_payable", "Payable")],
default="asset_receivable",
)
excluded_accounts_selector = fields.Char(
string="Accounts to exclude",
help="Select account codes to be excluded "
"with a comma-separated list of expressions like 70%.",
)
@api.model
def _get_excluded_accounts_domain(self, selector):
"""Convert an account codes selector to a domain to search accounts.
The selector is a comma-separated list of expressions like 70%.
The algorithm is the same as
AccountingExpressionProcessor._account_codes_to_domain
of `mis_builder` module.
"""
if not selector:
selector = ""
domains = []
for account_code in selector.split(","):
account_code = account_code.strip()
if "%" in account_code:
domains.append(
[
("code", "=like", account_code),
]
)
else:
domains.append(
[
("code", "=", account_code),
]
)
return expression.OR(domains)
def _get_excluded_accounts(self):
self.ensure_one()
domain = self._get_excluded_accounts_domain(self.excluded_accounts_selector)
return self.env["account.account"].search(domain)
@api.onchange("aging_type")
def onchange_aging_type(self):
if self.aging_type == "months":
self.date_end = fields.Date.context_today(self).replace(
day=1
) - relativedelta(days=1)
else:
self.date_end = fields.Date.context_today(self)
def _prepare_statement(self):
self.ensure_one()
return {
"date_end": self.date_end,
"company_id": self.company_id.id,
"partner_ids": self._context["active_ids"],
"show_aging_buckets": self.show_aging_buckets,
"show_only_overdue": self.show_only_overdue,
"filter_non_due_partners": self.filter_partners_non_due,
"account_type": self.account_type,
"aging_type": self.aging_type,
"filter_negative_balances": self.filter_negative_balances,
"excluded_accounts_ids": self._get_excluded_accounts().ids,
}
def button_export_html(self):
self.ensure_one()
report_type = "qweb-html"
return self._export(report_type)
def button_export_pdf(self):
self.ensure_one()
report_type = "qweb-pdf"
return self._export(report_type)
def button_export_xlsx(self):
self.ensure_one()
report_type = "xlsx"
return self._export(report_type)

View file

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2018 ForgeFlow, S.L. (https://www.forgeflow.com)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<!-- wizard action on res.partner -->
<record id="activity_statement_wizard_action" model="ir.actions.act_window">
<field name="name">Partner Activity Statement</field>
<field name="binding_model_id" ref="base.model_res_partner" />
<field name="res_model">activity.statement.wizard</field>
<field name="view_mode">form</field>
<field
name="groups_id"
eval="[(4, ref('partner_statement.group_activity_statement'))]"
/>
<field name="target">new</field>
</record>
<record id="outstanding_statement_wizard_action" model="ir.actions.act_window">
<field name="name">Partner Outstanding Statement</field>
<field name="binding_model_id" ref="base.model_res_partner" />
<field name="res_model">outstanding.statement.wizard</field>
<field name="view_mode">form</field>
<field
name="groups_id"
eval="[(4, ref('partner_statement.group_outstanding_statement'))]"
/>
<field name="target">new</field>
</record>
<record
id="detailed_activity_statement_wizard_action"
model="ir.actions.act_window"
>
<field name="name">Partner Detailed Activity Statement</field>
<field name="binding_model_id" ref="base.model_res_partner" />
<field name="res_model">detailed.activity.statement.wizard</field>
<field name="view_mode">form</field>
<field
name="groups_id"
eval="[(4, ref('partner_statement.group_activity_statement'))]"
/>
<field name="target">new</field>
</record>
<!-- wizard view -->
<record id="statement_common_view" model="ir.ui.view">
<field name="name">Statement Common Wizard View</field>
<field name="model">statement.common.wizard</field>
<field name="arch" type="xml">
<form name="Report Options">
<div style="text-align:justify" name="info">
<span
class="o_form_label"
>Aging details can be shown in the report, expressed in aging
buckets, so the partner can review how much is open, due or overdue.
</span>
</div>
<hr />
<group>
<group name="main_info">
<field
name="company_id"
options="{'no_create': True}"
groups="base.group_multi_company"
/>
<label for="account_type" />
<field name="account_type" nolabel="1" widget="radio" />
<field name="excluded_accounts_selector" />
</group>
<group name="aging_report">
<field name="show_only_overdue" />
<field name="show_aging_buckets" />
<field name="aging_type" />
</group>
</group>
<group>
<group name="dates">
<field name="date_end" />
</group>
<group name="multiple_partners">
<field name="number_partner_ids" readonly="1" invisible="1" />
<field
name="filter_partners_non_due"
attrs="{'invisible': [('number_partner_ids', '=', 1)]}"
/>
<field
name="filter_negative_balances"
attrs="{'invisible': [('number_partner_ids', '=', 1)]}"
/>
</group>
</group>
<footer>
<button
name="button_export_html"
string="View"
type="object"
default_focus="1"
class="oe_highlight"
/>
or
<button
name="button_export_pdf"
string="Export PDF"
type="object"
/>
or
<button
name="button_export_xlsx"
string="Export XLSX"
type="object"
/>
or
<button string="Cancel" class="oe_link" special="cancel" />
</footer>
</form>
</field>
</record>
<record id="outstanding_statement_wizard_view" model="ir.ui.view">
<field name="name">Outstanding Statement Wizard</field>
<field name="model">outstanding.statement.wizard</field>
<field name="inherit_id" ref="partner_statement.statement_common_view" />
<field name="mode">primary</field>
<field name="arch" type="xml">
<xpath expr="//div[@name='info']/span" position="before">
<span
class="o_form_label"
>The outstanding statement provides details of all partner's outstanding
receivables and payables up to a particular date. This includes all unpaid invoices, unclaimed
refunds and outstanding payments. The list is displayed in chronological order and is
split by currencies.
</span>
<br />
<br />
</xpath>
</field>
</record>
<record id="activity_statement_wizard_view" model="ir.ui.view">
<field name="name">Activity Statement Wizard</field>
<field name="model">activity.statement.wizard</field>
<field name="inherit_id" ref="partner_statement.statement_common_view" />
<field name="mode">primary</field>
<field name="arch" type="xml">
<xpath expr="//div[@name='info']/span" position="before">
<span
class="o_form_label"
>The activity statement provides details of all activity on
a partner's receivables and payables between two selected dates. This includes all invoices,
refunds and payments. Any outstanding balance dated prior to the chosen statement
period will appear as a forward balance at the top of the statement. The list is
displayed in chronological order and is split by currencies.
</span>
<br />
<br />
</xpath>
<xpath expr="//field[@name='date_end']" position="before">
<field name="date_start" />
</xpath>
</field>
</record>
<record id="detailed_activity_statement_wizard_view" model="ir.ui.view">
<field name="name">Detailed Activity Statement Wizard</field>
<field name="model">detailed.activity.statement.wizard</field>
<field name="inherit_id" ref="partner_statement.statement_common_view" />
<field name="mode">primary</field>
<field name="arch" type="xml">
<xpath expr="//div[@name='info']/span" position="before">
<span
class="o_form_label"
>The detailed activity statement is an extension of the activity statement, and intends to explain the transactions
that have happened during the period, also providing with a Prior Balance section and an Ending Balance section.
</span>
<br />
<br />
</xpath>
<xpath expr="//field[@name='date_end']" position="before">
<field name="date_start" />
</xpath>
</field>
</record>
</odoo>