diff --git a/easy_my_coop_loan/models/__init__.py b/easy_my_coop_loan/models/__init__.py index 21d0546..52fe449 100644 --- a/easy_my_coop_loan/models/__init__.py +++ b/easy_my_coop_loan/models/__init__.py @@ -1,5 +1,4 @@ -from . import loan -from . import loan_issue_line -from . import interest_line -from . import partner -from . import mail_template +from . import loan +from . import loan_issue_line +from . import interest_line +from . import partner diff --git a/easy_my_coop_loan/models/interest_line.py b/easy_my_coop_loan/models/interest_line.py index c934283..23d0670 100644 --- a/easy_my_coop_loan/models/interest_line.py +++ b/easy_my_coop_loan/models/interest_line.py @@ -1,60 +1,64 @@ -from odoo import fields, models - - -class LoanInterestLine(models.Model): - _name = 'loan.interest.line' - _description = "Loan Interest Line" - - name = fields.Integer(string="Year", - required=True) - issue_line = fields.Many2one('loan.issue.line', - string="Subscribed loan", - required=True) - partner_id = fields.Many2one(related='issue_line.partner_id', - store=True, - readlonly=True) - amount = fields.Monetary(related='issue_line.amount', - string="Subscribed amount", - currency_field='company_currency_id', - readonly=True) - interest = fields.Monetary(string="Gross interest amount", - currency_field='company_currency_id', - readonly=True) - net_interest = fields.Monetary(string="Net interest amount", - currency_field='company_currency_id', - readonly=True) - taxes_rate = fields.Float(string="Taxes on interest", - required=True) - taxes_amount = fields.Monetary(string="Taxes amount", - currency_field='company_currency_id', - readonly=True) - accrued_amount = fields.Monetary(string="Accrued amount", - currency_field='company_currency_id', - readonly=True) - accrued_interest = fields.Monetary(string="Accrued gross interest", - currency_field='company_currency_id', - readonly=True) - accrued_net_interest = fields.Monetary( - string="Accrued net interest", - currency_field='company_currency_id', - readonly=True) - accrued_taxes = fields.Monetary(string="Accrued taxes to pay", - currency_field='company_currency_id', - readonly=True) - due_date = fields.Date(string="Due date") - company_currency_id = fields.Many2one('res.currency', - related='company_id.currency_id', - string="Company Currency", - readonly=True) - company_id = fields.Many2one('res.company', - related='issue_line.company_id', - string="Company", - readonly=True) - state = fields.Selection([('draft', 'Draft'), - ('due', 'Due'), - ('requested', 'Payment requested'), - ('donation', 'Donation'), - ('paid', 'Paid') - ], - string="State", - default="draft") +# Copyright 2019 Coop IT Easy SCRL fs +# Houssine BAKKALI +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class LoanInterestLine(models.Model): + _name = 'loan.interest.line' + _description = "Loan Interest Line" + + name = fields.Integer(string="Year", + required=True) + issue_line = fields.Many2one('loan.issue.line', + string="Subscribed loan", + required=True) + partner_id = fields.Many2one(related='issue_line.partner_id', + store=True, + readlonly=True) + amount = fields.Monetary(related='issue_line.amount', + string="Subscribed amount", + currency_field='company_currency_id', + readonly=True) + interest = fields.Monetary(string="Gross interest amount", + currency_field='company_currency_id', + readonly=True) + net_interest = fields.Monetary(string="Net interest amount", + currency_field='company_currency_id', + readonly=True) + taxes_rate = fields.Float(string="Taxes on interest", + required=True) + taxes_amount = fields.Monetary(string="Taxes amount", + currency_field='company_currency_id', + readonly=True) + accrued_amount = fields.Monetary(string="Accrued amount", + currency_field='company_currency_id', + readonly=True) + accrued_interest = fields.Monetary(string="Accrued gross interest", + currency_field='company_currency_id', + readonly=True) + accrued_net_interest = fields.Monetary( + string="Accrued net interest", + currency_field='company_currency_id', + readonly=True) + accrued_taxes = fields.Monetary(string="Accrued taxes to pay", + currency_field='company_currency_id', + readonly=True) + due_date = fields.Date(string="Due date") + company_currency_id = fields.Many2one('res.currency', + related='company_id.currency_id', + string="Company Currency", + readonly=True) + company_id = fields.Many2one('res.company', + related='issue_line.company_id', + string="Company", + readonly=True) + state = fields.Selection([('draft', 'Draft'), + ('due', 'Due'), + ('requested', 'Payment requested'), + ('donation', 'Donation'), + ('paid', 'Paid') + ], + string="State", + default="draft") diff --git a/easy_my_coop_loan/models/loan.py b/easy_my_coop_loan/models/loan.py index f9f282f..122a5ad 100644 --- a/easy_my_coop_loan/models/loan.py +++ b/easy_my_coop_loan/models/loan.py @@ -1,177 +1,178 @@ -import logging - -from odoo import api, fields, models, _ - -_logger = logging.getLogger(__name__) - - -class LoanIssue(models.Model): - _name = 'loan.issue' - _description = 'Loan Issue' - - @api.multi - def _compute_subscribed_amount(self): - for issue in self: - susbscribed_amount = 0.0 - for line in issue.loan_issue_lines.filtered( - lambda record: record.state != 'cancelled'): - susbscribed_amount += line.amount - issue.subscribed_amount = susbscribed_amount - - name = fields.Char(string="Name", - translate=True) - default_issue = fields.Boolean(string="Default issue") - subscription_start_date = fields.Date(string="Start date subscription period") - subscription_end_date = fields.Date(string="End date subscription period") - user_id = fields.Many2one('res.users', - string="Responsible") - term_date = fields.Date(string="Term date") - loan_term = fields.Float(string="Duration of the loan in month") - rate = fields.Float(string="Interest rate") - face_value = fields.Monetary(string="Facial value", - currency_field='company_currency_id', - required=True) - minimum_amount = fields.Monetary(string="Minimum amount of issue", - currency_field='company_currency_id') - maximum_amount = fields.Monetary(string="Maximum amount of issue", - currency_field='company_currency_id') - min_amount_company = fields.Monetary(string="Minimum amount for a company", - currency_field='company_currency_id') - max_amount_company = fields.Monetary(string="Maximum amount for a company", - currency_field='company_currency_id') - min_amount_person = fields.Monetary(string="Minimum amount for a person", - currency_field='company_currency_id') - max_amount_person = fields.Monetary(string="Maximum amount for a person", - currency_field='company_currency_id') - subscribed_amount = fields.Monetary(string="Subscribed amount", - compute="_compute_subscribed_amount", - currency_field='company_currency_id') - interest_payment = fields.Selection([('end', 'End'), - ('yearly', 'Yearly')], - string="Interest payment") - loan_issue_lines = fields.One2many('loan.issue.line', - 'loan_issue_id', - string="Loan issue lines") - state = fields.Selection([('draft', 'Draft'), - ('confirmed', 'Confirmed'), - ('cancelled', 'Cancelled'), - ('ongoing', 'Ongoing'), - ('closed', 'Closed')], - string="State", - default='draft') - company_currency_id = fields.Many2one('res.currency', - related='company_id.currency_id', - string="Company Currency", - readonly=True) - company_id = fields.Many2one('res.company', - string='Company', - required=True, - readonly=True, - default=lambda self: self.env['res.company']._company_default_get()) # noqa - by_company = fields.Boolean(string="By company") - by_individual = fields.Boolean(string='By individuals') - display_on_website = fields.Boolean(sting='Display on website') - taxes_rate = fields.Float(string="Taxes on interest", - required=True) - - @api.multi - def get_max_amount(self, partner): - lines = self.loan_issue_lines.filtered( - lambda r: r.partner_id == partner and r.state != 'cancelled') - already_subscribed = sum(line.amount for line in lines) - if partner.is_company: - max_amount = self.max_amount_company - already_subscribed - else: - max_amount = self.max_amount_person - already_subscribed - return max_amount - - @api.multi - def toggle_display(self): - for loan_issue in self: - loan_issue.display_on_website = not loan_issue.display_on_website - - @api.multi - def get_web_issues(self, is_company): - bond_issues = self.search([ - ('display_on_website', '=', True), - ('state', '=', 'ongoing') - ]) - if is_company is True: - return bond_issues.filtered('by_company') - else: - return bond_issues.filtered('by_company') - - @api.multi - def action_confirm(self): - self.ensure_one() - self.write({'state': 'confirmed'}) - - @api.multi - def action_open(self): - self.ensure_one() - self.write({'state': 'ongoing'}) - - @api.multi - def action_draft(self): - self.ensure_one() - self.write({'state': 'draft'}) - - @api.multi - def action_cancel(self): - self.ensure_one() - self.write({'state': 'cancelled'}) - - @api.multi - def action_close(self): - self.ensure_one() - self.write({'state': 'closed'}) - - def get_interest_vals(self, line, vals): - interest_obj = self.env['loan.interest.line'] - accrued_amount = line.amount - accrued_interest = 0 - accrued_net_interest = 0 - accrued_taxes = 0 - for year in range(1, int(self.loan_term) + 1): - interest = accrued_amount * (line.loan_issue_id.rate / 100) - accrued_amount += interest - taxes_amount = interest * (self.taxes_rate / 100) - net_interest = interest - taxes_amount - accrued_interest += interest - accrued_net_interest += net_interest - accrued_taxes += taxes_amount - vals['interest'] = interest - vals['net_interest'] = net_interest - vals['taxes_amount'] = taxes_amount - vals['accrued_amount'] = accrued_amount - vals['accrued_interest'] = accrued_interest - vals['accrued_net_interest'] = accrued_net_interest - vals['accrued_taxes'] = accrued_taxes - vals['name'] = year - interest_obj.create(vals) - - @api.multi - def compute_loan_interest(self): - self.ensure_one() - - if self.interest_payment == 'end': - due_date = self.term_date - else: - raise NotImplementedError(_("Interest payment by year hasn't been " - "implemented yet")) - for line in self.loan_issue_lines: - # TODO remove this line - line.interest_lines.unlink() - # Please Do not Forget - vals = { - 'issue_line': line.id, - 'due_date': due_date, - 'taxes_rate': self.taxes_rate - } - self.get_interest_vals(line, vals) - - rounded_term = int(self.loan_term) - if self.loan_term - rounded_term > 0: - # TODO Handle this case - raise NotImplementedError(_("Calculation on non entire year " - "hasn't been implemented yet")) +# Copyright 2019 Coop IT Easy SCRL fs +# Houssine BAKKALI +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +import logging + +from odoo import api, fields, models, _ + +_logger = logging.getLogger(__name__) + + +class LoanIssue(models.Model): + _name = 'loan.issue' + _description = 'Loan Issue' + + @api.multi + def _compute_subscribed_amount(self): + for issue in self: + susbscribed_amount = 0.0 + for line in issue.loan_issue_lines.filtered( + lambda record: record.state != 'cancelled'): + susbscribed_amount += line.amount + issue.subscribed_amount = susbscribed_amount + + name = fields.Char(string="Name", + translate=True) + default_issue = fields.Boolean(string="Default issue") + subscription_start_date = fields.Date(string="Start date subscription period") + subscription_end_date = fields.Date(string="End date subscription period") + user_id = fields.Many2one('res.users', + string="Responsible") + loan_start_date = fields.Date(string="Loan start date") + term_date = fields.Date(string="Term date") + loan_term = fields.Float(string="Duration of the loan in month") + rate = fields.Float(string="Interest rate") + face_value = fields.Monetary(string="Facial value", + currency_field='company_currency_id', + required=True) + minimum_amount = fields.Monetary(string="Minimum amount of issue", + currency_field='company_currency_id') + maximum_amount = fields.Monetary(string="Maximum amount of issue", + currency_field='company_currency_id') + min_amount_company = fields.Monetary(string="Minimum amount for a company", + currency_field='company_currency_id') + max_amount_company = fields.Monetary(string="Maximum amount for a company", + currency_field='company_currency_id') + min_amount_person = fields.Monetary(string="Minimum amount for a person", + currency_field='company_currency_id') + max_amount_person = fields.Monetary(string="Maximum amount for a person", + currency_field='company_currency_id') + subscribed_amount = fields.Monetary(string="Subscribed amount", + compute="_compute_subscribed_amount", + currency_field='company_currency_id') + interest_payment = fields.Selection([('end', 'End'), + ('yearly', 'Yearly')], + string="Interest payment") + interest_payment_info = fields.Char(string="Yearly payment on") + loan_issue_lines = fields.One2many('loan.issue.line', + 'loan_issue_id', + string="Loan issue lines") + state = fields.Selection([('draft', 'Draft'), + ('confirmed', 'Confirmed'), + ('cancelled', 'Cancelled'), + ('ongoing', 'Ongoing'), + ('closed', 'Closed')], + string="State", + default='draft') + company_currency_id = fields.Many2one('res.currency', + related='company_id.currency_id', + string="Company Currency", + readonly=True) + company_id = fields.Many2one('res.company', + string='Company', + required=True, + readonly=True, + default=lambda self: self.env['res.company']._company_default_get()) # noqa + by_company = fields.Boolean(string="By company") + by_individual = fields.Boolean(string='By individuals') + display_on_website = fields.Boolean(sting='Display on website') + taxes_rate = fields.Float(string="Taxes on interest", + required=True) + + @api.multi + def get_max_amount(self, partner): + lines = self.loan_issue_lines.filtered( + lambda r: r.partner_id == partner and r.state != 'cancelled') + already_subscribed = sum(line.amount for line in lines) + if partner.is_company: + max_amount = self.max_amount_company - already_subscribed + else: + max_amount = self.max_amount_person - already_subscribed + return max_amount + + @api.multi + def get_web_issues(self, is_company): + bond_issues = self.search([ + ('display_on_website', '=', True), + ('state', '=', 'ongoing') + ]) + if is_company is True: + return bond_issues.filtered('by_company') + else: + return bond_issues.filtered('by_company') + + @api.multi + def action_confirm(self): + self.ensure_one() + self.write({'state': 'confirmed'}) + + @api.multi + def action_open(self): + self.ensure_one() + self.write({'state': 'ongoing'}) + + @api.multi + def action_draft(self): + self.ensure_one() + self.write({'state': 'draft'}) + + @api.multi + def action_cancel(self): + self.ensure_one() + self.write({'state': 'cancelled'}) + + @api.multi + def action_close(self): + self.ensure_one() + self.write({'state': 'closed'}) + + def get_interest_vals(self, line, vals): + interest_obj = self.env['loan.interest.line'] + accrued_amount = line.amount + accrued_interest = 0 + accrued_net_interest = 0 + accrued_taxes = 0 + for year in range(1, int(self.loan_term) + 1): + interest = accrued_amount * (line.loan_issue_id.rate / 100) + accrued_amount += interest + taxes_amount = interest * (self.taxes_rate / 100) + net_interest = interest - taxes_amount + accrued_interest += interest + accrued_net_interest += net_interest + accrued_taxes += taxes_amount + vals['interest'] = interest + vals['net_interest'] = net_interest + vals['taxes_amount'] = taxes_amount + vals['accrued_amount'] = accrued_amount + vals['accrued_interest'] = accrued_interest + vals['accrued_net_interest'] = accrued_net_interest + vals['accrued_taxes'] = accrued_taxes + vals['name'] = year + interest_obj.create(vals) + + @api.multi + def compute_loan_interest(self): + self.ensure_one() + + if self.interest_payment == 'end': + due_date = self.term_date + else: + raise NotImplementedError(_("Interest payment by year hasn't been " + "implemented yet")) + for line in self.loan_issue_lines: + # TODO remove this line + line.interest_lines.unlink() + # Please Do not Forget + vals = { + 'issue_line': line.id, + 'due_date': due_date, + 'taxes_rate': self.taxes_rate + } + self.get_interest_vals(line, vals) + + rounded_term = int(self.loan_term) + if self.loan_term - rounded_term > 0: + # TODO Handle this case + raise NotImplementedError(_("Calculation on non entire year " + "hasn't been implemented yet")) diff --git a/easy_my_coop_loan/models/loan_issue_line.py b/easy_my_coop_loan/models/loan_issue_line.py index 86fe684..e31bfe9 100644 --- a/easy_my_coop_loan/models/loan_issue_line.py +++ b/easy_my_coop_loan/models/loan_issue_line.py @@ -1,3 +1,6 @@ +# Copyright 2019 Coop IT Easy SCRL fs +# Houssine BAKKALI +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). from datetime import datetime diff --git a/easy_my_coop_loan/models/mail_template.py b/easy_my_coop_loan/models/mail_template.py deleted file mode 100644 index 12138c7..0000000 --- a/easy_my_coop_loan/models/mail_template.py +++ /dev/null @@ -1,10 +0,0 @@ -from odoo import models - - -class MailTemplate(models.Model): - _inherit = "mail.template" - -# def init(self): -# for template_id in EMAIL_TEMPLATE_IDS: -# mail_template = self.env.ref(template_id) -# mail_template.easy_my_coop = True diff --git a/easy_my_coop_loan/models/partner.py b/easy_my_coop_loan/models/partner.py index 61e3f03..dcd20f2 100644 --- a/easy_my_coop_loan/models/partner.py +++ b/easy_my_coop_loan/models/partner.py @@ -1,30 +1,29 @@ -# -*- coding: utf-8 -*- -# Copyright 2019 Coop IT Easy SCRL fs -# Robin Keunen -# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). - -from odoo import fields, models, api - - -class ResPartner(models.Model): - _inherit = "res.partner" - - loan_line_ids = fields.One2many( - comodel_name="loan.issue.line", - inverse_name="partner_id", - string="Loans", - ) - is_loaner = fields.Boolean( - string="Loaner", - compute="_compute_is_loaner", - store=True, - ) - - @api.multi - @api.depends("loan_line_ids", "loan_line_ids.state") - def _compute_is_loaner(self): - for partner in self: - loans = partner.loan_line_ids.filtered( - lambda l: l.state in ["subscribed", "waiting", "paid"] - ) - partner.is_loaner = bool(loans) +# Copyright 2019 Coop IT Easy SCRL fs +# Houssine BAKKALI +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models, api + + +class ResPartner(models.Model): + _inherit = "res.partner" + + loan_line_ids = fields.One2many( + comodel_name="loan.issue.line", + inverse_name="partner_id", + string="Loans", + ) + is_loaner = fields.Boolean( + string="Loaner", + compute="_compute_is_loaner", + store=True, + ) + + @api.multi + @api.depends("loan_line_ids", "loan_line_ids.state") + def _compute_is_loaner(self): + for partner in self: + loans = partner.loan_line_ids.filtered( + lambda l: l.state in ["subscribed", "waiting", "paid"] + ) + partner.is_loaner = bool(loans) diff --git a/easy_my_coop_loan/views/loan_view.xml b/easy_my_coop_loan/views/loan_view.xml index e3786d5..b0eb917 100644 --- a/easy_my_coop_loan/views/loan_view.xml +++ b/easy_my_coop_loan/views/loan_view.xml @@ -1,228 +1,234 @@ - - - - loan.issue.tree - loan.issue - - - - - - - - - - - - - - - - - - - loan.issue.form - loan.issue - -
-
- -
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
- - - Loans Issue Search - loan.issue - - - - - - - - - Loan Issues - loan.issue - form - tree,form - - - - Loans - loan.issue.line - form - tree,form - - - - loan_issue_line_view_tree - loan.issue.line - - - - - - - - - - - - - - - - - loan.issue.line.form - loan.issue.line - -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - - Loans Search - loan.issue.line - - - - - - - - - - - - - - - - - -
+ + + + loan.issue.tree + loan.issue + + + + + + + + + + + + + + + + + + + + loan.issue.form + loan.issue + +
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + Loans Issue Search + loan.issue + + + + + + + + + Loan Issues + loan.issue + form + tree,form + + + + Loans + loan.issue.line + form + tree,form + + + + loan_issue_line_view_tree + loan.issue.line + + + + + + + + + + + + + + + + + loan.issue.line.form + loan.issue.line + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Loans Search + loan.issue.line + + + + + + + + + + + + + + + + + +