Browse Source
[ADD] bond and loan issues management
[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 subscriptionpull/24/head
houssine
5 years ago
committed by
robin.keunen
27 changed files with 968 additions and 23 deletions
-
2easy_my_coop/models/coop.py
-
28easy_my_coop/views/email_template_view.xml
-
3easy_my_coop/views/operation_request_view.xml
-
1easy_my_coop/views/product_view.xml
-
1easy_my_coop/views/res_company_view.xml
-
2easy_my_coop/views/res_partner_view.xml
-
4easy_my_coop/views/subscription_request_view.xml
-
1easy_my_coop_loan/__init__.py
-
27easy_my_coop_loan/__manifest__.py
-
112easy_my_coop_loan/data/mail_template_data.xml
-
4easy_my_coop_loan/models/__init__.py
-
59easy_my_coop_loan/models/interest_line.py
-
186easy_my_coop_loan/models/loan.py
-
95easy_my_coop_loan/models/loan_issue_line.py
-
9easy_my_coop_loan/models/partner.py
-
9easy_my_coop_loan/security/ir.model.access.csv
-
163easy_my_coop_loan/views/loan_view.xml
-
23easy_my_coop_loan/views/partner_view.xml
-
40easy_my_coop_loan/views/term_view.xml
-
1easy_my_coop_loan_website/__init__.py
-
26easy_my_coop_loan_website/__manifest__.py
-
1easy_my_coop_loan_website/controllers/__init__.py
-
93easy_my_coop_loan_website/controllers/main.py
-
16easy_my_coop_loan_website/data/website_loan_data.xml
-
23easy_my_coop_loan_website/static/src/js/loan_issue.js
-
54easy_my_coop_loan_website/template/loan_issue_template.xml
-
8easy_my_coop_website/controllers/main.py
@ -1,16 +1,16 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data> |
|||
<menuitem name="Configuration" id="menu_easy_my_coop_config" parent="menu_main_easy_my_coop" sequence="20"/> |
|||
|
|||
<record model="ir.actions.act_window" id="action_easy_my_coop_email_templates"> |
|||
<field name="name">Mail Templates</field> |
|||
<field name="res_model">mail.template</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form,tree</field> |
|||
<field name="view_id" ref="mail.email_template_tree" /> |
|||
<field name="search_view_id" ref="mail.view_email_template_search"/> |
|||
</record> |
|||
|
|||
<menuitem id="menu_easy_my_coop_templates" parent="menu_easy_my_coop_config" action="action_easy_my_coop_email_templates" sequence="10" groups="group_easy_my_coop_manager"/> |
|||
</data> |
|||
<menuitem name="Configuration" id="menu_easy_my_coop_config" parent="menu_main_easy_my_coop" sequence="80" /> |
|||
|
|||
<record model="ir.actions.act_window" |
|||
id="action_easy_my_coop_email_templates"> |
|||
<field name="name">Mail Templates</field> |
|||
<field name="res_model">mail.template</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form,tree</field> |
|||
<field name="view_id" ref="mail.email_template_tree" /> |
|||
<field name="search_view_id" ref="mail.view_email_template_search" /> |
|||
</record> |
|||
|
|||
<menuitem id="menu_easy_my_coop_templates" parent="menu_easy_my_coop_config" action="action_easy_my_coop_email_templates" sequence="10" groups="group_easy_my_coop_manager" /> |
|||
</odoo> |
@ -0,0 +1 @@ |
|||
from . import models |
@ -0,0 +1,27 @@ |
|||
# Copyright 2019 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 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, |
|||
} |
@ -0,0 +1,112 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Mail template are declared in a NOUPDATE block |
|||
so users can freely customize/delete them --> |
|||
<data noupdate="1"> |
|||
<!--<data>--> |
|||
<record id="loan_subscription_confirmation" model="mail.template"> |
|||
<field name="name">Loan Subscription Confirmation Email</field> |
|||
<field name="email_from">${(object.company_id.coop_email_contact or object.loan_issue_id.user_id.email)|safe}</field> |
|||
<field name="subject">${object.company_id.name} Loan subscription confirmation (Ref ${object.loan_issue_id.name or 'n/a'})</field> |
|||
<field name="email_to">${object.partner_id.email}</field> |
|||
<field name="reply_to">${(object.company_id.coop_email_contact or object.loan_issue_id.user_id.email)|safe}</field> |
|||
<field name="model_id" ref="easy_my_coop_loan.model_loan_issue_line"/> |
|||
<field name="auto_delete" eval="True"/> |
|||
<field name="lang">${object.partner_id.lang}</field> |
|||
<field name="body_html"><![CDATA[ |
|||
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; "> |
|||
|
|||
<p>Hello ${object.partner_id.name},</p> |
|||
|
|||
<p>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</p> |
|||
|
|||
<br/> |
|||
<p>If you have any question, do not hesitate to contact us.</p> |
|||
<br/> |
|||
|
|||
<p>Sustainably your,</p> |
|||
<p>${object.company_id.name}.</p> |
|||
|
|||
% if object.company_id.street: |
|||
${object.company_id.street} |
|||
% endif |
|||
% if object.company_id.street2: |
|||
${object.company_id.street2}<br/> |
|||
% endif |
|||
% if object.company_id.city or object.company_id.zip: |
|||
${object.company_id.zip} ${object.company_id.city}<br/> |
|||
% 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 ''}<br/> |
|||
% endif |
|||
% if object.company_id.phone: |
|||
Phone: ${object.company_id.phone} |
|||
% endif |
|||
|
|||
% if object.company_id.website: |
|||
<div> |
|||
Web : <a href="${object.company_id.website}">${object.company_id.website}</a> |
|||
</div> |
|||
%endif |
|||
|
|||
<div> |
|||
<img src=${object.company_id.logo_url}> |
|||
</div> |
|||
</div> |
|||
]]></field> |
|||
</record> |
|||
<!--Request the payment of the subscribed loan issue --> |
|||
<record id="loan_issue_payment_request" model="mail.template"> |
|||
<field name="name">Loan Issue Payment Request - Send by Email</field> |
|||
<field name="email_from">${(object.company_id.coop_email_contact or object.loan_issue_id.user_id.email)|safe}</field> |
|||
<field name="subject">${object.company_id.name} Payment request (Ref ${object.loan_issue_id.name or 'n/a'})</field> |
|||
<field name="partner_to">${object.partner_id.id}</field> |
|||
<field name="reply_to">${(object.company_id.coop_email_contact or object.loan_issue_id.user_id.email)|safe}</field> |
|||
<field name="model_id" ref="easy_my_coop_loan.model_loan_issue_line"/> |
|||
<field name="auto_delete" eval="True"/> |
|||
<field name="lang">${object.partner_id.lang}</field> |
|||
<field name="body_html"><![CDATA[ |
|||
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; "> |
|||
|
|||
<p>Hello ${object.partner_id.name},</p> |
|||
|
|||
<p>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.</p> |
|||
|
|||
<p>Amount: ${object.amount} ${object.loan_issue_id.company_currency_id.symbol}</p> |
|||
<p>Account number: ${object.company_id.partner_id.bank_ids[0].sanitized_acc_number}</p> |
|||
<p>Communication: ${object.loan_issue_id.name} + ${object.partner_id.name}</p> |
|||
|
|||
<p>Sustainably your,</p> |
|||
<p>${object.company_id.name}.</p> |
|||
|
|||
% if object.company_id.street: |
|||
${object.company_id.street} |
|||
% endif |
|||
% if object.company_id.street2: |
|||
${object.company_id.street2}<br/> |
|||
% endif |
|||
% if object.company_id.city or object.company_id.zip: |
|||
${object.company_id.zip} ${object.company_id.city}<br/> |
|||
% 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 ''}<br/> |
|||
% endif |
|||
% if object.company_id.phone: |
|||
Phone: ${object.company_id.phone} |
|||
% endif |
|||
|
|||
% if object.company_id.website: |
|||
<div> |
|||
Web : <a href="${object.company_id.website}">${object.company_id.website}</a> |
|||
</div> |
|||
%endif |
|||
|
|||
<div> |
|||
<img src=${object.company_id.logo_url}> |
|||
</div> |
|||
</div> |
|||
]]></field> |
|||
</record> |
|||
|
|||
</data> |
|||
</odoo> |
@ -0,0 +1,4 @@ |
|||
from . import loan |
|||
from . import loan_issue_line |
|||
from . import interest_line |
|||
from . import partner |
@ -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") |
@ -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") |
@ -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'}) |
@ -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") |
@ -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 |
@ -0,0 +1,163 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<menuitem name="Loan Issue" id="menu_easy_my_coop_main_loan_issue" parent="easy_my_coop.menu_main_easy_my_coop" sequence="20" groups="easy_my_coop.group_easy_my_coop_user"/> |
|||
<record id="view_loan_issue_tree" model="ir.ui.view"> |
|||
<field name="name">loan.issue.tree</field> |
|||
<field name="model">loan.issue</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Loan issues"> |
|||
<field name="name" /> |
|||
<field name="subscription_start_date" /> |
|||
<field name="subscription_end_date" /> |
|||
<field name="term_date" /> |
|||
<field name="term" /> |
|||
<field name="rate" /> |
|||
<field name="minimum_amount" /> |
|||
<field name="maximum_amount" /> |
|||
<field name="subscribed_amount" /> |
|||
<field name="user_id" /> |
|||
<field name="state" /> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_loan_issue_form" model="ir.ui.view"> |
|||
<field name="name">loan.issue.form</field> |
|||
<field name="model">loan.issue</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Loan issue"> |
|||
<header> |
|||
<button name="action_confirm" string="Confirm" type="object" states="draft" |
|||
groups="easy_my_coop.group_easy_my_coop_manager"/> |
|||
<button name="action_cancel" string="Cancel" type="object" states="draft,ongoing" |
|||
confirm="Are you sure you want to cancel this loan issue?" |
|||
groups="easy_my_coop.group_easy_my_coop_manager"/> |
|||
<button name="action_open" string="Open" type="object" |
|||
states="confirmed" groups="easy_my_coop.group_easy_my_coop_manager"/> |
|||
<button name="action_close" string="Close" type="object" states="ongoing" |
|||
confirm="Are you sure you want to close this loan issue?" |
|||
groups="easy_my_coop.group_easy_my_coop_manager"/> |
|||
<button name="action_draft" string="Set to draft" |
|||
type="object" states="confirmed,cancelled" |
|||
groups="easy_my_coop.group_easy_my_coop_manager"/> |
|||
<button name="compute_loan_interest" string="Compute interest" |
|||
type="object" states="closed,ongoing" |
|||
groups="easy_my_coop.group_easy_my_coop_manager"/> |
|||
|
|||
<field name="state" widget="statusbar" statusbar_visible="draft,confirmed,ongoing,closed"/> |
|||
</header> |
|||
<sheet> |
|||
<div class="oe_button_box" name="button_box"> |
|||
<button name="toggle_display" type="object" |
|||
class="oe_stat_button" icon="fa-globe"> |
|||
<field name="display_on_website" widget="website_button"/> |
|||
</button> |
|||
</div> |
|||
<group> |
|||
<group> |
|||
<field name="name" /> |
|||
<field name="is_loan" /> |
|||
<field name="is_bond" /> |
|||
<field name="default_issue" /> |
|||
<field name="face_value" /> |
|||
<field name="minimum_amount" /> |
|||
<field name="maximum_amount" /> |
|||
<field name="maximum_amount_per_sub" /> |
|||
<field name="subscribed_amount" /> |
|||
<field name="by_individual" /> |
|||
<field name="by_company" /> |
|||
</group> |
|||
<group> |
|||
<field name="user_id" widget="selection" /> |
|||
<field name="rate" /> |
|||
<field name="taxes_rate" /> |
|||
<field name="subscription_start_date" /> |
|||
<field name="subscription_end_date" /> |
|||
<field name="term_date" /> |
|||
<field name="term" widget="selection"/> |
|||
<field name="interest_payment" widget="selection" /> |
|||
</group> |
|||
</group> |
|||
<notebook> |
|||
<page string="Lines"> |
|||
<field name="loan_issue_lines"> |
|||
<tree delete="false"> |
|||
<field name="name" /> |
|||
<field name="partner_id" /> |
|||
<field name="date" /> |
|||
<field name="quantity" /> |
|||
<field name="face_value" /> |
|||
<field name="amount" /> |
|||
<field name="state" /> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_loan_issue" model="ir.actions.act_window"> |
|||
<field name="name">Loan issue</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">loan.issue</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
|
|||
<menuitem action="action_loan_issue" id="loan_issue_menu" parent="menu_easy_my_coop_main_loan_issue" sequence="25" /> |
|||
|
|||
<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 issue"> |
|||
<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_cancel" string="Cancel" type="object" |
|||
states="draft,subscribed,waiting" |
|||
confirm="Are you sure you want to cancel this loan subscription ?" /> |
|||
<button name="action_draft" string="Set to draft" |
|||
type="object" states="cancelled" /> |
|||
<button name="action_paid" string="Paid" |
|||
type="object" states="waiting" /> |
|||
<field name="state" widget="statusbar" /> |
|||
</header> |
|||
<sheet> |
|||
<group> |
|||
<group> |
|||
<field name="name" /> |
|||
<field name="quantity" /> |
|||
<field name="face_value" /> |
|||
</group> |
|||
<group> |
|||
<field name="date" /> |
|||
<field name="partner_id" /> |
|||
<field name="amount" /> |
|||
</group> |
|||
</group> |
|||
<notebook> |
|||
<page string="Interst 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="net_interest" /> |
|||
<field name="taxes_amount" /> |
|||
<field name="due_date" /> |
|||
<field name="state" /> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,23 @@ |
|||
<odoo> |
|||
<record id="view_partner_form_loan_issue" model="ir.ui.view"> |
|||
<field name="name">res.partner.form.loan.issue</field> |
|||
<field name="model">res.partner</field> |
|||
<field name="inherit_id" ref="easy_my_coop.view_partner_form_easy_my_coop"/> |
|||
<field name="arch" type="xml"> |
|||
<page name="share_subscription" position="after"> |
|||
<page string="Loan issue lines" name="loan_issue_lines" groups="easy_my_coop.group_easy_my_coop_user"> |
|||
<field name="loan_line_ids"> |
|||
<tree create="false" delete="false" edit="false"> |
|||
<field name="loan_issue_id"/> |
|||
<field name="date"/> |
|||
<field name="quantity"/> |
|||
<field name="face_value"/> |
|||
<field name="amount"/> |
|||
<field name="state"/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
</page> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,40 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<record id="view_loan_term_tree" model="ir.ui.view"> |
|||
<field name="name">loan.term.tree</field> |
|||
<field name="model">loan.term</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Loan terms"> |
|||
<field name="name" /> |
|||
<field name="term" /> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_loan_term_form" model="ir.ui.view"> |
|||
<field name="name">loan.term.form</field> |
|||
<field name="model">loan.term</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Loan terms"> |
|||
<group> |
|||
<group> |
|||
<field name="name" /> |
|||
</group> |
|||
<group> |
|||
<field name="term" /> |
|||
</group> |
|||
</group> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_loan_term" model="ir.actions.act_window"> |
|||
<field name="name">Loan term</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">loan.term</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
|
|||
<menuitem action="action_loan_term" id="loan_term_menu" parent="easy_my_coop.menu_easy_my_coop_config" sequence="5" /> |
|||
</odoo> |
@ -0,0 +1 @@ |
|||
from . import controllers |
@ -0,0 +1,26 @@ |
|||
# Copyright 2019 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 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, |
|||
} |
@ -0,0 +1 @@ |
|||
from . import main |
@ -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) |
@ -0,0 +1,16 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data> |
|||
<record id="menu_subscribeloanissue" model="website.menu"> |
|||
<field name="name">Subscribe to loan issue</field> |
|||
<field name="url">/subscription/loan_issue_form</field> |
|||
<field name="parent_id" ref="website.main_menu"/> |
|||
<field name="sequence" type="int">65</field> |
|||
</record> |
|||
<record id="subscribe_loan_issue_page" model="website.page"> |
|||
<field name="website_published">True</field> |
|||
<field name="url">/subscription/loan_issue_form</field> |
|||
<field name="view_id" ref="menu_subscribeloanissue"/> |
|||
</record> |
|||
</data> |
|||
</odoo> |
@ -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'); |
|||
}); |
|||
}); |
|||
}); |
@ -0,0 +1,54 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<template id="assets_frontend" inherit_id="web.assets_frontend" name="Coop"> |
|||
<xpath expr="." position="inside"> |
|||
<script type="text/javascript" src="/easy_my_coop_loan_website/static/src/js/loan_issue.js"></script> |
|||
</xpath> |
|||
</template> |
|||
|
|||
<template id="loanissuesubscription" name="Loan Issue Subscription"> |
|||
<t t-call="website.layout"> |
|||
<div id="wrap"> |
|||
<div class="oe_structure"/> |
|||
<div class="container oe_easymy_coop_loan"> |
|||
<h2 class="energie">Subscribe to Loan Issue</h2><br/> |
|||
<div class="row"> |
|||
<div class="col-md-8"> |
|||
<form action="/subscription/subscribe_loan_issue" method="post" class="form-horizontal mt32" enctype="multipart/form-data"> |
|||
<p style="color:red;"><t t-esc="error_msg"/></p> |
|||
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/> |
|||
|
|||
<div t-attf-class="form-group #{error and 'loan_issue_id' in error and 'has-error' or ''}"> |
|||
<label class="col-md-3 col-sm-4 control-label" style="width:25%" for="share_product_id">Loan issue</label> |
|||
<select id="loan_issue" name="loan_issue_id" class="col-md-7 col-sm-8 form-control" style="width:54%;margin-left:15px"> |
|||
<t t-foreach="loan_issues or []" t-as="loan_issue"> |
|||
<option t-att-value="loan_issue.id" t-att-selected="loan_issue.id == int(loan_issue_id)"><t t-esc="loan_issue.name"/></option> |
|||
</t> |
|||
</select> |
|||
</div> |
|||
<div t-attf-class="form-group #{error and 'subscription_amount' in error and 'has-error' or ''}"> |
|||
<label class="col-md-3 col-sm-4 control-label" style="width:25%" for="subscription_amount">Amount</label> |
|||
<input id="subscription_amount" type="number" class="col-md-7 col-sm-8 form-control total" name="subscription_amount" min="0" step="100" max="5000"/> |
|||
</div> |
|||
<table style="margin-left:195px"> |
|||
<tr> |
|||
<!--<td width="80%"> |
|||
<div class="g-recaptcha" t-att-data-sitekey="website.recaptcha_key_site" data-theme="green"/><br/> |
|||
</td>--> |
|||
<td> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-3 col-sm-offset-4 col-sm-8 col-md-7"> |
|||
<button class="btn btn-primary btn-lg">Send</button> |
|||
</div> |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
</table> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
</template> |
|||
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue