From 1ea48e82773b1626657cd2209c99ec23ea1df038 Mon Sep 17 00:00:00 2001 From: houssine Date: Tue, 20 Aug 2019 16:57:39 +0200 Subject: [PATCH] [ADD] bond and loan issues management [ADD] bond and loan issues management module skeleton [IMP] change increase menu sequence [IMP] add models, fields and views [IMP] add xml declaration in head of file [ADD] add easy_my_coop_loan_website - WIP [IMP] add access rights [IMP] this raise inconsistency so replace id by default_code. [IMP] change import openerp to odoo [IMP] add website loan module [FIX] put website display in loan [FIX] fix import [FIX] fix function [IMP] use correct name [IMP] make the loan and bond visible [IMP] add js, field and logic to set amount limit per subscription [IMP] remove dependency on recaptcha as user is logged to subscribe [IMP] add fields [IMP] save loan issue subscription still in WIP [IMP] remove alert pop up [IMP] add dependency to easy_my_coop_website [IMP] remove force send for sub request creation email notification [IMP] add mail templates [IMP] save subscription in the corresponding loan issue. add email notif [FIX] fix loan issue line view [FIX] add related field to loan issue. It is where the data stand [IMP] move term_view up [FIX] fix js error when false is returned [FIX] fix function when loan_issue_id in None [IMP] add actions and button [FIX] fix action [FIX] fix mail template [IMP] set noupdate=1 [IMP] change order [IMP] display loan issue lines on partner form [IMP] add loan view in partner form [IMP] add face value on loan issue and line add face value on loan issue and line. add as well the quantity and computation of the amount [FIX] missing id overriding values wasn't working [IMP] getting bond face value and setting it as step. [IMP] subscribed_amount computed field is the sum of the amount lines [IMP] allow a waiting payment to be cancelled [IMP] make field required [REFACT] move loan issue line code to dedicated file [IMP] add interest calculation and model [ADD] bond and loan issues management module skeleton [IMP] add models, fields and views [IMP] allow creation by hand [IMP] adding partner related field [IMP] put code in separate function [FIX] pass it to get method [IMP] routes consistent form [FIX] fix eof [FIX] GET is working for ajax call [IMP] website page for loan issue subscription --- easy_my_coop/models/coop.py | 2 +- easy_my_coop/views/email_template_view.xml | 28 +-- easy_my_coop/views/operation_request_view.xml | 3 +- easy_my_coop/views/product_view.xml | 1 + easy_my_coop/views/res_company_view.xml | 1 + easy_my_coop/views/res_partner_view.xml | 2 +- .../views/subscription_request_view.xml | 4 +- easy_my_coop_loan/__init__.py | 1 + easy_my_coop_loan/__manifest__.py | 27 +++ easy_my_coop_loan/data/mail_template_data.xml | 112 +++++++++++ easy_my_coop_loan/models/__init__.py | 4 + easy_my_coop_loan/models/interest_line.py | 59 ++++++ easy_my_coop_loan/models/loan.py | 186 ++++++++++++++++++ easy_my_coop_loan/models/loan_issue_line.py | 95 +++++++++ easy_my_coop_loan/models/partner.py | 9 + .../security/ir.model.access.csv | 9 + easy_my_coop_loan/views/loan_view.xml | 163 +++++++++++++++ easy_my_coop_loan/views/partner_view.xml | 23 +++ easy_my_coop_loan/views/term_view.xml | 40 ++++ easy_my_coop_loan_website/__init__.py | 1 + easy_my_coop_loan_website/__manifest__.py | 26 +++ .../controllers/__init__.py | 1 + easy_my_coop_loan_website/controllers/main.py | 93 +++++++++ .../data/website_loan_data.xml | 16 ++ .../static/src/js/loan_issue.js | 23 +++ .../template/loan_issue_template.xml | 54 +++++ easy_my_coop_website/controllers/main.py | 8 +- 27 files changed, 968 insertions(+), 23 deletions(-) create mode 100644 easy_my_coop_loan/__init__.py create mode 100644 easy_my_coop_loan/__manifest__.py create mode 100644 easy_my_coop_loan/data/mail_template_data.xml create mode 100644 easy_my_coop_loan/models/__init__.py create mode 100644 easy_my_coop_loan/models/interest_line.py create mode 100644 easy_my_coop_loan/models/loan.py create mode 100644 easy_my_coop_loan/models/loan_issue_line.py create mode 100644 easy_my_coop_loan/models/partner.py create mode 100644 easy_my_coop_loan/security/ir.model.access.csv create mode 100644 easy_my_coop_loan/views/loan_view.xml create mode 100644 easy_my_coop_loan/views/partner_view.xml create mode 100644 easy_my_coop_loan/views/term_view.xml create mode 100644 easy_my_coop_loan_website/__init__.py create mode 100644 easy_my_coop_loan_website/__manifest__.py create mode 100644 easy_my_coop_loan_website/controllers/__init__.py create mode 100644 easy_my_coop_loan_website/controllers/main.py create mode 100644 easy_my_coop_loan_website/data/website_loan_data.xml create mode 100644 easy_my_coop_loan_website/static/src/js/loan_issue.js create mode 100644 easy_my_coop_loan_website/template/loan_issue_template.xml diff --git a/easy_my_coop/models/coop.py b/easy_my_coop/models/coop.py index e3c8c36..4bded84 100644 --- a/easy_my_coop/models/coop.py +++ b/easy_my_coop/models/coop.py @@ -101,7 +101,7 @@ class SubscriptionRequest(models.Model): subscr_request = super(SubscriptionRequest, self).create(vals) confirmation_mail_template = self.env.ref(mail_template, False) - confirmation_mail_template.send_mail(subscr_request.id, True) + confirmation_mail_template.send_mail(subscr_request.id) return subscr_request diff --git a/easy_my_coop/views/email_template_view.xml b/easy_my_coop/views/email_template_view.xml index 836e93b..a98d189 100644 --- a/easy_my_coop/views/email_template_view.xml +++ b/easy_my_coop/views/email_template_view.xml @@ -1,16 +1,16 @@ + - - - - - Mail Templates - mail.template - form - form,tree - - - - - - + + + + Mail Templates + mail.template + form + form,tree + + + + + diff --git a/easy_my_coop/views/operation_request_view.xml b/easy_my_coop/views/operation_request_view.xml index 2264c4f..4b7ff1f 100644 --- a/easy_my_coop/views/operation_request_view.xml +++ b/easy_my_coop/views/operation_request_view.xml @@ -1,3 +1,4 @@ + operation.request.tree @@ -102,5 +103,5 @@ - + \ No newline at end of file diff --git a/easy_my_coop/views/product_view.xml b/easy_my_coop/views/product_view.xml index 999643f..68ddfda 100644 --- a/easy_my_coop/views/product_view.xml +++ b/easy_my_coop/views/product_view.xml @@ -1,3 +1,4 @@ + product.template.share.form diff --git a/easy_my_coop/views/res_company_view.xml b/easy_my_coop/views/res_company_view.xml index 69eb547..1d64c4e 100644 --- a/easy_my_coop/views/res_company_view.xml +++ b/easy_my_coop/views/res_company_view.xml @@ -1,3 +1,4 @@ + res.company.form.easymy.coop diff --git a/easy_my_coop/views/res_partner_view.xml b/easy_my_coop/views/res_partner_view.xml index 4609bd4..dbb4d07 100644 --- a/easy_my_coop/views/res_partner_view.xml +++ b/easy_my_coop/views/res_partner_view.xml @@ -1,4 +1,4 @@ - + diff --git a/easy_my_coop/views/subscription_request_view.xml b/easy_my_coop/views/subscription_request_view.xml index 7a87bbb..421f097 100644 --- a/easy_my_coop/views/subscription_request_view.xml +++ b/easy_my_coop/views/subscription_request_view.xml @@ -1,4 +1,4 @@ - + @@ -166,7 +166,7 @@ - + share.line.form diff --git a/easy_my_coop_loan/__init__.py b/easy_my_coop_loan/__init__.py new file mode 100644 index 0000000..7f0969e --- /dev/null +++ b/easy_my_coop_loan/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/easy_my_coop_loan/__manifest__.py b/easy_my_coop_loan/__manifest__.py new file mode 100644 index 0000000..d115bb0 --- /dev/null +++ b/easy_my_coop_loan/__manifest__.py @@ -0,0 +1,27 @@ +# Copyright 2019 Coop IT Easy SCRLfs () +# - Houssine BAKKALI - +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +{ + "name": "Easy My Coop Bond and Subordinated Loan Issues", + "version": "12.0.1.0.1", + "depends": [ + "easy_my_coop", + ], + "author": "Coop IT Easy SCRLfs", + "category": "Cooperative management", + "website": "http://www.coopiteasy.be", + "license": "AGPL-3", + "description": """ + This module allows to manage the bonds and subordinated loans subscription + life cycle. + """, + 'data': [ + 'security/ir.model.access.csv', + 'views/term_view.xml', + 'views/loan_view.xml', + 'views/partner_view.xml', + 'data/mail_template_data.xml', + ], + 'installable': True, +} diff --git a/easy_my_coop_loan/data/mail_template_data.xml b/easy_my_coop_loan/data/mail_template_data.xml new file mode 100644 index 0000000..b570ed3 --- /dev/null +++ b/easy_my_coop_loan/data/mail_template_data.xml @@ -0,0 +1,112 @@ + + + + + + + Loan Subscription Confirmation Email + ${(object.company_id.coop_email_contact or object.loan_issue_id.user_id.email)|safe} + ${object.company_id.name} Loan subscription confirmation (Ref ${object.loan_issue_id.name or 'n/a'}) + ${object.partner_id.email} + ${(object.company_id.coop_email_contact or object.loan_issue_id.user_id.email)|safe} + + + ${object.partner_id.lang} + + +

Hello ${object.partner_id.name},

+ +

Your request will be soon processed by our team. If all the provided info are correct you will soon receive the payment information in another email

+ +
+

If you have any question, do not hesitate to contact us.

+
+ +

Sustainably your,

+

${object.company_id.name}.

+ + % if object.company_id.street: + ${object.company_id.street} + % endif + % if object.company_id.street2: + ${object.company_id.street2}
+ % endif + % if object.company_id.city or object.company_id.zip: + ${object.company_id.zip} ${object.company_id.city}
+ % endif + % if object.company_id.country_id: + ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}
+ % endif + % if object.company_id.phone: + Phone:  ${object.company_id.phone} + % endif + + % if object.company_id.website: + + %endif + +
+ +
+ + ]]>
+
+ + + Loan Issue Payment Request - Send by Email + ${(object.company_id.coop_email_contact or object.loan_issue_id.user_id.email)|safe} + ${object.company_id.name} Payment request (Ref ${object.loan_issue_id.name or 'n/a'}) + ${object.partner_id.id} + ${(object.company_id.coop_email_contact or object.loan_issue_id.user_id.email)|safe} + + + ${object.partner_id.lang} + + +

Hello ${object.partner_id.name},

+ +

Find here after the necessary information for the payment. We kindly remind you that your subscription will be effective only once we received the payment.

+ +

Amount: ${object.amount} ${object.loan_issue_id.company_currency_id.symbol}

+

Account number: ${object.company_id.partner_id.bank_ids[0].sanitized_acc_number}

+

Communication: ${object.loan_issue_id.name} + ${object.partner_id.name}

+ +

Sustainably your,

+

${object.company_id.name}.

+ + % if object.company_id.street: + ${object.company_id.street} + % endif + % if object.company_id.street2: + ${object.company_id.street2}
+ % endif + % if object.company_id.city or object.company_id.zip: + ${object.company_id.zip} ${object.company_id.city}
+ % endif + % if object.company_id.country_id: + ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}
+ % endif + % if object.company_id.phone: + Phone:  ${object.company_id.phone} + % endif + + % if object.company_id.website: + + %endif + +
+ +
+ + ]]>
+
+ +
+
diff --git a/easy_my_coop_loan/models/__init__.py b/easy_my_coop_loan/models/__init__.py new file mode 100644 index 0000000..d997735 --- /dev/null +++ b/easy_my_coop_loan/models/__init__.py @@ -0,0 +1,4 @@ +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 new file mode 100644 index 0000000..3e12e35 --- /dev/null +++ b/easy_my_coop_loan/models/interest_line.py @@ -0,0 +1,59 @@ +from odoo import fields, models + + +class LoanInterestLine(models.Model): + _name = '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 new file mode 100644 index 0000000..b762fc5 --- /dev/null +++ b/easy_my_coop_loan/models/loan.py @@ -0,0 +1,186 @@ +import logging + +from odoo import api, fields, models + +_logger = logging.getLogger(__name__) + + +class LoanTerm(models.Model): + _name = 'loan.term' + + name = fields.Char(string="Name", + required=True) + term = fields.Float(string="Term", + required=True) + + +class LoanIssue(models.Model): + _name = '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") + is_bond = fields.Boolean(string="Is a bond issue?") + is_loan = fields.Boolean(string="Is a subordinated loan issue?") + default_issue = fields.Boolean(string="Default issue") + subscription_start_date = fields.Date(string="Start date") + subscription_end_date = fields.Date(string="End date") + user_id = fields.Many2one('res.users', + string="Responsible") + term_date = fields.Date(string="Term date") + 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", + currency_field='company_currency_id') + maximum_amount = fields.Monetary(string="Maximum amount", + currency_field='company_currency_id') + maximum_amount_per_sub = fields.Monetary( + string="Maximum amount per subscription", + 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") + term = fields.Many2one('loan.term', + string="term of the loan") + 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 toggle_display(self): + for loan_issue in self: + loan_issue.display_on_website = not loan_issue.display_on_website + + @api.multi + def get_web_loan_issues(self, is_company): + loan_issues = self.search([ + ('is_loan', '=', True), + ('display_on_website', '=', True), + ('state', '=', 'ongoing') + ]) + if is_company is True: + return loan_issues.filtered('by_company') + else: + return loan_issues.filtered('by_individual') + + @api.multi + def get_web_bond_issues(self, is_company): + bond_issues = self.search([ + ('is_bond', '=', True), + ('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 get_web_issues(self, is_company): + issues = self.get_web_loan_issues(is_company) + issues = issues + self.get_web_bond_issues(is_company) + return issues + + @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.term.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 + 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.term.term) + if self.term.term - rounded_term > 0: + # TODO Handle this case + _logger.info("todo") diff --git a/easy_my_coop_loan/models/loan_issue_line.py b/easy_my_coop_loan/models/loan_issue_line.py new file mode 100644 index 0000000..f23193c --- /dev/null +++ b/easy_my_coop_loan/models/loan_issue_line.py @@ -0,0 +1,95 @@ + +from datetime import datetime + +from odoo import api, fields, models + + +class LoanIssueLine(models.Model): + _name = 'loan.issue.line' + _order = 'date desc, id' + + @api.multi + @api.depends('quantity', 'face_value') + def _compute_amount(self): + for line in self: + line.amount = line.face_value * line.quantity + + name = fields.Char(string="Reference") + loan_issue_id = fields.Many2one('loan.issue', + string="Loan issue", + required=True) + interest_lines = fields.One2many('loan.interest.line', + 'issue_line', + string="Interest lines") + quantity = fields.Integer(string='quantity', + required=True) + face_value = fields.Monetary(related='loan_issue_id.face_value', + currency_field='company_currency_id', + store=True, + readonly=True) + partner_id = fields.Many2one('res.partner', + string="Subscriber", + required=True) + date = fields.Date(string="Subscription date", + default=lambda self: datetime.strftime(datetime.now(), + '%Y-%m-%d'), + required=True) + amount = fields.Monetary(string="Subscribed amount", + currency_field='company_currency_id', + compute='_compute_amount', + store=True) + state = fields.Selection([('draft', 'Draft'), + ('subscribed', 'Subscribed'), + ('waiting', 'Waiting payment'), + ('paid', 'paid'), + ('cancelled', 'Cancelled'), + ('ended', 'Ended')], + string="State", + required=True, + 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', + related='loan_issue_id.company_id', + string="Company", + readonly=True) + + def create(self, vals): + mail_template = 'easy_my_coop_loan.loan_subscription_confirmation' + confirmation_mail_template = self.env.ref(mail_template, False) + + line = super(LoanIssueLine, self).create(vals) + confirmation_mail_template.send_mail(line.id) + + return line + + @api.multi + def action_draft(self): + for line in self: + line.write({'state': 'draft'}) + + @api.multi + def action_validate(self): + for line in self: + line.write({'state': 'subscribed'}) + + @api.multi + def action_request_payment(self): + mail_template = 'easy_my_coop_loan.loan_issue_payment_request' + pay_req_mail_template = self.env.ref(mail_template, False) + + for line in self: + pay_req_mail_template.send_mail(line.id) + line.write({'state': 'waiting'}) + + @api.multi + def action_cancel(self): + for line in self: + line.write({'state': 'cancelled'}) + + @api.multi + def action_paid(self): + for line in self: + line.write({'state': 'paid'}) diff --git a/easy_my_coop_loan/models/partner.py b/easy_my_coop_loan/models/partner.py new file mode 100644 index 0000000..5b6900d --- /dev/null +++ b/easy_my_coop_loan/models/partner.py @@ -0,0 +1,9 @@ +from odoo import fields, models + + +class ResPartner(models.Model): + _inherit = 'res.partner' + + loan_line_ids = fields.One2many('loan.issue.line', + 'partner_id', + string="Name") diff --git a/easy_my_coop_loan/security/ir.model.access.csv b/easy_my_coop_loan/security/ir.model.access.csv new file mode 100644 index 0000000..62b79cb --- /dev/null +++ b/easy_my_coop_loan/security/ir.model.access.csv @@ -0,0 +1,9 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_loan_issue_user,loan.issue,model_loan_issue,base.group_user,1,0,0,0 +access_loan_issue_manager,loan.issue,model_loan_issue,easy_my_coop.group_easy_my_coop_manager,1,1,1,0 +access_loan_issue_line_user,loan.issue.line,model_loan_issue_line,base.group_user,1,0,0,0 +access_loan_issue_line_manager,loan.issue.line,model_loan_issue_line,easy_my_coop.group_easy_my_coop_manager,1,1,1,0 +access_loan_term_user,loan.term,model_loan_term,base.group_user,1,0,0,0 +access_loan_term_manager,loan.term,model_loan_term,easy_my_coop.group_easy_my_coop_manager,1,1,1,0 +access_loan_interest_line_user,loan.interest.line,model_loan_interest_line,base.group_user,1,0,0,0 +access_loan_interest_line_manager,loan.interest.line,model_loan_interest_line,easy_my_coop.group_easy_my_coop_manager,1,1,1,1 \ No newline at end of file diff --git a/easy_my_coop_loan/views/loan_view.xml b/easy_my_coop_loan/views/loan_view.xml new file mode 100644 index 0000000..defe3d7 --- /dev/null +++ b/easy_my_coop_loan/views/loan_view.xml @@ -0,0 +1,163 @@ + + + + + loan.issue.tree + loan.issue + + + + + + + + + + + + + + + + + + + loan.issue.form + loan.issue + +
+
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + Loan issue + ir.actions.act_window + loan.issue + form + tree,form + + + + + + loan.issue.line.form + loan.issue.line + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
\ No newline at end of file diff --git a/easy_my_coop_loan/views/partner_view.xml b/easy_my_coop_loan/views/partner_view.xml new file mode 100644 index 0000000..60ad0f7 --- /dev/null +++ b/easy_my_coop_loan/views/partner_view.xml @@ -0,0 +1,23 @@ + + + res.partner.form.loan.issue + res.partner + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/easy_my_coop_loan/views/term_view.xml b/easy_my_coop_loan/views/term_view.xml new file mode 100644 index 0000000..ef41952 --- /dev/null +++ b/easy_my_coop_loan/views/term_view.xml @@ -0,0 +1,40 @@ + + + + loan.term.tree + loan.term + + + + + + + + + + loan.term.form + loan.term + +
+ + + + + + + + +
+
+
+ + + Loan term + ir.actions.act_window + loan.term + form + tree,form + + + +
\ No newline at end of file diff --git a/easy_my_coop_loan_website/__init__.py b/easy_my_coop_loan_website/__init__.py new file mode 100644 index 0000000..4dfcdd1 --- /dev/null +++ b/easy_my_coop_loan_website/__init__.py @@ -0,0 +1 @@ +from . import controllers diff --git a/easy_my_coop_loan_website/__manifest__.py b/easy_my_coop_loan_website/__manifest__.py new file mode 100644 index 0000000..dce93fa --- /dev/null +++ b/easy_my_coop_loan_website/__manifest__.py @@ -0,0 +1,26 @@ +# Copyright 2019 Coop IT Easy SCRLfs () +# - Houssine BAKKALI - +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +{ + "name": "Easy My Coop Loan Issues Website", + "version": "12.0.1.0.1", + "depends": [ + "easy_my_coop_loan", + "easy_my_coop_website", + "website", + ], + "author": "Coop IT Easy SCRLfs", + "category": "Cooperative management", + "website": "http://www.coopiteasy.be", + "license": "AGPL-3", + "description": """ + This module implements the subscription page for bonds and + subordinated loans. + """, + 'data': [ + 'data/website_loan_data.xml', + 'template/loan_issue_template.xml' + ], + 'installable': True, +} diff --git a/easy_my_coop_loan_website/controllers/__init__.py b/easy_my_coop_loan_website/controllers/__init__.py new file mode 100644 index 0000000..0c5c815 --- /dev/null +++ b/easy_my_coop_loan_website/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/easy_my_coop_loan_website/controllers/main.py b/easy_my_coop_loan_website/controllers/main.py new file mode 100644 index 0000000..92e0209 --- /dev/null +++ b/easy_my_coop_loan_website/controllers/main.py @@ -0,0 +1,93 @@ +from odoo import http +from odoo.http import request + +from odoo.tools.translate import _ + + +class WebsiteLoanIssueSubscription(http.Controller): + + @http.route(['/subscription/get_loan_issue'], + type='json', + auth="user", + methods=['POST'], website=True) + def get_loan_issue(self, loan_issue_id, **kw): + loan_issue_obj = request.env['loan.issue'] + if loan_issue_id: + loan_issue = loan_issue_obj.sudo().browse(int(loan_issue_id)) + return { + loan_issue.id: { + 'max_amount': loan_issue.maximum_amount_per_sub, + 'face_value': loan_issue.face_value, + } + } + else: + return False + + @http.route(['/subscription/loan_issue_form'], + type='http', auth="user", website=True) + def display_loan_issue_subscription_page(self, **kwargs): + values = {} + partner = request.env.user.partner_id + is_company = partner.is_company + + values = self.fill_values(values, is_company) + values.update(kwargs=kwargs.items()) + return request.render( + "easy_my_coop_loan_website.loanissuesubscription", + values) + + def get_loan_issues(self, is_company): + loan_obj = request.env['loan.issue'] + loan_issues = loan_obj.sudo().get_web_issues(is_company) + + return loan_issues + + def fill_values(self, values, is_company): + company = request.website.company_id + loan_issues = self.get_loan_issues(is_company) + + values['loan_issues'] = loan_issues + values['company'] = company + + if not values.get('loan_issue_id'): + for loan_issue in loan_issues: + if loan_issue.default_issue is True: + values['loan_issue_id'] = loan_issue.id + break + if not values.get('loan_issue_id', False) and loan_issues: + values['loan_issue_id'] = loan_issues[0].id + + return values + + def validation(self, loan_issue, kwargs): + sub_amount = kwargs.get('subscription_amount') + redirect = "easy_my_coop_loan_website.loanissuesubscription" + + values = {} + if not loan_issue: + values["error_msg"] = _("The selected loan issue is not found") + return request.render(redirect, values) + if sub_amount: + values["error_msg"] = _("The amount shoud be of monetary type") + return request.render(redirect, values) + return True + + @http.route(['/subscription/subscribe_loan_issue'], + type='http', + auth="user", website=True) + def loan_issue_subscription(self, **kwargs): + loan_obj = request.env['loan.issue'] + loan_obj_line = request.env['loan.issue.line'] + + loan_issue = loan_obj.sudo().browse(kwargs.get('loan_issue_id')) + partner = request.env.user.partner_id + + if self.validation(loan_issue, kwargs): + values = { + 'loan_issue_id': loan_issue.id, + 'partner_id': partner.id, + 'amount': kwargs['subscription_amount'], + 'state': 'subscribed' + } + loan_obj_line.sudo().create(values) + return request.render("easy_my_coop_website.cooperator_thanks", values) diff --git a/easy_my_coop_loan_website/data/website_loan_data.xml b/easy_my_coop_loan_website/data/website_loan_data.xml new file mode 100644 index 0000000..e0550e0 --- /dev/null +++ b/easy_my_coop_loan_website/data/website_loan_data.xml @@ -0,0 +1,16 @@ + + + + + Subscribe to loan issue + /subscription/loan_issue_form + + 65 + + + True + /subscription/loan_issue_form + + + + \ No newline at end of file diff --git a/easy_my_coop_loan_website/static/src/js/loan_issue.js b/easy_my_coop_loan_website/static/src/js/loan_issue.js new file mode 100644 index 0000000..0aecb45 --- /dev/null +++ b/easy_my_coop_loan_website/static/src/js/loan_issue.js @@ -0,0 +1,23 @@ +odoo.define('easy_my_coop_loan_website.oe_easymy_coop_loan', function (require) { +$(document).ready(function () { + "use strict"; + var ajax = require('web.ajax'); + + $('.oe_easymy_coop_loan').each(function () { + var oe_easymy_coop_loan = this; + $('#loan_issue').change(function () { + var loan_issue_id = $("#loan_issue").val(); + ajax.jsonRpc("/subscription/get_loan_issue", 'call', { + 'loan_issue_id': loan_issue_id + }) + .then(function (data) { + if (data !== false) { + $("#subscription_amount").prop('max',data[loan_issue_id].maximum_amount_per_sub); + $("#subscription_amount").prop('step',data[loan_issue_id].face_value); + } + }); + }); + $('#loan_issue').trigger('change'); + }); +}); +}); \ No newline at end of file diff --git a/easy_my_coop_loan_website/template/loan_issue_template.xml b/easy_my_coop_loan_website/template/loan_issue_template.xml new file mode 100644 index 0000000..f54e5f1 --- /dev/null +++ b/easy_my_coop_loan_website/template/loan_issue_template.xml @@ -0,0 +1,54 @@ + + + + + + \ No newline at end of file diff --git a/easy_my_coop_website/controllers/main.py b/easy_my_coop_website/controllers/main.py index 3cd7c15..1a51c46 100644 --- a/easy_my_coop_website/controllers/main.py +++ b/easy_my_coop_website/controllers/main.py @@ -2,9 +2,9 @@ import base64 from datetime import datetime import re -from openerp import http -from openerp.http import request -from openerp.tools.translate import _ +from odoo import http +from odoo.http import request +from odoo.tools.translate import _ # Only use for behavior, don't stock it _TECHNICAL = ['view_from', 'view_callback'] @@ -280,7 +280,7 @@ class WebsiteSubscription(http.Controller): max_amount = max_amount - partner.total_value if company.unmix_share_type: share = self.get_selected_share(kwargs) - if int(partner.cooperator_type) != share.id: + if partner.cooperator_type != share.default_code: values = self.fill_values(values, is_company, logged) values["error_msg"] = (_("You can't subscribe two " "different types of share"))