Compare commits
merge into: njeudy:12.0
njeudy:11.0
njeudy:12.0
njeudy:12.0-add-financial-risk
njeudy:12.0-backend_filter
njeudy:12.0-chg-monetary_fields
njeudy:12.0-easy_my_coop-module_category_cooperator_management
njeudy:12.0-emc-rest-connector
njeudy:12.0-emc_loan-o3-add-paid-amount
njeudy:12.0-emc_loan-o6-subscription_end_date
njeudy:12.0-fix-coop-validation
njeudy:12.0-flag-easymycoop-mail-template
njeudy:12.0-loan-improvements
njeudy:12.0-max-amount-per-share
njeudy:12.0-o4-net-interest-rate
njeudy:12.0-openupgrade
njeudy:12.0-small-changes
njeudy:12.0-touch-cooperator-type
njeudy:14.0-MIG-INITIAL
njeudy:9.0
njeudy:9.0-fix_tax_shelter_declaration_exclusion
njeudy:9.0-medor-hide_bank_and_birthdate
njeudy:9.0-tag
njeudy:9.0_remove_national_register_number
njeudy:myceliandre_usability
pull from: njeudy:12.0-loan-improvements
njeudy:11.0
njeudy:12.0
njeudy:12.0-add-financial-risk
njeudy:12.0-backend_filter
njeudy:12.0-chg-monetary_fields
njeudy:12.0-easy_my_coop-module_category_cooperator_management
njeudy:12.0-emc-rest-connector
njeudy:12.0-emc_loan-o3-add-paid-amount
njeudy:12.0-emc_loan-o6-subscription_end_date
njeudy:12.0-fix-coop-validation
njeudy:12.0-flag-easymycoop-mail-template
njeudy:12.0-loan-improvements
njeudy:12.0-max-amount-per-share
njeudy:12.0-o4-net-interest-rate
njeudy:12.0-openupgrade
njeudy:12.0-small-changes
njeudy:12.0-touch-cooperator-type
njeudy:14.0-MIG-INITIAL
njeudy:9.0
njeudy:9.0-fix_tax_shelter_declaration_exclusion
njeudy:9.0-medor-hide_bank_and_birthdate
njeudy:9.0-tag
njeudy:9.0_remove_national_register_number
njeudy:myceliandre_usability
36 Commits
12.0
...
12.0-loan-
36 changed files with 1413 additions and 188 deletions
-
15easy_my_coop_loan/__manifest__.py
-
12easy_my_coop_loan/data/loan_data.xml
-
8easy_my_coop_loan/data/mail_template_data.xml
-
33easy_my_coop_loan/models/interest_line.py
-
73easy_my_coop_loan/models/loan.py
-
148easy_my_coop_loan/models/loan_issue_line.py
-
111easy_my_coop_loan/report/loan_issue_line_report.xml
-
13easy_my_coop_loan/report/loan_report.xml
-
2easy_my_coop_loan/security/ir.model.access.csv
-
96easy_my_coop_loan/views/loan_interest_lines_view.xml
-
114easy_my_coop_loan/views/loan_line_view.xml
-
111easy_my_coop_loan/views/loan_view.xml
-
2easy_my_coop_loan_account/__init__.py
-
29easy_my_coop_loan_account/__manifest__.py
-
31easy_my_coop_loan_account/data/emc_loan_account_data.xml
-
5easy_my_coop_loan_account/models/__init__.py
-
46easy_my_coop_loan_account/models/account_fiscal_year.py
-
39easy_my_coop_loan_account/models/account_move.py
-
92easy_my_coop_loan_account/models/company.py
-
200easy_my_coop_loan_account/models/interest_line.py
-
71easy_my_coop_loan_account/models/loan_issue_line.py
-
22easy_my_coop_loan_account/views/loan_issue_line_view.xml
-
25easy_my_coop_loan_account/views/res_company_view.xml
-
1easy_my_coop_loan_account/wizard/__init__.py
-
77easy_my_coop_loan_account/wizard/end_of_year_operation.py
-
35easy_my_coop_loan_account/wizard/end_of_year_operation.xml
-
1easy_my_coop_loan_bba/__init__.py
-
21easy_my_coop_loan_bba/__manifest__.py
-
1easy_my_coop_loan_bba/models/__init__.py
-
95easy_my_coop_loan_bba/models/loan_issue_line.py
-
11easy_my_coop_loan_website/__manifest__.py
-
26easy_my_coop_loan_website/controllers/main.py
-
6easy_my_coop_website/__manifest__.py
-
9easy_my_coop_website_portal/__manifest__.py
-
6easy_my_coop_website_portal/controllers/main.py
-
14easy_my_coop_website_portal/views/easy_my_coop_website_portal_templates.xml
@ -0,0 +1,12 @@ |
|||||
|
<odoo noupdate="1"> |
||||
|
<record id="sequence_loan_issue_line" model="ir.sequence"> |
||||
|
<field name="name">Loan issue line</field> |
||||
|
<field name="code">loan.issue.line.sequence</field> |
||||
|
<field name="prefix">LOAN/%(year)s/</field> |
||||
|
<field eval="1" name="number_next"/> |
||||
|
<field eval="1" name="number_increment"/> |
||||
|
<field eval="True" name="use_date_range"/> |
||||
|
<field eval="False" name="company_id"/> |
||||
|
<field name="padding">4</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,111 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<template id="loan_issue_line_document"> |
||||
|
|
||||
|
<t t-call="web.external_layout"> |
||||
|
<t t-set="address"> |
||||
|
<address t-field="o.partner_id" |
||||
|
t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/> |
||||
|
</t> |
||||
|
<div class="page mt32"> |
||||
|
<h2> |
||||
|
<span>Reimbursement table</span> |
||||
|
</h2> |
||||
|
|
||||
|
<p name="loan_payment_date_date" class="mt16"> |
||||
|
<span>Loan payment received on</span> |
||||
|
<span t-field="o.payment_date"/> |
||||
|
</p> |
||||
|
|
||||
|
<table class="table table-sm o_main_table mt16" |
||||
|
name="invoice_line_table"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<t t-set="colspan" t-value="5"/> |
||||
|
<th class="text-left">Year</th> |
||||
|
<th class="text-right">Subscribed amount</th> |
||||
|
<th class="text-right">Accrued amount</th> |
||||
|
<th class="text-right">Gross interest</th> |
||||
|
<th class="text-right">Accrued gross interest</th> |
||||
|
<th class="text-right">Net interest</th> |
||||
|
<th class="text-right">Tax amount</th> |
||||
|
<th class="text-right">Due amount</th> |
||||
|
<th class="text-right">State</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody class="invoice_tbody"> |
||||
|
<t t-foreach="o.interest_lines" t-as="line"> |
||||
|
<tr> |
||||
|
<td class="text-left" name="name"> |
||||
|
<span t-field="line.name"/> |
||||
|
</td> |
||||
|
<td class="text-right" name="subscribed_amount"> |
||||
|
<span t-field="line.amount"/> |
||||
|
</td> |
||||
|
<td class="text-right" name="accrued_amount"> |
||||
|
<span t-field="line.accrued_amount"/> |
||||
|
</td> |
||||
|
<td class="text-right" name="interest"> |
||||
|
<span t-field="line.interest" |
||||
|
t-options='{"widget": "monetary", "display_currency": o.loan_issue_id.company_currency_id}'/> |
||||
|
</td> |
||||
|
<td class="text-right" name="accrued_interest"> |
||||
|
<span t-field="line.accrued_interest" |
||||
|
t-options='{"widget": "monetary", "display_currency": o.loan_issue_id.company_currency_id}'/> |
||||
|
</td> |
||||
|
<td class="text-right" name="net_interest"> |
||||
|
<span t-field="line.net_interest" |
||||
|
t-options='{"widget": "monetary", "display_currency": o.loan_issue_id.company_currency_id}'/> |
||||
|
</td> |
||||
|
<td class="text-right" name="taxes_amount"> |
||||
|
<span t-field="line.taxes_amount" |
||||
|
t-options='{"widget": "monetary", "display_currency": o.loan_issue_id.company_currency_id}'/> |
||||
|
</td> |
||||
|
<td class="text-right" name="due_amount"> |
||||
|
<span t-field="line.due_amount" |
||||
|
t-options='{"widget": "monetary", "display_currency": o.loan_issue_id.company_currency_id}'/> |
||||
|
</td> |
||||
|
<td class="text-right" name="due_date"> |
||||
|
<span t-field="line.due_date"/> |
||||
|
</td> |
||||
|
<td class="text-right" name="state"> |
||||
|
<span t-field="line.state"/> |
||||
|
</td> |
||||
|
</tr> |
||||
|
</t> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
|
||||
|
<div class="row mt32"> |
||||
|
<div name="board_commitee" class="col-sm-6"> |
||||
|
<p> |
||||
|
For the board of<span t-field="o.company_id.name"/>. |
||||
|
</p> |
||||
|
<p> |
||||
|
<strong> |
||||
|
<span t-field="o.company_id.board_representative"/> |
||||
|
</strong> |
||||
|
</p> |
||||
|
<img t-if="o.company_id.signature_scan" |
||||
|
t-attf-class="mt16 w-50" |
||||
|
t-attf-style="{{ 'min-width: 100px; max-width: 250px' if report_type == 'pdf' else '' }}" |
||||
|
t-att-src="'data:image/png;base64,%s' % o.company_id.signature_scan.decode()"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
</t> |
||||
|
</template> |
||||
|
|
||||
|
|
||||
|
<template id="loan_issue_line"> |
||||
|
<t t-call="web.html_container"> |
||||
|
<t t-foreach="docs" t-as="o"> |
||||
|
<t t-call="easy_my_coop_loan.loan_issue_line_document" |
||||
|
t-lang="o.partner_id.lang"/> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,13 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<report |
||||
|
id="action_loan_issue_line_report" |
||||
|
model="loan.issue.line" |
||||
|
string="Reimbursment table report" |
||||
|
report_type="qweb-pdf" |
||||
|
name="easy_my_coop_loan.loan_issue_line" |
||||
|
file="easy_my_coop_loan.loan_issue_line_report.xml" |
||||
|
multi="True" |
||||
|
menu="True" |
||||
|
/> |
||||
|
</odoo> |
@ -0,0 +1,96 @@ |
|||||
|
<odoo> |
||||
|
<record id="action_loan_interest_lines" model="ir.actions.act_window"> |
||||
|
<field name="name">Loan interest lines</field> |
||||
|
<field name="res_model">loan.interest.line</field> |
||||
|
<field name="view_type">form</field> |
||||
|
<field name="view_mode">tree,form</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="loan_interest_line_view_tree" model="ir.ui.view"> |
||||
|
<field name="name">loan.interest.line.view.tree</field> |
||||
|
<field name="model">loan.interest.line</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<tree string="Loan interest lines"> |
||||
|
<field name="issue_line" invisible="True"/> |
||||
|
<field name="name"/> |
||||
|
<field name="amount"/> |
||||
|
<field name="accrued_amount"/> |
||||
|
<field name="interest"/> |
||||
|
<field name="accrued_interest"/> |
||||
|
<field name="net_interest"/> |
||||
|
<field name="taxes_amount"/> |
||||
|
<field name="due_loan_amount"/> |
||||
|
<field name="due_amount"/> |
||||
|
<field name="due_date"/> |
||||
|
<field name="state"/> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="view_loan_interest_line_form" model="ir.ui.view"> |
||||
|
<field name="name">loan.interest.line.form</field> |
||||
|
<field name="model">loan.interest.line</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form string="Loan interest line"> |
||||
|
<header> |
||||
|
<field name="state" widget="statusbar"/> |
||||
|
</header> |
||||
|
<sheet> |
||||
|
<group> |
||||
|
<group> |
||||
|
<field name="issue_line"/> |
||||
|
<field name="name"/> |
||||
|
<field name="amount"/> |
||||
|
<field name="accrued_amount"/> |
||||
|
<field name="due_loan_amount"/> |
||||
|
<field name="due_amount"/> |
||||
|
<field name="due_date"/> |
||||
|
</group> |
||||
|
<group> |
||||
|
<field name="interest"/> |
||||
|
<field name="net_interest"/> |
||||
|
<field name="taxes_amount"/> |
||||
|
<field name="accrued_interest"/> |
||||
|
<field name="accrued_net_interest"/> |
||||
|
</group> |
||||
|
</group> |
||||
|
</sheet> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="view_loan_interest_line_filter" model="ir.ui.view"> |
||||
|
<field name="name">Loans interest lines Search</field> |
||||
|
<field name="model">loan.interest.line</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<search string="Search Loan interest lines"> |
||||
|
<field name="name"/> |
||||
|
<field name="partner_id"/> |
||||
|
<field name="loan_issue_id"/> |
||||
|
<separator/> |
||||
|
<filter string="Draft" name="state_draft" |
||||
|
domain="[('state','=','draft')]"/> |
||||
|
<filter string="Due" name="state_due" |
||||
|
domain="[('state','=','due')]"/> |
||||
|
<filter string="Requested" name="state_requested" |
||||
|
domain="[('state','=','requested')]"/> |
||||
|
<filter string="Donation" name="state_donation" |
||||
|
domain="[('state','=','donation')]"/> |
||||
|
<filter string="Paid" name="state_paid" |
||||
|
domain="[('state','=','paid')]"/> |
||||
|
<group expand="0" name="group_by" string="Group By"> |
||||
|
<filter name="loan_issue_id" string="Loan issue" |
||||
|
context="{'group_by' : 'loan_issue_id'}"/> |
||||
|
<filter name="partner_id" string="Loaner" |
||||
|
context="{'group_by' : 'partner_id'}"/> |
||||
|
<filter name="issue_line" string="Loans" |
||||
|
context="{'group_by' : 'issue_line'}"/> |
||||
|
<filter name="due_date" string="Due Date" |
||||
|
context="{'group_by': 'due_date'}"/> |
||||
|
<filter name="state" string="State" |
||||
|
context="{'group_by': 'state'}"/> |
||||
|
</group> |
||||
|
</search> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,114 @@ |
|||||
|
<odoo> |
||||
|
<record id="action_loan_issue_lines" model="ir.actions.act_window"> |
||||
|
<field name="name">Loans</field> |
||||
|
<field name="res_model">loan.issue.line</field> |
||||
|
<field name="view_type">form</field> |
||||
|
<field name="view_mode">tree,form</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="loan_issue_line_view_tree" model="ir.ui.view"> |
||||
|
<field name="name">loan_issue_line_view_tree</field> |
||||
|
<field name="model">loan.issue.line</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<tree string="Loans"> |
||||
|
<field name="name"/> |
||||
|
<field name="partner_id"/> |
||||
|
<field name="loan_issue_id"/> |
||||
|
<field name="quantity"/> |
||||
|
<field name="face_value"/> |
||||
|
<field name="amount"/> |
||||
|
<field name="date"/> |
||||
|
<field name="state"/> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="view_loan_issue_line_form" model="ir.ui.view"> |
||||
|
<field name="name">loan.issue.line.form</field> |
||||
|
<field name="model">loan.issue.line</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form string="Loan"> |
||||
|
<header> |
||||
|
<button name="action_validate" string="Validate" |
||||
|
type="object" states="draft"/> |
||||
|
<button name="action_request_payment" |
||||
|
string="Request Payment" |
||||
|
type="object" states="subscribed"/> |
||||
|
<button name="action_draft" string="Set to draft" |
||||
|
type="object" states="cancelled"/> |
||||
|
<button name="action_paid" string="Paid" |
||||
|
type="object" states="waiting"/> |
||||
|
<button name="action_cancel" string="Cancel" type="object" |
||||
|
states="draft,subscribed,waiting" |
||||
|
confirm="Are you sure you want to cancel this loan subscription ?"/> |
||||
|
<button name="action_compute_interest" string="Compute interest" |
||||
|
type="object" states="paid"/> |
||||
|
|
||||
|
<field name="state" widget="statusbar"/> |
||||
|
</header> |
||||
|
<sheet> |
||||
|
<group> |
||||
|
<group> |
||||
|
<field name="name"/> |
||||
|
<field name="partner_id"/> |
||||
|
<field name="loan_issue_id"/> |
||||
|
<field name="quantity"/> |
||||
|
<field name="face_value"/> |
||||
|
</group> |
||||
|
<group> |
||||
|
<field name="date"/> |
||||
|
<field name="payment_date"/> |
||||
|
<field name="reference"/> |
||||
|
<field name="amount"/> |
||||
|
</group> |
||||
|
</group> |
||||
|
<notebook> |
||||
|
<page name="interest_lines" string="Interest lines"> |
||||
|
<field name="interest_lines"> |
||||
|
<tree delete="false" create="false"> |
||||
|
<field name="name"/> |
||||
|
<field name="amount"/> |
||||
|
<field name="accrued_amount"/> |
||||
|
<field name="interest"/> |
||||
|
<field name="accrued_interest"/> |
||||
|
<field name="net_interest"/> |
||||
|
<field name="taxes_amount"/> |
||||
|
<field name="due_amount"/> |
||||
|
<field name="due_date"/> |
||||
|
<field name="state"/> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</page> |
||||
|
</notebook> |
||||
|
</sheet> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="view_loan_issue_line_filter" model="ir.ui.view"> |
||||
|
<field name="name">Loans Search</field> |
||||
|
<field name="model">loan.issue.line</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<search string="Search Loans"> |
||||
|
<field name="name"/> |
||||
|
<field name="partner_id"/> |
||||
|
<field name="loan_issue_id"/> |
||||
|
<separator/> |
||||
|
<filter string="Draft" name="state_draft" |
||||
|
domain="[('state','=','draft')]"/> |
||||
|
<filter string="Paid" name="state_paid" |
||||
|
domain="[('state','=','paid')]"/> |
||||
|
<filter string="Done" name="state_done" |
||||
|
domain="[('state','=','done')]"/> |
||||
|
<filter string="Subscribed" name="state_subscribed" |
||||
|
domain="[('state','=','subscribed')]"/> |
||||
|
<group expand="0" name="group_by" string="Group By"> |
||||
|
<filter name="loan_issue_id" string="Loan Issue" |
||||
|
context="{'group_by' : 'loan_issue_id'}"/> |
||||
|
<filter name="date" string="Subscription Date" |
||||
|
context="{'group_by': 'date'}"/> |
||||
|
</group> |
||||
|
</search> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,2 @@ |
|||||
|
from . import models |
||||
|
from . import wizard |
@ -0,0 +1,29 @@ |
|||||
|
# Copyright 2020 - ongoing Coop IT Easy SCRLfs (<http://www.coopiteasy.be>) |
||||
|
# - Houssine BAKKALI - <houssine@coopiteasy.be> |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
{ |
||||
|
"name": "Easy My Coop Loan Account", |
||||
|
"version": "12.0.1.0.0", |
||||
|
"depends": [ |
||||
|
"account", |
||||
|
"account_fiscal_year", |
||||
|
"easy_my_coop_loan", |
||||
|
], |
||||
|
"author": "Coop IT Easy SCRLfs", |
||||
|
"category": "Cooperative management", |
||||
|
"website": "https://www.coopiteasy.be", |
||||
|
"license": "AGPL-3", |
||||
|
"summary": """ |
||||
|
This module brings the accounting part of the loan issue. |
||||
|
It has for purpose to generate all the accounting entries to the covered |
||||
|
use cases. |
||||
|
""", |
||||
|
"data": [ |
||||
|
"data/emc_loan_account_data.xml", |
||||
|
"views/res_company_view.xml", |
||||
|
"views/loan_issue_line_view.xml", |
||||
|
"wizard/end_of_year_operation.xml", |
||||
|
], |
||||
|
"installable": True, |
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
<odoo> |
||||
|
<data noupdate="1"> |
||||
|
<record id="sequence_awaiting_loan_payment_journal" model="ir.sequence"> |
||||
|
<field name="name">Awaiting Loan Payment Journal</field> |
||||
|
<field eval="3" name="padding"/> |
||||
|
<field name="prefix">ALPJ/%(year)s/</field> |
||||
|
<field name="use_date_range">True</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="subscription_journal" model="account.journal"> |
||||
|
<field name="name">Awaiting Loan Payment Journal</field> |
||||
|
<field name="code">ALPJ</field> |
||||
|
<field name="type">general</field> |
||||
|
<field name="sequence_id" ref="sequence_awaiting_loan_payment_journal"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="sequence_loan_journal" model="ir.sequence"> |
||||
|
<field name="name">Loan Journal</field> |
||||
|
<field eval="3" name="padding"/> |
||||
|
<field name="prefix">LOANJ/%(year)s/</field> |
||||
|
<field name="use_date_range">True</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="loan_journal" model="account.journal"> |
||||
|
<field name="name">Loan Journal</field> |
||||
|
<field name="code">LOANJ</field> |
||||
|
<field name="type">general</field> |
||||
|
<field name="sequence_id" ref="sequence_loan_journal"/> |
||||
|
</record> |
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,5 @@ |
|||||
|
from . import company |
||||
|
from . import loan_issue_line |
||||
|
from . import interest_line |
||||
|
from . import account_move |
||||
|
from . import account_fiscal_year |
@ -0,0 +1,46 @@ |
|||||
|
# Copyright 2020 Coop IT Easy SCRL fs |
||||
|
# Houssine BAKKALI <houssine@coopiteasy.be> |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
|
||||
|
from dateutil.relativedelta import relativedelta |
||||
|
|
||||
|
from odoo import api, fields, models |
||||
|
from odoo.exceptions import UserError |
||||
|
|
||||
|
|
||||
|
class AccountFiscalYear(models.Model): |
||||
|
_inherit = "account.fiscal.year" |
||||
|
|
||||
|
@api.model |
||||
|
def get_ongoing_fiscal_year(self, company_id=None): |
||||
|
today = fields.Date.today() |
||||
|
fy = self.env["account.fiscal.year"].search([ |
||||
|
('date_from', '<=', today), |
||||
|
('date_to', '>=', today), |
||||
|
]) |
||||
|
|
||||
|
if not fy: |
||||
|
raise UserError("No fiscal year has been found for %s" % |
||||
|
str(today)) |
||||
|
|
||||
|
if company_id: |
||||
|
return fy.filtered(lambda r: r.company_id == company_id) |
||||
|
return fy |
||||
|
|
||||
|
@api.model |
||||
|
def get_next_fiscal_year(self, date=None, company_id=None): |
||||
|
if not date: |
||||
|
date = fields.Date.today() |
||||
|
nextyear = date + relativedelta(years=+1) |
||||
|
fy = self.env["account.fiscal.year"].search([ |
||||
|
('date_from', '<=', nextyear), |
||||
|
('date_to', '>=', nextyear), |
||||
|
]) |
||||
|
if not fy: |
||||
|
raise UserError("No next fiscal year has been found for %s" % |
||||
|
str(nextyear)) |
||||
|
if company_id: |
||||
|
return fy.filtered(lambda r: r.company_id == company_id) |
||||
|
|
||||
|
return fy |
@ -0,0 +1,39 @@ |
|||||
|
# Copyright 2020 Coop IT Easy SCRL fs |
||||
|
# Houssine BAKKALI <houssine@coopiteasy.be> |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class AccountMove(models.Model): |
||||
|
_inherit = "account.move" |
||||
|
|
||||
|
loan_issue_line = fields.One2many( |
||||
|
"loan.issue.line", |
||||
|
"awaiting_move_id", |
||||
|
string="Loan issue line", |
||||
|
readonly=True, |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AccountMoveLine(models.Model): |
||||
|
_inherit = "account.move.line" |
||||
|
|
||||
|
loan_issue_line = fields.One2many( |
||||
|
"loan.issue.line", |
||||
|
related="move_id.loan_issue_line", |
||||
|
) |
||||
|
|
||||
|
@api.multi |
||||
|
def check_full_reconcile(self): |
||||
|
super(AccountMoveLine, self).check_full_reconcile() |
||||
|
full_reconcile_id = self.mapped("full_reconcile_id") |
||||
|
loan_issue_line = self.mapped("loan_issue_line") |
||||
|
if full_reconcile_id and loan_issue_line: |
||||
|
for move_line in self: |
||||
|
if move_line.statement_id: |
||||
|
loan_issue_line.payment_date = move_line.date |
||||
|
loan_issue_line.with_context( |
||||
|
{"paid_by_bank_statement": True} |
||||
|
).action_paid() |
||||
|
print(full_reconcile_id) |
@ -0,0 +1,92 @@ |
|||||
|
# Copyright 2020 Coop IT Easy SCRL fs |
||||
|
# Houssine Bakkali <houssine@coopiteasy.be> |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
|
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class ResCompany(models.Model): |
||||
|
_inherit = "res.company" |
||||
|
|
||||
|
awaiting_loan_payment_account = fields.Many2one( |
||||
|
"account.account", |
||||
|
company_dependent=True, |
||||
|
string="Awaiting Loan Payment Account", |
||||
|
domain=[ |
||||
|
("internal_type", "=", "receivable"), |
||||
|
("deprecated", "=", False), |
||||
|
], |
||||
|
help="This account serve to track awaiting payment." |
||||
|
" It only serve a bank reconciliation purpose to register the awaiting" |
||||
|
" loan payment as received/paid", |
||||
|
required=True, |
||||
|
) |
||||
|
loaner_account = fields.Many2one( |
||||
|
"account.account", |
||||
|
company_dependent=True, |
||||
|
string="Loaner Account", |
||||
|
help="This account will be the default one as the" |
||||
|
" receivable account for the cooperators", |
||||
|
required=True, |
||||
|
) |
||||
|
debt_long_term_account = fields.Many2one( |
||||
|
"account.account", |
||||
|
company_dependent=True, |
||||
|
string="Long Term Debt Account", |
||||
|
help="This account is used to register the loan debt due for more" |
||||
|
" than one year", |
||||
|
required=True, |
||||
|
) |
||||
|
debt_long_term_fy_account = fields.Many2one( |
||||
|
"account.account", |
||||
|
company_dependent=True, |
||||
|
string="Long Term Debt Due In The Year Account", |
||||
|
help="This account is used to register the loan debt due for the" |
||||
|
" current fiscal year", |
||||
|
required=True, |
||||
|
) |
||||
|
debt_long_term_due_account = fields.Many2one( |
||||
|
"account.account", |
||||
|
company_dependent=True, |
||||
|
string="Long Term Debt Due Account", |
||||
|
help="This account is used to register the loan debt due", |
||||
|
required=True, |
||||
|
) |
||||
|
expense_account = fields.Many2one( |
||||
|
"account.account", |
||||
|
company_dependent=True, |
||||
|
string="Expense Account", |
||||
|
help="This account is used to register the prorata temporis interest" |
||||
|
" amount at the end of the fiscal year", |
||||
|
required=True, |
||||
|
) |
||||
|
interest_account = fields.Many2one( |
||||
|
"account.account", |
||||
|
company_dependent=True, |
||||
|
string="Interest Account", |
||||
|
help="This account is used to register the due loan interest", |
||||
|
required=True, |
||||
|
) |
||||
|
tax_account = fields.Many2one( |
||||
|
"account.account", |
||||
|
company_dependent=True, |
||||
|
string="Tax Account", |
||||
|
help="This account is used to register the tax to pay" |
||||
|
" to the tax administration", |
||||
|
required=True, |
||||
|
) |
||||
|
awaiting_loan_payment_journal = fields.Many2one( |
||||
|
"account.journal", |
||||
|
string="Awaiting loan payment journal", |
||||
|
help="This journal will be the default one as the" |
||||
|
" to track the payment from the loaners", |
||||
|
required=True, |
||||
|
) |
||||
|
loan_journal = fields.Many2one( |
||||
|
"account.journal", |
||||
|
string="Loan journal", |
||||
|
help="This journal will be the one used to register all" |
||||
|
" the loan account move lines", |
||||
|
required=True, |
||||
|
) |
@ -0,0 +1,200 @@ |
|||||
|
# Copyright 2020 Coop IT Easy SCRL fs |
||||
|
# Houssine BAKKALI <houssine@coopiteasy.be> |
||||
|
# 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 LoanInterestLine(models.Model): |
||||
|
_inherit = "loan.interest.line" |
||||
|
|
||||
|
loan_due_fy_move = fields.Many2one( |
||||
|
comodel_name="account.move", |
||||
|
string="Loan due this fiscal year account move" |
||||
|
) |
||||
|
loan_due_move = fields.Many2one( |
||||
|
comodel_name="account.move", |
||||
|
string="Loan due this fiscal year account move" |
||||
|
) |
||||
|
loan_reimbursment_move = fields.Many2one( |
||||
|
comodel_name="account.move", |
||||
|
string="Loan reimbursement account move" |
||||
|
) |
||||
|
interest_closing_fy = fields.Many2one( |
||||
|
comodel_name="account.move", |
||||
|
string="Interest closing fiscal year account move" |
||||
|
) |
||||
|
interest_opening_fy = fields.Many2one( |
||||
|
comodel_name="account.move", |
||||
|
string="Interest opening fiscal year account move" |
||||
|
) |
||||
|
|
||||
|
@api.multi |
||||
|
def get_move_line(self, move_id, partner=None): |
||||
|
self.ensure_one() |
||||
|
move_line = { |
||||
|
"date_maturity": self.due_date, |
||||
|
"date": self.due_date, |
||||
|
"move_id": move_id.id, |
||||
|
} |
||||
|
if partner: |
||||
|
move_line["partner_id"] = partner.id |
||||
|
return move_line |
||||
|
|
||||
|
@api.multi |
||||
|
def create_move(self, date=None): |
||||
|
self.ensure_one() |
||||
|
if date: |
||||
|
due_date = date |
||||
|
else: |
||||
|
due_date = self.due_date |
||||
|
|
||||
|
return self.env["account.move"].create({ |
||||
|
"ref": self.name, |
||||
|
"date": due_date, |
||||
|
"journal_id": self.company_id.loan_journal.id, |
||||
|
}) |
||||
|
|
||||
|
@api.multi |
||||
|
def generate_payment_move_lines(self): |
||||
|
|
||||
|
for line in self: |
||||
|
if not self.loan_reimbursment_move: |
||||
|
company = line.company_id |
||||
|
move = line.create_move() |
||||
|
|
||||
|
debit_vals = line.get_move_line(move, line.partner_id) |
||||
|
loaner_vals = line.get_move_line(move, line.partner_id) |
||||
|
|
||||
|
debit_vals["debit"] = line.interest |
||||
|
debit_vals["account_id"] = company.interest_account.id |
||||
|
|
||||
|
if line.due_loan_amount > 0 and line.net_interest > 0: |
||||
|
loaner_vals["credit"] = line.due_amount |
||||
|
elif line.due_loan_amount > 0: |
||||
|
loaner_vals["credit"] = line.due_loan_amount |
||||
|
elif line.net_interest > 0: |
||||
|
loaner_vals["credit"] = line.net_interest |
||||
|
loaner_vals["account_id"] = company.loaner_account |
||||
|
|
||||
|
vals_list = [debit_vals, loaner_vals] |
||||
|
|
||||
|
if line.taxes_amount > 0: |
||||
|
tax_vals = line.get_move_line(move) |
||||
|
tax_vals["credit"] = line.taxes_amount |
||||
|
tax_vals["account_id"] = company.tax_account.id |
||||
|
vals_list.append(tax_vals) |
||||
|
|
||||
|
self.env["account.move.line"].create(vals_list) |
||||
|
|
||||
|
line.write({"loan_reimbursment_move": move.id}) |
||||
|
|
||||
|
@api.multi |
||||
|
def generate_interest_move_lines_fy(self, date, next_fy): |
||||
|
aml_obj = self.env["account.move.line"] |
||||
|
for line in self: |
||||
|
if not self.interest_closing_fy: |
||||
|
company = line.company_id |
||||
|
|
||||
|
# compute the prorata interest for the fiscal year |
||||
|
prorata_date = line.due_date - relativedelta(years=-1) |
||||
|
diff_days = (prorata_date - date).days |
||||
|
days = line.issue_line.get_number_of_days(date.year) |
||||
|
|
||||
|
previous_interest = line.accrued_interest - line.interest |
||||
|
prorata_interest = line.interest * (diff_days / days) |
||||
|
interest_fy = previous_interest + prorata_interest |
||||
|
|
||||
|
# create interest closing account move lines |
||||
|
close_fy_move = line.create_move(date) |
||||
|
deb_vals = line.get_move_line(close_fy_move, line.partner_id) |
||||
|
cred_vals = line.get_move_line(close_fy_move, line.partner_id) |
||||
|
|
||||
|
deb_vals["debit"] = interest_fy |
||||
|
deb_vals["date"] = date |
||||
|
deb_vals["account_id"] = company.interest_account.id |
||||
|
|
||||
|
cred_vals["credit"] = interest_fy |
||||
|
cred_vals["date"] = date |
||||
|
cred_vals["account_id"] = company.expense_account.id |
||||
|
|
||||
|
aml_obj.create([deb_vals, cred_vals]) |
||||
|
|
||||
|
line.write({"interest_closing_fy": close_fy_move.id}) |
||||
|
|
||||
|
# create interest opening account move lines |
||||
|
opening_date = next_fy.date_from |
||||
|
open_fy_move = line.create_move(opening_date) |
||||
|
deb_vals = line.get_move_line(open_fy_move, line.partner_id) |
||||
|
cred_vals = line.get_move_line(open_fy_move, line.partner_id) |
||||
|
|
||||
|
deb_vals["debit"] = interest_fy |
||||
|
deb_vals["date"] = opening_date |
||||
|
deb_vals["account_id"] = company.expense_account.id |
||||
|
|
||||
|
cred_vals["credit"] = interest_fy |
||||
|
cred_vals["date"] = opening_date |
||||
|
cred_vals["account_id"] = company.interest_account.id |
||||
|
|
||||
|
aml_obj.create([deb_vals, cred_vals]) |
||||
|
line.write({"interest_opening_fy": open_fy_move.id}) |
||||
|
|
||||
|
@api.multi |
||||
|
def generate_loan_due_fy(self, date): |
||||
|
|
||||
|
for line in self: |
||||
|
if not self.loan_due_fy_move: |
||||
|
company = line.company_id |
||||
|
move = line.create_move(date) |
||||
|
|
||||
|
deb_vals = line.get_move_line(move, line.partner_id) |
||||
|
cred_vals = line.get_move_line(move, line.partner_id) |
||||
|
|
||||
|
deb_vals["debit"] = line.due_loan_amount |
||||
|
deb_vals["date"] = date |
||||
|
deb_vals["account_id"] = company.debt_long_term_account.id |
||||
|
|
||||
|
cred_vals["credit"] = line.due_loan_amount |
||||
|
cred_vals["date"] = date |
||||
|
cred_vals["account_id"] = company.debt_long_term_fy_account.id |
||||
|
|
||||
|
self.env["account.move.line"].create([deb_vals, cred_vals]) |
||||
|
|
||||
|
line.write({"loan_due_fy_move": move.id, |
||||
|
"state": "due_fy"}) |
||||
|
|
||||
|
@api.multi |
||||
|
def generate_loan_due_now(self): |
||||
|
|
||||
|
for line in self: |
||||
|
if line.loan_due_move: |
||||
|
company = line.company_id |
||||
|
move = line.create_move(fields.Date.today()) |
||||
|
|
||||
|
debit_vals = line.get_move_line(move, line.partner_id) |
||||
|
credit_vals = line.get_move_line(move, line.partner_id) |
||||
|
|
||||
|
debit_vals["debit"] = line.due_loan_amount |
||||
|
debit_vals["account_id"] = company.debt_long_term_fy_account.id |
||||
|
|
||||
|
credit_vals["credit"] = line.due_loan_amount |
||||
|
credit_vals["account_id"] = company.debt_long_term_due_account |
||||
|
|
||||
|
self.env["account.move.line"].create([debit_vals, credit_vals]) |
||||
|
|
||||
|
line.write({"loan_due_move": move.id, |
||||
|
"state": "due"}) |
||||
|
|
||||
|
@api.model |
||||
|
def _generate_payment_move(self): |
||||
|
# TODO configure how many days before you want generate the move lines |
||||
|
fy = self.env["account.fiscal.year"].get_next_fiscal_year() |
||||
|
interest_lines = self.search([ |
||||
|
('due_date', '>=', fy.date_from), |
||||
|
('due_date', '<=', fy.date_to), |
||||
|
('due_amount', '>', 0), |
||||
|
]) |
||||
|
|
||||
|
interest_lines.generate_payment_move_lines() |
||||
|
|
||||
|
return True |
@ -0,0 +1,71 @@ |
|||||
|
# Copyright 2020 Coop IT Easy SCRL fs |
||||
|
# Houssine BAKKALI <houssine@coopiteasy.be> |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from datetime import date |
||||
|
|
||||
|
from odoo import api, fields, models, _ |
||||
|
from odoo.exceptions import UserError |
||||
|
|
||||
|
|
||||
|
class LoanIssueLine(models.Model): |
||||
|
_inherit = "loan.issue.line" |
||||
|
|
||||
|
awaiting_move_id = fields.Many2one( |
||||
|
comodel_name="account.move", |
||||
|
string="Awaiting payment account move" |
||||
|
) |
||||
|
|
||||
|
@api.multi |
||||
|
def get_loan_move_line(self, move_id): |
||||
|
self.ensure_one() |
||||
|
move_line = { |
||||
|
"partner_id": self.partner_id.id, |
||||
|
"date_maturity": date.today(), |
||||
|
"move_id": move_id, |
||||
|
} |
||||
|
return move_line |
||||
|
|
||||
|
@api.model |
||||
|
def create_move(self, line, date, journal): |
||||
|
return self.env["account.move"].create({ |
||||
|
"ref": line.reference, |
||||
|
"date": date.today(), |
||||
|
"journal_id": journal, |
||||
|
}) |
||||
|
|
||||
|
@api.multi |
||||
|
def create_waiting_payment_move(self): |
||||
|
move_line_obj = self.env["account.move.line"] |
||||
|
for line in self: |
||||
|
comp = line.company_id |
||||
|
move = self.create_move( |
||||
|
line, |
||||
|
date.today(), |
||||
|
comp.awaiting_loan_payment_journal.id, |
||||
|
) |
||||
|
loan_vals = line.get_loan_move_line(move.id) |
||||
|
loaner_vals = line.get_loan_move_line(move.id) |
||||
|
|
||||
|
loan_vals["account_id"] = comp.debt_long_term_account.id |
||||
|
loan_vals["credit"] = line.amount |
||||
|
|
||||
|
loaner_vals["account_id"] = comp.awaiting_loan_payment_account.id |
||||
|
loaner_vals["debit"] = line.amount |
||||
|
|
||||
|
move_line_obj.create([loan_vals, loaner_vals]) |
||||
|
line.awaiting_move_id = move |
||||
|
|
||||
|
@api.multi |
||||
|
def action_request_payment(self): |
||||
|
self.create_waiting_payment_move() |
||||
|
super(LoanIssueLine, self).action_request_payment() |
||||
|
|
||||
|
@api.multi |
||||
|
def action_paid(self): |
||||
|
paid_by = self.env.context.get("paid_by_bank_statement") |
||||
|
if paid_by: |
||||
|
super(LoanIssueLine, self).action_paid() |
||||
|
else: |
||||
|
raise UserError(_("The payment must be registered" |
||||
|
" by bank statement")) |
@ -0,0 +1,22 @@ |
|||||
|
<odoo> |
||||
|
|
||||
|
<record id="view_loan_issue_line_account_form" model="ir.ui.view"> |
||||
|
<field name="name">loan.issue.line.form</field> |
||||
|
<field name="model">loan.issue.line</field> |
||||
|
<field name="inherit_id" ref="easy_my_coop_loan.view_loan_issue_line_form"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<page name="interest_lines" position="after"> |
||||
|
<page name="accounting" string="Accounting"> |
||||
|
<group> |
||||
|
<group> |
||||
|
<field name="awaiting_move_id" readonly="True"/> |
||||
|
</group> |
||||
|
<group> |
||||
|
</group> |
||||
|
</group> |
||||
|
</page> |
||||
|
</page> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,25 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<odoo> |
||||
|
<record model="ir.ui.view" id="view_company_easy_my_coop_loan"> |
||||
|
<field name="name">res.company.form.easymy.coop</field> |
||||
|
<field name="inherit_id" ref="easy_my_coop.view_company_inherit_form2"/> |
||||
|
<field name="model">res.company</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<group name="coop_grp" position="before"> |
||||
|
<group name="coop_loan_grp" string="EasyMy Coop Loan" |
||||
|
groups="easy_my_coop.group_easy_my_coop_user"> |
||||
|
<field name="awaiting_loan_payment_account"/> |
||||
|
<field name="loaner_account"/> |
||||
|
<field name="debt_long_term_account"/> |
||||
|
<field name="debt_long_term_fy_account"/> |
||||
|
<field name="debt_long_term_due_account"/> |
||||
|
<field name="expense_account"/> |
||||
|
<field name="interest_account"/> |
||||
|
<field name="tax_account"/> |
||||
|
<field name="awaiting_loan_payment_journal"/> |
||||
|
<field name="loan_journal"/> |
||||
|
</group> |
||||
|
</group> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1 @@ |
|||||
|
from . import end_of_year_operation |
@ -0,0 +1,77 @@ |
|||||
|
# Copyright 2020 Coop IT Easy SCRL fs |
||||
|
# Houssine BAKKALI <houssine@coopiteasy.be> |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
from odoo.exceptions import UserError |
||||
|
|
||||
|
|
||||
|
class LoanEndOfYearOperation(models.TransientModel): |
||||
|
_name = "loan.end.of.year.operation" |
||||
|
operation_type = fields.Selection( |
||||
|
[("eoy_operation", "End of year operation"), |
||||
|
("loan_due", "Loan payment account move lines")], |
||||
|
required=True, |
||||
|
string="Operation type" |
||||
|
) |
||||
|
ongoing_fy_id = fields.Many2one( |
||||
|
comodel_name="account.fiscal.year", |
||||
|
string="Ongoing fiscal year", |
||||
|
required=True |
||||
|
) |
||||
|
due_date = fields.Date( |
||||
|
string="Due date" |
||||
|
) |
||||
|
|
||||
|
@api.multi |
||||
|
def run(self): |
||||
|
self.ensure_one() |
||||
|
afy_obj = self.env["account.fiscal.year"] |
||||
|
interest_line_obj = self.env["loan.interest.line"] |
||||
|
|
||||
|
loan_issues = self.env["loan.issue"].browse( |
||||
|
self._context.get("active_ids") |
||||
|
) |
||||
|
|
||||
|
last_fy_day = self.ongoing_fy_id.date_to |
||||
|
next_fy = afy_obj.get_next_fiscal_year(last_fy_day) |
||||
|
|
||||
|
if self.ongoing_fy_id == "eoy_operation": |
||||
|
if next_fy: |
||||
|
interest_lines_loan = interest_line_obj.search([ |
||||
|
("due_date", ">=", next_fy.date_from), |
||||
|
("due_date", "<=", next_fy.date_to), |
||||
|
("due_loan_amount", ">", 0), |
||||
|
("loan_issue_id", "in", loan_issues.ids), |
||||
|
("loan_reimbursment_move", "=", False) |
||||
|
]) |
||||
|
|
||||
|
interest_lines_loan.generate_loan_due_fy(last_fy_day) |
||||
|
interest_lines = interest_line_obj.search([ |
||||
|
("due_date", ">=", next_fy.date_from), |
||||
|
("due_date", "<=", next_fy.date_to), |
||||
|
("interest", ">", 0), |
||||
|
("loan_issue_id", "in", loan_issues.ids), |
||||
|
("interest_closing_fy", "=", False), |
||||
|
("interest_opening_fy", "=", False) |
||||
|
]) |
||||
|
|
||||
|
interest_lines.generate_interest_move_lines_fy(last_fy_day, |
||||
|
next_fy) |
||||
|
# interest_lines.write({"state": "scheduled"}) |
||||
|
# interest_lines_loan.write({"state": "scheduled"}) |
||||
|
(interest_lines + interest_lines_loan).write({"state": |
||||
|
"scheduled"}) |
||||
|
if not interest_lines_loan and not interest_lines: |
||||
|
raise UserError("There is no end of year account move" |
||||
|
" lines to generate for the selected loan" |
||||
|
" issue") |
||||
|
elif self.ongoing_fy_id == "loan_due": |
||||
|
interest_lines = interest_line_obj.search([ |
||||
|
("due_date", ">=", next_fy.date_from), |
||||
|
("due_date", "<=", next_fy.date_to), |
||||
|
("interest", ">", 0), |
||||
|
("loan_issue_id", "in", loan_issues.ids), |
||||
|
("interest_closing_fy", "=", False), |
||||
|
("interest_opening_fy", "=", False) |
||||
|
]) |
@ -0,0 +1,35 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<record id="view_loan_end_of_year_operation" model="ir.ui.view"> |
||||
|
<field name="name">End of year loan operation</field> |
||||
|
<field name="model">loan.end.of.year.operation</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form string="End of year loan operation"> |
||||
|
<p class="oe_grey"> |
||||
|
End of year loan operation. |
||||
|
</p> |
||||
|
<group> |
||||
|
<field name="ongoing_fy_id"/> |
||||
|
<field name="due_date" attrs="{'invisible':[('ongoing_fy_id', '!=', 'loan_due')]}"/> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button name="run" string="Run" type="object" |
||||
|
class="btn-primary"/> |
||||
|
<button string="Cancel" class="btn-default" |
||||
|
special="cancel"/> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<act_window id="action_view_loan_end_of_year_operation" |
||||
|
multi="True" |
||||
|
key2="client_action_multi" |
||||
|
name="End of year loan operation" |
||||
|
res_model="loan.end.of.year.operation" |
||||
|
src_model="loan.issue" |
||||
|
view_mode="form" |
||||
|
view_type="form" |
||||
|
target="new" |
||||
|
groups="easy_my_coop.group_easy_my_coop_manager"/> |
||||
|
</odoo> |
@ -0,0 +1 @@ |
|||||
|
from . import models |
@ -0,0 +1,21 @@ |
|||||
|
# Copyright 2020 - ongoing Coop IT Easy (http://www.coopiteasy.be) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
{ |
||||
|
'name': 'Easy My Coop Loan BBA', |
||||
|
'category': 'Sales', |
||||
|
'author': "Coop IT Easy - Houssine BAKKALI <houssine@coopiteasy.be>", |
||||
|
'website': 'https://www.coopiteasy.be', |
||||
|
'version': '12.0.1.0.0', |
||||
|
'license': 'AGPL-3', |
||||
|
'depends': [ |
||||
|
'easy_my_coop_loan', |
||||
|
'l10n_be_invoice_bba' |
||||
|
], |
||||
|
"description": """ |
||||
|
This module implements the bba structured communication on the loan line. |
||||
|
""", |
||||
|
'data': [ |
||||
|
], |
||||
|
'installable': True, |
||||
|
} |
@ -0,0 +1 @@ |
|||||
|
from . import loan_issue_line |
@ -0,0 +1,95 @@ |
|||||
|
# © 2018 Coop IT Easy (http://www.coopiteasy.be) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
import random |
||||
|
import re |
||||
|
|
||||
|
from odoo import api, fields, models, _ |
||||
|
from odoo.exceptions import UserError |
||||
|
|
||||
|
|
||||
|
class LoanIssueLine(models.Model): |
||||
|
|
||||
|
_inherit = 'loan.issue.line' |
||||
|
|
||||
|
@api.multi |
||||
|
def generate_bbacomm(self): |
||||
|
self.ensure_one() |
||||
|
algorithm = self.company_id.l10n_be_structured_comm |
||||
|
if algorithm == 'date': |
||||
|
date = fields.Date.from_string(fields.Date.today()) |
||||
|
doy = date.strftime('%j') |
||||
|
year = date.strftime('%Y') |
||||
|
seq = '001' |
||||
|
invoices = self.search([('type', '=', 'out_invoice'), |
||||
|
('reference', 'like', '+++%s/%s/%%' % |
||||
|
(doy, year))], order='reference') |
||||
|
if invoices: |
||||
|
prev_seq = int(invoices[-1].reference[12:15]) |
||||
|
if prev_seq < 999: |
||||
|
seq = '%03d' % (prev_seq + 1) |
||||
|
else: |
||||
|
raise UserError(_('The daily maximum of outgoing invoices ' |
||||
|
'with an automatically generated BBA ' |
||||
|
'Structured Communications has been ' |
||||
|
'exceeded!' '\nPlease create manually a ' |
||||
|
'unique BBA Structured Communication.')) |
||||
|
bbacomm = doy + year + seq |
||||
|
base = int(bbacomm) |
||||
|
mod = base % 97 or 97 |
||||
|
reference = '+++%s/%s/%s%02d+++' % (doy, year, seq, mod) |
||||
|
elif algorithm == 'partner_ref': |
||||
|
partner_ref = self.partner_id.ref |
||||
|
print(partner_ref) |
||||
|
partner_ref_nr = re.sub('\D', '', partner_ref or '') |
||||
|
if (len(partner_ref_nr) < 3) or (len(partner_ref_nr) > 7): |
||||
|
raise UserError(_('The Customer should have an Internal ' |
||||
|
'Reference with min 3 and max 7 digits ' |
||||
|
'for the generation of BBA Structured ' |
||||
|
'Communications!')) |
||||
|
else: |
||||
|
partner_ref_nr = partner_ref_nr.ljust(7, '0') |
||||
|
seq = '001' |
||||
|
invoices = self.search([('type', '=', 'out_invoice'), |
||||
|
('reference', 'like', '+++%s/%s/%%' % |
||||
|
(partner_ref_nr[:3], |
||||
|
partner_ref_nr[3:])) |
||||
|
], order='reference') |
||||
|
if invoices: |
||||
|
prev_seq = int(invoices[-1].reference[12:15]) |
||||
|
if prev_seq < 999: |
||||
|
seq = '%03d' % (prev_seq + 1) |
||||
|
else: |
||||
|
raise UserError(_( |
||||
|
'The daily maximum of outgoing invoices with an ' |
||||
|
'automatically generated BBA Structured ' |
||||
|
'Communications has been exceeded!' |
||||
|
'\nPlease create manually a unique BBA Structured ' |
||||
|
'Communication.')) |
||||
|
bbacomm = partner_ref_nr + seq |
||||
|
base = int(bbacomm) |
||||
|
mod = base % 97 or 97 |
||||
|
reference = '+++%s/%s/%s%02d+++' % (partner_ref_nr[:3], |
||||
|
partner_ref_nr[3:], seq, mod) |
||||
|
elif algorithm == 'random': |
||||
|
base = random.randint(1, 9999999999) |
||||
|
bbacomm = str(base).rjust(10, '0') |
||||
|
base = int(bbacomm) |
||||
|
mod = base % 97 or 97 |
||||
|
mod = str(mod).rjust(2, '0') |
||||
|
reference = '+++%s/%s/%s%s+++' % (bbacomm[:3], |
||||
|
bbacomm[3:7], |
||||
|
bbacomm[7:], mod) |
||||
|
else: |
||||
|
raise UserError(_("Unsupported Structured Communication Type " |
||||
|
"Algorithm '%s' !" |
||||
|
"\nPlease contact your Odoo support channel." |
||||
|
) % algorithm) |
||||
|
return reference |
||||
|
|
||||
|
@api.multi |
||||
|
def action_validate(self): |
||||
|
super(LoanIssueLine, self).action_validate() |
||||
|
for line in self: |
||||
|
bba = line.generate_bbacomm() |
||||
|
line.write({'reference': bba}) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue