@ -0,0 +1,36 @@ |
|||
Subscription Package for Community |
|||
================================== |
|||
* Subscription Package for Odoo 15 community edition |
|||
|
|||
Installation |
|||
============ |
|||
- www.odoo.com/documentation/15.0/setup/install.html |
|||
- Install our custom addon |
|||
|
|||
Company |
|||
------- |
|||
* 'Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
|||
|
|||
Contacts |
|||
-------- |
|||
* Mail Contact : odoo@cybrosys.com |
|||
* Website : https://cybrosys.com |
|||
|
|||
Credits |
|||
-------- |
|||
* Developer: Amal Prasad @ Cybrosys, |
|||
Alakananda @ Cybrosys |
|||
|
|||
Bug Tracker |
|||
----------- |
|||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. |
|||
|
|||
Maintainer |
|||
========== |
|||
This module is maintained by Cybrosys Technologies. |
|||
|
|||
For support and more information, please visit https://www.cybrosys.com |
|||
|
|||
Further information |
|||
=================== |
|||
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,25 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from . import models |
|||
from . import report |
|||
from . import wizard |
@ -0,0 +1,57 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies (<https://www.cybrosys.com>). |
|||
# Author: Cybrosys Techno Solutions (<https://www.cybrosys.com>) |
|||
# |
|||
# This program is free software: you can modify |
|||
# it under the terms of the GNU Affero General Public License (AGPL) as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################### |
|||
|
|||
{ |
|||
'name': 'Subscription Management For Community', |
|||
'Version': '15.0.1.0.0', |
|||
'summary': 'Subscription Package Management Module For Odoo15 Community', |
|||
'description': 'Subscription Package Management Module For Odoo15 Community', |
|||
'category': 'Sales', |
|||
'author': 'Cybrosys Techno solutions', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'maintainer': 'Cybrosys Techno Solutions', |
|||
'website': "https://www.cybrosys.com", |
|||
'depends': ['base', 'sale_management'], |
|||
'data': [ |
|||
'security/security.xml', |
|||
'security/ir.model.access.csv', |
|||
'data/uom_demo.xml', |
|||
'data/subscription_stage_data.xml', |
|||
'data/mail_template.xml', |
|||
'data/cron.xml', |
|||
'wizard/subscription_close_wizard.xml', |
|||
'views/subscription_package.xml', |
|||
'views/subscription_products.xml', |
|||
'views/subscription_plan.xml', |
|||
'views/subscription_stage.xml', |
|||
'views/subscription_close.xml', |
|||
'views/subscription_renew.xml', |
|||
'views/mail_activity_views.xml', |
|||
'views/res_partner.xml', |
|||
'report/subscription_report_view.xml', |
|||
], |
|||
'images': ['static/description/banner.png'], |
|||
'license': 'AGPL-3', |
|||
'installable': True, |
|||
'application': True, |
|||
'auto_install': False, |
|||
} |
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Cron Jobs --> |
|||
<record id="close_limit_cron" model="ir.cron"> |
|||
<field name="name">Check Close Limit</field> |
|||
<field name="model_id" ref="model_subscription_package"/> |
|||
<field name="state">code</field> |
|||
<field name="code">model.close_limit_cron()</field> |
|||
<field name='interval_number'>1</field> |
|||
<field name='interval_type'>days</field> |
|||
<field name="numbercall">-1</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,56 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Email Templates --> |
|||
<record id="mail_template_subscription_renew" model="mail.template"> |
|||
<field name="name">Subscription: Email Renew Alert</field> |
|||
<field name="model_id" ref="subscription_package.model_subscription_package"/> |
|||
<field name="subject">{{ object.company_id.name }}: Please check the subscription {{ object.name }}</field> |
|||
<field name="email_from">{{ object.company_id.email }}</field> |
|||
<field name="email_to">{{ object.partner_id.email }}</field> |
|||
<field name="auto_delete" eval="True"/> |
|||
<field name="lang">{{ object.partner_id.lang }}</field> |
|||
<field name="body_html" type="html"> |
|||
<div style="background:#F0F0F0;color:#515166;padding:10px 0px;font-family:Arial,Helvetica,sans-serif;font-size:14px;"> |
|||
<table style="width:600px;margin:5px auto;"> |
|||
<tbody> |
|||
<tr> |
|||
<td> |
|||
<a href="/"> |
|||
<img src="/web/binary/company_logo" |
|||
style="vertical-align:baseline;max-width:100px;"/> |
|||
</a> |
|||
</td> |
|||
<td style="text-align:right;vertical-align:middle;"> |
|||
Subscription Renew Alert |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
<table style="width:600px;margin:0px auto;background:white;border:1px solid #e1e1e1;"> |
|||
<tbody> |
|||
<tr> |
|||
<td style="padding:15px 20px 10px 20px;"> |
|||
<p>Dear<t t-out="object.partner_id.name or ''"/>, |
|||
</p> |
|||
<p>Your subscription Plan |
|||
<strong t-out="object.name or ''"/> |
|||
is going to Expired on |
|||
<strong t-out="object.close_date or ''"/>. |
|||
</p> |
|||
<p>If you have some concerns about it, please contact your contact person |
|||
<t |
|||
t-out="object.company_id.name or ''"/> |
|||
or reply to this email. |
|||
</p> |
|||
<p>Kind regards.</p> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,25 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data noupdate="1"> |
|||
|
|||
<record model="subscription.package.stage" id="draft_stage"> |
|||
<field name="name">Draft</field> |
|||
<field name="sequence">5</field> |
|||
<field name="category">draft</field> |
|||
</record> |
|||
|
|||
<record model="subscription.package.stage" id="progress_stage"> |
|||
<field name="name">In Progress</field> |
|||
<field name="sequence">10</field> |
|||
<field name="category">progress</field> |
|||
</record> |
|||
|
|||
<record model="subscription.package.stage" id="closed_stage"> |
|||
<field name="name">Closed</field> |
|||
<field name="sequence">15</field> |
|||
<field name="fold" eval="True"/> |
|||
<field name="category">closed</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</odoo> |
@ -0,0 +1,24 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data noupdate="1"> |
|||
|
|||
<record id="uom_categ_time" model="uom.category"> |
|||
<field name="name">Time</field> |
|||
</record> |
|||
|
|||
<record id="product_uom_months" model="uom.uom"> |
|||
<field name="category_id" ref="uom_categ_time"/> |
|||
<field name="name">Months</field> |
|||
<field name="factor_inv" eval="1"/> |
|||
<field name="uom_type">reference</field> |
|||
</record> |
|||
|
|||
<record id="product_uom_years" model="uom.uom"> |
|||
<field name="category_id" ref="uom_categ_time"/> |
|||
<field name="name">Years</field> |
|||
<field name="factor_inv" eval="12"/> |
|||
<field name="uom_type">bigger</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</odoo> |
@ -0,0 +1,29 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from . import subscription_plan |
|||
from . import subscription_stage |
|||
from . import subscription_package |
|||
from . import subscription_products |
|||
from . import subscription_close |
|||
from . import subscription_renew |
|||
from . import res_partner |
@ -0,0 +1,34 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from odoo import fields, models |
|||
|
|||
|
|||
class Partner(models.Model): |
|||
_inherit = 'res.partner' |
|||
|
|||
active_subscription = fields.Boolean(string="Active Subscription", |
|||
default=False) |
|||
subscription_product_line_ids = fields.One2many('subscription.package.product.line', |
|||
'res_partner_id', |
|||
ondelete='restrict', |
|||
string='Products Line') |
@ -0,0 +1,33 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from odoo import models, fields |
|||
|
|||
|
|||
class SubscriptionPackageStopReason(models.Model): |
|||
_name = "subscription.package.stop" |
|||
_description = "Subscription Package Stop Reason" |
|||
_order = 'sequence' |
|||
|
|||
sequence = fields.Integer(help="Determine the display order", index=True, |
|||
string='Sequence') |
|||
name = fields.Char(string='Reason', required=True) |
@ -0,0 +1,386 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from odoo import _, api, models, fields, SUPERUSER_ID |
|||
import datetime |
|||
from odoo.exceptions import UserError |
|||
from dateutil.relativedelta import relativedelta |
|||
|
|||
|
|||
class SubscriptionPackageProductLine(models.Model): |
|||
_name = 'subscription.package.product.line' |
|||
_description = 'Subscription Product Lines' |
|||
|
|||
subscription_id = fields.Many2one('subscription.package', store=True, |
|||
string='Subscription') |
|||
company_id = fields.Many2one('res.company', string='Company', store=True, |
|||
related='subscription_id.company_id') |
|||
create_date = fields.Datetime(string='Create date', store=True, |
|||
default=fields.Datetime.now) |
|||
user_id = fields.Many2one('res.users', string='Salesperson', store=True, |
|||
related='subscription_id.user_id') |
|||
product_id = fields.Many2one('product.product', string='Product', |
|||
store=True, ondelete='restrict', |
|||
domain=[('is_subscription', '=', True)]) |
|||
product_qty = fields.Float(string='Quantity', store=True, default=1.0) |
|||
product_uom_id = fields.Many2one('uom.uom', string='UoM', store=True, |
|||
related='product_id.uom_id', |
|||
ondelete='restrict') |
|||
uom_catg_id = fields.Many2one('uom.category', string='UoM', store=True, |
|||
related='product_id.uom_id.category_id') |
|||
unit_price = fields.Float(string='Unit Price', store=True, readonly=False, |
|||
related='product_id.list_price') |
|||
currency_id = fields.Many2one('res.currency', string='Currency', |
|||
store=True, |
|||
related='subscription_id.currency_id') |
|||
total_amount = fields.Monetary(string='Subtotal', store=True, |
|||
compute='_compute_total_amount') |
|||
sequence = fields.Integer('Sequence', help="Determine the display order", |
|||
index=True) |
|||
res_partner_id = fields.Many2one('res.partner', string='Currency', |
|||
store=True, |
|||
related='subscription_id.partner_id') |
|||
|
|||
@api.depends('product_qty', 'unit_price') |
|||
def _compute_total_amount(self): |
|||
""" Calculate subtotal amount of product line """ |
|||
for rec in self: |
|||
if rec.product_id: |
|||
rec.total_amount = rec.unit_price * rec.product_qty |
|||
|
|||
|
|||
class SubscriptionPackage(models.Model): |
|||
_name = 'subscription.package' |
|||
_description = 'Subscription Package' |
|||
_rec_name = 'name' |
|||
_inherit = ['mail.thread', 'mail.activity.mixin'] |
|||
|
|||
@api.model |
|||
def _read_group_stage_ids(self, categories, domain, order): |
|||
""" Read all the stages and display it in the kanban view, |
|||
even if it is empty.""" |
|||
category_ids = categories._search([], order=order, |
|||
access_rights_uid=SUPERUSER_ID) |
|||
return categories.browse(category_ids) |
|||
|
|||
def _default_stage_id(self): |
|||
"""Setting default stage""" |
|||
rec = self.env['subscription.package.stage'].search([], limit=1, |
|||
order='sequence ASC') |
|||
return rec.id if rec else None |
|||
|
|||
name = fields.Char(string='Name', default="New", compute='_compute_name', |
|||
store=True, required=True) |
|||
partner_id = fields.Many2one('res.partner', string='Customer', store=True) |
|||
partner_invoice_id = fields.Many2one('res.partner', |
|||
string='Invoice Address', |
|||
related='partner_id', readonly=False) |
|||
partner_shipping_id = fields.Many2one('res.partner', |
|||
string='Shipping/Service Address', |
|||
related='partner_id', |
|||
readonly=False) |
|||
plan_id = fields.Many2one('subscription.package.plan', |
|||
string='Subscription Plan') |
|||
start_date = fields.Date(string='Start Date', store=True, |
|||
ondelete='restrict') |
|||
next_invoice_date = fields.Date(string='Next Invoice Date', readonly=False, |
|||
store=True, |
|||
compute="_compute_next_invoice_date") |
|||
company_id = fields.Many2one('res.company', string='Company', |
|||
default=lambda self: self.env.company, |
|||
required=True) |
|||
user_id = fields.Many2one('res.users', string='Sales Person', |
|||
default=lambda self: self.env.user) |
|||
sale_order = fields.Many2one('sale.order', string="Sale Order") |
|||
to_renew = fields.Boolean(string='To Renew', default=False) |
|||
tag_ids = fields.Many2many('account.analytic.tag', string='Tags') |
|||
stage_id = fields.Many2one('subscription.package.stage', string='Stage', |
|||
default=lambda self: self._default_stage_id(), |
|||
index=True, |
|||
group_expand='_read_group_stage_ids') |
|||
invoice_count = fields.Integer(string='Invoices', |
|||
compute='_compute_invoice_count') |
|||
so_count = fields.Integer(string='Sales', compute='_compute_sale_count') |
|||
description = fields.Text(string='Description') |
|||
analytic_account_id = fields.Many2one('account.analytic.account', |
|||
string='Analytic Account') |
|||
product_line_ids = fields.One2many('subscription.package.product.line', |
|||
'subscription_id', ondelete='restrict', |
|||
string='Products Line') |
|||
currency_id = fields.Many2one('res.currency', string='Currency', |
|||
readonly=True, |
|||
default=lambda |
|||
self: self.env.company.currency_id) |
|||
current_stage = fields.Char(string='Current Stage', default='Draft', |
|||
store=True, compute='_compute_current_stage') |
|||
reference_code = fields.Char(string='Reference', store=True) |
|||
is_closed = fields.Boolean(string="Closed", default=False) |
|||
close_reason = fields.Many2one('subscription.package.stop', |
|||
string='Close Reason') |
|||
closed_by = fields.Many2one('res.users', string='Closed By') |
|||
close_date = fields.Date(string='Closed on') |
|||
stage_category = fields.Selection(related='stage_id.category', store=True) |
|||
invoice_mode = fields.Selection(related="plan_id.invoice_mode") |
|||
total_recurring_price = fields.Float(string='Recurring Price', |
|||
compute='_compute_total_recurring_price', |
|||
store=True) |
|||
|
|||
@api.depends('invoice_count') |
|||
def _compute_invoice_count(self): |
|||
""" Calculate Invoice count based on subscription package """ |
|||
invoice_count = self.env['account.move'].search_count( |
|||
[('subscription_id', '=', self.id)]) |
|||
if invoice_count > 0: |
|||
self.invoice_count = invoice_count |
|||
else: |
|||
self.invoice_count = 0 |
|||
|
|||
@api.depends('so_count') |
|||
def _compute_sale_count(self): |
|||
""" Calculate sale order count based on subscription package """ |
|||
self.so_count = self.env['sale.order'].search_count( |
|||
[('subscription_id', '=', self.id)]) |
|||
|
|||
@api.depends('stage_id') |
|||
def _compute_current_stage(self): |
|||
""" It displays current stage for subscription package """ |
|||
for rec in self: |
|||
rec.current_stage = rec.env['subscription.package.stage'].search( |
|||
[('id', '=', rec.stage_id.id)]).category |
|||
|
|||
@api.depends('start_date') |
|||
def _compute_next_invoice_date(self): |
|||
pending_subscriptions = self.env['subscription.package'].search( |
|||
[('stage_category', '=', 'progress')]) |
|||
for sub in pending_subscriptions: |
|||
if sub.start_date: |
|||
sub.next_invoice_date = sub.start_date + relativedelta( |
|||
days=sub.plan_id.renewal_time) |
|||
|
|||
def button_invoice_count(self): |
|||
""" It displays invoice based on subscription package """ |
|||
return { |
|||
'name': 'Invoices', |
|||
'domain': [('subscription_id', '=', self.id)], |
|||
'view_type': 'form', |
|||
'res_model': 'account.move', |
|||
'view_mode': 'tree,form', |
|||
'type': 'ir.actions.act_window', |
|||
'context': { |
|||
"create": False |
|||
} |
|||
} |
|||
|
|||
def button_sale_count(self): |
|||
""" It displays sale order based on subscription package """ |
|||
return { |
|||
'name': 'Products', |
|||
'domain': [('subscription_id', '=', self.id)], |
|||
'view_type': 'form', |
|||
'res_model': 'sale.order', |
|||
'view_mode': 'tree,form', |
|||
'type': 'ir.actions.act_window', |
|||
'context': { |
|||
"create": False |
|||
} |
|||
} |
|||
|
|||
def button_close(self): |
|||
""" Button for subscription close wizard """ |
|||
return { |
|||
'name': "Subscription Close Reason", |
|||
'type': 'ir.actions.act_window', |
|||
'view_type': 'form', |
|||
'view_mode': 'form', |
|||
'res_model': 'subscription.close.wizard', |
|||
'target': 'new' |
|||
} |
|||
|
|||
def button_payment(self): |
|||
""" Button to create invoice for subscription package""" |
|||
this_products_line = [] |
|||
for rec in self.product_line_ids: |
|||
rec_list = [0, 0, {'product_id': rec.product_id.id, |
|||
'quantity': rec.product_qty}] |
|||
this_products_line.append(rec_list) |
|||
invoices = self.env['account.move'].search([('subscription_id', '=', self.id), ('state', '=', 'draft')]) |
|||
orders = self.env['sale.order'].search([('subscription_id', '=', self.id), ('invoice_status', '=', 'no')]) |
|||
if invoices: |
|||
for invoice in invoices: |
|||
invoice.action_post() |
|||
if orders and invoices: |
|||
for order in orders: |
|||
order.action_confirm() |
|||
for invoice in invoices: |
|||
invoice.action_post() |
|||
out_invoice = self.env['account.move'].create( |
|||
{ |
|||
'move_type': 'out_invoice', |
|||
'date': fields.Date.today(), |
|||
'invoice_date': fields.Date.today(), |
|||
'partner_id': self.partner_invoice_id.id, |
|||
'currency_id': self.partner_invoice_id.currency_id.id, |
|||
'invoice_line_ids': this_products_line |
|||
}) |
|||
self.env['account.move'].payment_id = out_invoice.id |
|||
if self.stage_category == 'progress': |
|||
values = {'start_date': datetime.datetime.today()} |
|||
self.write(values) |
|||
return { |
|||
'name': 'Subscription Payment', |
|||
'type': 'ir.actions.act_window', |
|||
'res_model': 'account.move', |
|||
'view_mode': 'form', |
|||
'res_id': out_invoice.id |
|||
} |
|||
|
|||
def button_start_date(self): |
|||
"""Button to start subscription package""" |
|||
if not self.start_date: |
|||
self.start_date = datetime.date.today() |
|||
for rec in self: |
|||
if len(rec.env['subscription.package.stage'].search([('category', '=', 'draft')])) > 1: |
|||
raise UserError( |
|||
_('More than one stage is having category "Draft". ' |
|||
'Please change category of stage to "In Progress", ' |
|||
'only one stage is allowed to have category "Draft"')) |
|||
else: |
|||
rec.write( |
|||
{'stage_id': (rec.env['subscription.package.stage'].search([ |
|||
('category', '=', 'draft')]).id) + 1}) |
|||
|
|||
def button_sale_order(self): |
|||
"""Button to create sale order""" |
|||
this_products_line = [] |
|||
for rec in self.product_line_ids: |
|||
rec_list = [0, 0, {'product_id': rec.product_id.id, |
|||
'product_uom_qty': rec.product_qty}] |
|||
this_products_line.append(rec_list) |
|||
# for order in self.sale_order: |
|||
orders = self.env['sale.order'].search([('subscription_id', '=', self.id), ('invoice_status', '=', 'no')]) |
|||
if orders: |
|||
for order in orders: |
|||
order.action_confirm() |
|||
so_id = self.env['sale.order'].create({ |
|||
'partner_id': self.partner_id.id, |
|||
'partner_invoice_id': self.partner_id.id, |
|||
'partner_shipping_id': self.partner_id.id, |
|||
'is_subscription': True, |
|||
'subscription_id': self.id, |
|||
'order_line': this_products_line |
|||
}) |
|||
self.sale_order = so_id |
|||
return { |
|||
'name': _('Sales Orders'), |
|||
'type': 'ir.actions.act_window', |
|||
'res_model': 'sale.order', |
|||
'domain': [('id', '=', so_id.id)], |
|||
'view_mode': 'tree,form' |
|||
} |
|||
|
|||
@api.model |
|||
def create(self, vals): |
|||
"""It displays subscription product in partner and generate sequence""" |
|||
partner = self.env['res.partner'].search( |
|||
[('id', '=', vals.get('partner_id'))]) |
|||
partner.active_subscription = True |
|||
if vals.get('reference_code', 'New') is False: |
|||
vals['reference_code'] = self.env['ir.sequence'].next_by_code( |
|||
'sequence.reference.code') or 'New' |
|||
create_id = super(SubscriptionPackage, self).create(vals) |
|||
return create_id |
|||
|
|||
@api.depends('reference_code') |
|||
def _compute_name(self): |
|||
"""It displays record name as combination of short code, reference |
|||
code and partner name """ |
|||
plan_id = self.env['subscription.package.plan'].search( |
|||
[('id', '=', self.plan_id.id)]) |
|||
if plan_id.short_code and self.reference_code: |
|||
self.name = plan_id.short_code + '/' + self.reference_code + '-' + self.partner_id.name |
|||
|
|||
def set_close(self): |
|||
""" Button to close subscription package """ |
|||
stage = self.env['subscription.package.stage'].search( |
|||
[('category', '=', 'closed')], limit=1).id |
|||
for sub in self: |
|||
values = {'stage_id': stage, 'to_renew': False} |
|||
sub.write(values) |
|||
return True |
|||
|
|||
def close_limit_cron(self): |
|||
""" It Checks renew date, close date. It will send mail when renew date """ |
|||
pending_subscriptions = self.env['subscription.package'].search( |
|||
[('stage_category', '=', 'progress')]) |
|||
today_date = fields.Date.today() |
|||
pending_subscription = False |
|||
close_subscription = False |
|||
for pending_subscription in pending_subscriptions: |
|||
pending_subscription.close_date = pending_subscription.start_date + relativedelta( |
|||
days=pending_subscription.plan_id.days_to_end) |
|||
difference = ( |
|||
pending_subscription.close_date - pending_subscription.start_date).days / 10 |
|||
renew_date = pending_subscription.close_date - relativedelta( |
|||
days=difference) |
|||
if today_date == renew_date: |
|||
self.env.ref( |
|||
'subscription_package.mail_template_subscription_renew').send_mail( |
|||
pending_subscription.id, force_send=True) |
|||
pending_subscription.write({'to_renew': True}) |
|||
if pending_subscription.plan_id.invoice_mode == 'draft_invoice': |
|||
this_products_line = [] |
|||
for rec in pending_subscription.product_line_ids: |
|||
rec_list = [0, 0, {'product_id': rec.product_id.id, |
|||
'quantity': rec.product_qty}] |
|||
this_products_line.append(rec_list) |
|||
self.env['account.move'].create( |
|||
{ |
|||
'move_type': 'out_invoice', |
|||
'date': fields.Date.today(), |
|||
'invoice_date': fields.Date.today(), |
|||
'state': 'draft', |
|||
'partner_id': pending_subscription.partner_invoice_id.id, |
|||
'currency_id': pending_subscription.partner_invoice_id.currency_id.id, |
|||
'invoice_line_ids': this_products_line |
|||
}) |
|||
pending_subscription.write({'to_renew': False, |
|||
'start_date': datetime.datetime.today()}) |
|||
close_subscriptions = self.env['subscription.package'].search( |
|||
[('stage_category', '=', 'progress'), ('to_renew', '=', True)]) |
|||
for close_subscription in close_subscriptions: |
|||
close_subscription.close_date = close_subscription.start_date + relativedelta( |
|||
days=close_subscription.plan_id.days_to_end) |
|||
if today_date == close_subscription.close_date: |
|||
close_subscription.set_close() |
|||
return dict(pending=pending_subscription, closed=close_subscription) |
|||
|
|||
@api.depends('product_line_ids.total_amount') |
|||
def _compute_total_recurring_price(self): |
|||
""" Calculate recurring price """ |
|||
for record in self: |
|||
total_recurring = 0 |
|||
for line in record.product_line_ids: |
|||
total_recurring += line.total_amount |
|||
record['total_recurring_price'] = total_recurring |
|||
|
|||
def action_renew(self): |
|||
return self.button_sale_order() |
@ -0,0 +1,130 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from odoo import api, models, fields |
|||
|
|||
|
|||
class SubscriptionPlan(models.Model): |
|||
_name = 'subscription.package.plan' |
|||
_description = 'Subscription Package Plan' |
|||
|
|||
name = fields.Char(string='Plan Name', required=True) |
|||
renewal_value = fields.Char(string='Renewal') |
|||
renewal_period = fields.Selection([('days', 'Day(s)'), |
|||
('weeks', 'Week(s)'), |
|||
('months', 'Month(s)'), |
|||
('years', 'Year(s)')], |
|||
default='months') |
|||
renewal_time = fields.Integer(string='Renewal Time Interval', |
|||
readonly=True, |
|||
compute='_compute_renewal_time', |
|||
store=True) |
|||
limit_choice = fields.Selection([('ones', 'Ones'), |
|||
('manual', 'Until Closed Manually'), |
|||
('custom', 'Custom')], |
|||
default='ones') |
|||
limit_count = fields.Integer(string='Custom Renewal Limit') |
|||
days_to_end = fields.Integer(string='Days End', readonly=True, |
|||
compute='_compute_days_to_end', store=True, |
|||
help="Subscription ending date") |
|||
invoice_mode = fields.Selection([('manual', 'Manually'), |
|||
('draft_invoice', 'Draft')], |
|||
default='draft_invoice') |
|||
journal_id = fields.Many2one('account.journal', string='Journal', |
|||
store=True, domain="[('type', '=', 'sale')]") |
|||
company_id = fields.Many2one('res.company', string='Company', store=True, |
|||
default=lambda self: self.env.company) |
|||
short_code = fields.Char(string='Short Code') |
|||
terms_and_conditions = fields.Text(string='Terms and Conditions') |
|||
product_count = fields.Integer(string='Products', |
|||
compute='_compute_product_count') |
|||
subscription_count = fields.Integer(string='Subscriptions', |
|||
compute='_compute_subscription_count') |
|||
|
|||
@api.depends('product_count') |
|||
def _compute_product_count(self): |
|||
""" Calculate product count based on subscription plan """ |
|||
self.product_count = self.env['product.product'].search_count( |
|||
[('subscription_plan_id', '=', self.id)]) |
|||
|
|||
@api.depends('subscription_count') |
|||
def _compute_subscription_count(self): |
|||
""" Calculate subscription count based on subscription plan """ |
|||
self.subscription_count = self.env[ |
|||
'subscription.package'].search_count([('plan_id', '=', self.id)]) |
|||
|
|||
@api.depends('renewal_value', 'renewal_period') |
|||
def _compute_renewal_time(self): |
|||
""" This method calculate renewal time based on renewal value """ |
|||
for rec in self: |
|||
if rec.renewal_period == 'days': |
|||
rec.renewal_time = int(rec.renewal_value) |
|||
elif rec.renewal_period == 'weeks': |
|||
rec.renewal_time = int(rec.renewal_value) * 7 |
|||
elif rec.renewal_period == 'months': |
|||
rec.renewal_time = int(rec.renewal_value) * 28 |
|||
elif rec.renewal_period == 'years': |
|||
rec.renewal_time = int(rec.renewal_value) * 364 |
|||
if rec.name: |
|||
rec.short_code = str(rec.name[0:3]).upper() |
|||
|
|||
@api.depends('renewal_time', 'limit_count') |
|||
def _compute_days_to_end(self): |
|||
""" This method calculate days to end for subscription plan based on |
|||
limit count """ |
|||
for rec in self: |
|||
if rec.limit_choice == 'ones': |
|||
rec.days_to_end = rec.renewal_time |
|||
if rec.limit_choice == 'manual': |
|||
rec.days_to_end = False |
|||
if rec.limit_choice == 'custom': |
|||
rec.days_to_end = rec.renewal_time * rec.limit_count |
|||
|
|||
def button_product_count(self): |
|||
""" It displays products based on subscription plan """ |
|||
return { |
|||
'name': 'Products', |
|||
'domain': [('subscription_plan_id', '=', self.id)], |
|||
'view_type': 'form', |
|||
'res_model': 'product.product', |
|||
'view_mode': 'tree,form', |
|||
'type': 'ir.actions.act_window', |
|||
} |
|||
|
|||
def button_sub_count(self): |
|||
""" It displays subscriptions based on subscription plan """ |
|||
return { |
|||
'name': 'Subscriptions', |
|||
'domain': [('plan_id', '=', self.id)], |
|||
'view_type': 'form', |
|||
'res_model': 'subscription.package', |
|||
'view_mode': 'tree,form', |
|||
'type': 'ir.actions.act_window', |
|||
} |
|||
|
|||
def name_get(self): |
|||
""" It displays record name as combination of short code and |
|||
plan name """ |
|||
res = [] |
|||
for rec in self: |
|||
res.append((rec.id, '%s - %s' % (rec.short_code, rec.name))) |
|||
return res |
@ -0,0 +1,51 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from odoo import api, models, fields |
|||
|
|||
|
|||
class SubscriptionInvoice(models.Model): |
|||
_inherit = "account.move" |
|||
|
|||
is_subscription = fields.Boolean(string='Is Subscription', default=False) |
|||
subscription_id = fields.Many2one('subscription.package', |
|||
string='Subscription') |
|||
|
|||
@api.model_create_multi |
|||
def create(self, vals_list): |
|||
""" It displays subscription in account move """ |
|||
for rec in vals_list: |
|||
so_id = self.env['sale.order'].search( |
|||
[('name', '=', rec.get('invoice_origin'))]) |
|||
if so_id.is_subscription is True: |
|||
new_vals_list = [{'is_subscription': True, |
|||
'subscription_id': so_id.subscription_id}] |
|||
vals_list[0].update(new_vals_list[0]) |
|||
return super(SubscriptionInvoice, self).create(vals_list) |
|||
|
|||
|
|||
class SubscriptionProduct(models.Model): |
|||
_inherit = "product.template" |
|||
|
|||
is_subscription = fields.Boolean(string='Is Subscription', default=False) |
|||
subscription_plan_id = fields.Many2one('subscription.package.plan', |
|||
string='Subscription Plan') |
@ -0,0 +1,68 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from odoo import api, models, fields |
|||
import datetime |
|||
|
|||
|
|||
class SubscriptionSaleOrder(models.Model): |
|||
_inherit = "sale.order" |
|||
|
|||
is_subscription = fields.Boolean(string='Is Subscription', default=False) |
|||
subscription_id = fields.Many2one('subscription.package', |
|||
string='Subscription') |
|||
sub_reference = fields.Char(string="Sub Reference Code", store=True, |
|||
compute="_compute_reference_code") |
|||
|
|||
@api.model |
|||
def create(self, vals): |
|||
""" It displays subscription in sale order """ |
|||
if vals.get('is_subscription') is True: |
|||
new_vals = [{ |
|||
'is_subscription': True, |
|||
'subscription_id': vals.get('subscription_id'), |
|||
}] |
|||
vals.update(new_vals[0]) |
|||
return super(SubscriptionSaleOrder, self).create(vals) |
|||
else: |
|||
return super(SubscriptionSaleOrder, self).create(vals) |
|||
|
|||
@api.depends('subscription_id') |
|||
def _compute_reference_code(self): |
|||
""" It displays subscription reference code """ |
|||
self.sub_reference = self.env['subscription.package'].search( |
|||
[('id', '=', int(self.subscription_id.id))]).reference_code |
|||
|
|||
def action_confirm(self): |
|||
""" It Changed the stage, to renew, start date for subscription |
|||
package based on sale order confirm """ |
|||
|
|||
res = super(SubscriptionSaleOrder, self).action_confirm() |
|||
sale_order = self.subscription_id.sale_order |
|||
so_state = self.search([('id', '=', sale_order.id)]).state |
|||
if so_state in ['sale', 'done']: |
|||
stage = self.env['subscription.package.stage'].search( |
|||
[('category', '=', 'progress')], limit=1).id |
|||
values = {'stage_id': stage, 'to_renew': False, |
|||
'start_date': datetime.datetime.today()} |
|||
self.subscription_id.write(values) |
|||
return res |
@ -0,0 +1,42 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from odoo import models, fields |
|||
|
|||
|
|||
class SubscriptionPackageStage(models.Model): |
|||
_name = "subscription.package.stage" |
|||
_description = "Subscription Package Stages" |
|||
_rec_name = 'name' |
|||
|
|||
name = fields.Char(string='Stage Name', required=True) |
|||
sequence = fields.Integer('Sequence', help="Determine the display order", |
|||
index=True) |
|||
condition = fields.Text(string='Conditions') |
|||
fold = fields.Boolean(string='Folded in Kanban', |
|||
help="This stage is folded in the kanban view " |
|||
"when there are no records in that stage " |
|||
"to display.") |
|||
category = fields.Selection([('draft', 'Draft'), |
|||
('progress', 'In Progress'), |
|||
('closed', 'Closed')], |
|||
readonly=False, default='draft') |
@ -0,0 +1,23 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from . import subscription_report |
@ -0,0 +1,62 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from odoo import models, fields |
|||
from odoo import tools |
|||
|
|||
|
|||
class SubscriptionReport(models.Model): |
|||
_name = "subscription.report" |
|||
_description = "Subscription Analysis" |
|||
_auto = False |
|||
|
|||
total_recurring_price = fields.Float('Recurring Price', readonly=True) |
|||
quantity = fields.Float('Quantity', readonly=True) |
|||
user_id = fields.Many2one('res.users', 'Salesperson', readonly=True) |
|||
plan_id = fields.Many2one('subscription.package.plan', 'Subscription Template', readonly=True) |
|||
|
|||
def _query(self): |
|||
select_ = """ |
|||
SELECT min(sl.id) as id, |
|||
sl.product_qty as quantity, |
|||
sub.total_recurring_price as total_recurring_price, |
|||
sub.user_id as user_id, |
|||
sub.plan_id as plan_id, |
|||
sub.name as name |
|||
""" |
|||
from_ = """ |
|||
subscription_package_product_line sl |
|||
join subscription_package sub on (sl.subscription_id = sub.id) |
|||
""" |
|||
groupby_ = """ |
|||
GROUP BY sl.product_qty, |
|||
sub.total_recurring_price, |
|||
sub.user_id, |
|||
sub.plan_id, |
|||
sub.name |
|||
""" |
|||
return '%s FROM ( %s ) %s' % (select_, from_, groupby_) |
|||
|
|||
def init(self): |
|||
tools.drop_view_if_exists(self.env.cr, self._table) |
|||
self.env.cr.execute("""CREATE or REPLACE VIEW %s as (%s)""" % ( |
|||
self._table, self._query())) |
@ -0,0 +1,37 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
|
|||
<record id="subscription_report_pivot" model="ir.ui.view"> |
|||
<field name="name">Subscription Report Pivot</field> |
|||
<field name="model">subscription.report</field> |
|||
<field name="arch" type="xml"> |
|||
<pivot string="Subscription Analysis" sample="1"> |
|||
<field name="plan_id" type="row"/> |
|||
<field name="user_id" type="col"/> |
|||
</pivot> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="subscription_report_graph" model="ir.ui.view"> |
|||
<field name="name">Subscription Report Graph</field> |
|||
<field name="model">subscription.report</field> |
|||
<field name="arch" type="xml"> |
|||
<graph string="Subscription Analysis" sample="1"> |
|||
<field name="plan_id"/> |
|||
</graph> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="subscription_action_action_view_pivot" model="ir.actions.act_window"> |
|||
<field name="name">Subscriptions Report</field> |
|||
<field name="res_model">subscription.report</field> |
|||
<field name="view_mode">pivot,graph</field> |
|||
</record> |
|||
|
|||
<menuitem id="subscription_menu_report" |
|||
name="Report" |
|||
parent="subscription_package.subscription_menu_root" |
|||
action="subscription_package.subscription_action_action_view_pivot" |
|||
sequence="11"/> |
|||
|
|||
</odoo> |
|
@ -0,0 +1,25 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data> |
|||
|
|||
<record model="ir.module.category" id="module_subscription_category"> |
|||
<field name="name">Subscription</field> |
|||
<field name="description">Helps you handle your subscription security.</field> |
|||
<field name="sequence">9</field> |
|||
</record> |
|||
|
|||
<record id="group_subscription_user" model="res.groups"> |
|||
<field name="name">User</field> |
|||
<field name="category_id" ref="module_subscription_category"/> |
|||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/> |
|||
</record> |
|||
|
|||
<record id="group_subscription_manager" model="res.groups"> |
|||
<field name="name">Subscription Administrator</field> |
|||
<field name="category_id" ref="module_subscription_category"/> |
|||
<field name="implied_ids" eval="[(4, ref('group_subscription_user'))]"/> |
|||
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/> |
|||
</record> |
|||
|
|||
</data> |
|||
</odoo> |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 115 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 203 KiB |
After Width: | Height: | Size: 113 KiB |
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,719 @@ |
|||
<div class="container" style="padding: 1rem !important; margin-bottom: 1rem !important;"> |
|||
<div class="row"> |
|||
<div class="col-sm-12 col-md-12 col-lg-12 d-flex justify-content-between" style="border-bottom: 1px solid #d5d5d5;"> |
|||
<div class="my-3"> |
|||
<img src="./assets/icons/logo.png" style="width: auto !important; height: 40px !important;"> |
|||
</div> |
|||
<div class="my-3 d-flex align-items-center"> |
|||
<div |
|||
style="background-color: #7C7BAD !important; color: #fff !important; font-weight: 600 !important; padding: 5px 15px 8px !important; margin: 0 5px !important;"> |
|||
<i class="fa fa-check mr-1"></i>Community |
|||
</div> |
|||
<div |
|||
style="background-color: #875A7B !important; color: #fff !important; font-weight: 600 !important; padding: 5px 15px 8px !important; margin: 0 5px !important;"> |
|||
<i class="fa fa-check mr-1"></i>Enterprise |
|||
</div> |
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="container" style="padding: 0rem 1.5rem 4rem !important"> |
|||
<div class="row" style="height: 900px !important;"> |
|||
<div class="col-sm-12 col-md-12 col-lg-12" |
|||
style="padding: 4rem 1rem !important; background-color: #714B67 !important; height: 600px !important; border-radius: 20px !important;"> |
|||
<h1 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #FFFFFF !important; font-size: 3.5rem !important; text-align: center !important;"> |
|||
Subscription Package</h1> |
|||
<p |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 300 !important; color: #FFFFFF !important; font-size: 1.4rem !important; text-align: center !important;"> |
|||
Print Subscription Package |
|||
</p> |
|||
<img src="./assets/screenshots/hero.gif" class="img-responsive" width="100%" height="auto" /> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="row"> |
|||
<div class="col-md-12" style="border-bottom: 1px solid #d5d5d5 !important; margin-bottom: 2rem !important"> |
|||
<h2 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> |
|||
<i class="fa fa-compass mr-2"></i>Explore this module |
|||
</h2> |
|||
</div> |
|||
<div class="col-md-6"> |
|||
<a href="#overview" style="text-decoration: none !important;"> |
|||
<div class="row" |
|||
style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> |
|||
<div class="col-8"> |
|||
<h3 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> |
|||
Overview</h3> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> |
|||
Learn more about this module</p> |
|||
</div> |
|||
<div class="col-4 text-right d-flex justify-content-end align-items-center"> |
|||
<i class="fa fa-chevron-right" style="color: #714B67 !important;"></i> |
|||
</div> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-md-6"> |
|||
<a href="#features" style="text-decoration: none !important;"> |
|||
<div class="row" |
|||
style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> |
|||
<div class="col-8"> |
|||
<h3 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> |
|||
Features</h3> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> |
|||
View features of this module</p> |
|||
</div> |
|||
<div class="col-4 text-right d-flex justify-content-end align-items-center"> |
|||
<i class="fa fa-chevron-right" style="color: #714B67 !important;"></i> |
|||
</div> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-md-6"> |
|||
<a href="#screenshots" style="text-decoration: none !important;"> |
|||
<div class="row" |
|||
style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> |
|||
<div class="col-8"> |
|||
<h3 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> |
|||
Screenshots</h3> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> |
|||
See key screenshots of this module</p> |
|||
</div> |
|||
<div class="col-4 text-right d-flex justify-content-end align-items-center"> |
|||
<i class="fa fa-chevron-right" style="color: #714B67 !important;"></i> |
|||
</div> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
<div class="row" id="overview"> |
|||
<div class="col-md-12" style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> |
|||
<h2 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> |
|||
<i class="fa fa-pie-chart mr-2"></i>Overview |
|||
</h2> |
|||
</div> |
|||
|
|||
<div class="col-mg-12 pl-3"> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important; line-height: 30px !important;"> |
|||
|
|||
This module is used to generate subscription package </p> |
|||
|
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
<div class="row" id="features"> |
|||
<div class="col-md-12" style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> |
|||
<h2 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> |
|||
<i class="fa fa-star mr-2"></i>Features |
|||
</h2> |
|||
</div> |
|||
|
|||
<div class="col-md-6 pl-3 py-3 d-flex"> |
|||
<div> |
|||
<img src="assets/icons/check.png"> |
|||
</div> |
|||
<div> |
|||
<h4 |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Community & Enterprise Support</h4> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> |
|||
Available in Odoo 15.0 Community and Enterprise.</p> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-6 pl-3 py-3 d-flex"> |
|||
<div> |
|||
<img src="assets/icons/check.png"> |
|||
</div> |
|||
<div> |
|||
<h4 |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Subscription Package Plan </h4> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-md-6 pl-3 py-3 d-flex"> |
|||
<div> |
|||
<img src="assets/icons/check.png"> |
|||
</div> |
|||
<div> |
|||
<h4 |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Subscription Renewable </h4> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-md-6 pl-3 py-3 d-flex"> |
|||
<div> |
|||
<img src="assets/icons/check.png"> |
|||
</div> |
|||
<div> |
|||
<h4 |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Automatic Subscription Closed </h4> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-md-6 pl-3 py-3 d-flex"> |
|||
<div> |
|||
<img src="assets/icons/check.png"> |
|||
</div> |
|||
<div> |
|||
<h4 |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Renew Email Alerts </h4> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-md-6 pl-3 py-3 d-flex"> |
|||
<div> |
|||
<img src="assets/icons/check.png"> |
|||
</div> |
|||
<div> |
|||
<h4 |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Create Subscription Plans </h4> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-md-6 pl-3 py-3 d-flex"> |
|||
<div> |
|||
<img src="assets/icons/check.png"> |
|||
</div> |
|||
<div> |
|||
<h4 |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Recurring Invoices Daily/Weekly/Monthly/Yearly </h4> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
<div class="row" id="screenshots"> |
|||
<div class="col-md-12" style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> |
|||
<h2 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> |
|||
<i class="fa fa-image mr-2"></i>Screenshots |
|||
</h2> |
|||
</div> |
|||
<div class="col-lg-12 my-2"> |
|||
<h4 class="mt-2" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Subscription Plans</h4> |
|||
<img src="assets/screenshots/subscription_plan.png" class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-12 my-3"> |
|||
<h4 class="mt-2" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Create Subscription Plan</h4> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> |
|||
<ul> |
|||
<li>First of all, You will create a Subscription Plan.</li> |
|||
<li>In Subscription Plan we have a Radio Button named 'Number of Occurrence',<br /> |
|||
- if we choose 'Ones', then this plan will expire according to 'Invoice on' time interval.<br /> |
|||
- if we choose 'Until Closed Manually', then this plan will expire only after clicking the button 'Close |
|||
Subscription'.<br /> |
|||
- if we choose 'Custom', then this plan will expire according to 'Invoice on' time interval and 'Renewal |
|||
Limit'. |
|||
</li> |
|||
<li>In Subscription Plan we have a Radio Button named 'Create Invoice',</li> |
|||
- If we choose 'Manually', then invoice creation is manually.<br /> |
|||
- If we choose 'Draft', then invoice creation is automatically.<br /> |
|||
</ul> |
|||
</p> |
|||
<img src="assets/screenshots/create_sub_plan.png" class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-12 my-3"> |
|||
<h4 class="mt-2" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Create Subscription Product</h4> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> |
|||
<ul> |
|||
<li>First of all, You will create a Product.</li> |
|||
<li>Here we have a CheckBox named 'Is Subscription', if we Enable the Checkbox, then the product is |
|||
subscription |
|||
product.</li> |
|||
<li>Now we choose a Subscription Plan for the period.</li> |
|||
</ul> |
|||
</p> |
|||
<img src="assets/screenshots/sub_product.png" class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-12 my-3"> |
|||
<h4 class="mt-2" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Create Subscription Customer</h4> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> |
|||
<ul> |
|||
<li>First of all, You will create a Customer.</li> |
|||
<li>Here we have a page 'Subscription' that show subscription product for customer.</li> |
|||
</ul> |
|||
</p> |
|||
<img src="assets/screenshots/sub_customer.png" class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-12 my-3"> |
|||
<h4 class="mt-3" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Activity Types </h4> |
|||
<img src="assets/screenshots/activity_type.png" class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-12 my-3"> |
|||
<h4 class="mt-3" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Subscription Close Reasons </h4> |
|||
<img src="assets/screenshots/close_reason.png" class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-12 my-3"> |
|||
<h4 class="mt-3" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Subscription Stages </h4> |
|||
<img src="assets/screenshots/sub_stage.png" class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-12 my-3"> |
|||
<h4 class="mt-3" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Create Subscription Stage </h4> |
|||
<img src="assets/screenshots/create_sub_stage.png" class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-12 my-3"> |
|||
<h4 class="mt-3" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Subscription Report </h4> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> |
|||
It shows report for subscription plans. |
|||
</p> |
|||
<img src="assets/screenshots/sub_report.png" class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-12 my-3"> |
|||
<h4 class="mt-3" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Subscriptions to Renew </h4> |
|||
<img src="assets/screenshots/sub_renew.png" class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-12 my-3"> |
|||
<h4 class="mt-3" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Create Subscription Package with Sale Order </h4> |
|||
<img src="assets/screenshots/create_sub.png" class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-12 my-3"> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> |
|||
<ul> |
|||
<li>To create a Subscription with source 'Create Sale Order', Create a Quotation of Sale Order with at least |
|||
one |
|||
subscription type product in the order line.</li> |
|||
<li>When we click on the 'Confirm' button on the 'Sale Quotation' then, automatically a subscription is |
|||
created |
|||
in 'In-progress' state. </li> |
|||
</ul> |
|||
</p> |
|||
<img src="assets/screenshots/sub_sale.png" class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto" /> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
<!-- SUGGESTED PRODUCTS --> |
|||
<div class="row"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center" |
|||
style="text-align: center; padding: 2.5rem 1rem !important;"> |
|||
<h2 style="color: #212529 !important;">Suggested Products</h2> |
|||
<hr |
|||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;" /> |
|||
|
|||
<div id="demo1" class="row carousel slide" data-ride="carousel"> |
|||
<!-- The slideshow --> |
|||
<div class="carousel-inner"> |
|||
<div class="carousel-item active" style="min-height:0px"> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/crm_dashboard/" target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/crm_dashboard_image.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/commission_plan/" target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/crm_image.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/crm_kit/" target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/crm_kit_image.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div class="carousel-item" style="min-height:0px"> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/access_restriction_by_ip/" target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/ip_image.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/dynamic_product_fields/" target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/product_custom_image.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" style="float:left"> |
|||
<a href="https://apps.odoo.com/apps/modules/15.0/task_deadline_reminder/" target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/task_deadline_image.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- Left and right controls --> |
|||
<a class="carousel-control-prev" href="#demo1" data-slide="prev" style="left:-25px;width: 35px;color: #000;"> |
|||
<span class="carousel-control-prev-icon"><i class="fa fa-chevron-left" style="font-size:24px"></i></span> |
|||
</a> |
|||
<a class="carousel-control-next" href="#demo1" data-slide="next" style="right:-25px;width: 35px;color: #000;"> |
|||
<span class="carousel-control-next-icon"><i class="fa fa-chevron-right" style="font-size:24px"></i></span> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- END OF SUGGESTED PRODUCTS --> |
|||
|
|||
<!-- OUR SERVICES --> |
|||
<section class="container" style="margin-top: 6rem !important;"> |
|||
<div class="row"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> |
|||
<h2 style="color: #212529 !important;">Our Services</h2> |
|||
<hr |
|||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/cogs.png" class="img-responsive" height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Customization</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/wrench.png" class="img-responsive" height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Implementation</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/lifebuoy.png" class="img-responsive" height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Support</h6> |
|||
</div> |
|||
|
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/user.png" class="img-responsive" height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Hire |
|||
Odoo |
|||
Developer</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/puzzle.png" class="img-responsive" height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Integration</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/update.png" class="img-responsive" height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Migration</h6> |
|||
</div> |
|||
|
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/consultation.png" class="img-responsive" height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Consultancy</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/training.png" class="img-responsive" height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Implementation</h6> |
|||
</div> |
|||
|
|||
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> |
|||
<div class="d-flex justify-content-center align-items-center mx-3 my-3" |
|||
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;"> |
|||
<img src="assets/icons/license.png" class="img-responsive" height="48px" width="48px"> |
|||
</div> |
|||
<h6 class="text-center" style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> |
|||
Odoo |
|||
Licensing Consultancy</h6> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<!-- END OF END OF OUR SERVICES --> |
|||
|
|||
<!-- OUR INDUSTRIES --> |
|||
<section class="container" style="margin-top: 6rem !important;"> |
|||
<div class="row"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> |
|||
<h2 style="color: #212529 !important;">Our Industries</h2> |
|||
<hr |
|||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;" /> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/trading-black.png" class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Trading |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Easily procure |
|||
and |
|||
sell your products</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/pos-black.png" class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
POS |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Easy |
|||
configuration |
|||
and convivial experience</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/education-black.png" class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Education |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
A platform for |
|||
educational management</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/manufacturing-black.png" class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Manufacturing |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Plan, track and |
|||
schedule your operations</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/ecom-black.png" class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
E-commerce & Website |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Mobile |
|||
friendly, |
|||
awe-inspiring product pages</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/service-black.png" class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Service Management |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Keep track of |
|||
services and invoice</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/restaurant-black.png" class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Restaurant |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
Run your bar or |
|||
restaurant methodically</p> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; padding: 2rem !important; height: 250px !important;"> |
|||
<img src="./assets/icons/hotel-black.png" class="img-responsive mb-3" height="48px" width="48px"> |
|||
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> |
|||
Hotel Management |
|||
</h5> |
|||
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> |
|||
An |
|||
all-inclusive |
|||
hotel management application</p> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
</section> |
|||
|
|||
<!-- END OF END OF OUR INDUSTRIES --> |
|||
|
|||
<!-- FOOTER --> |
|||
<!-- Footer Section --> |
|||
<section class="container" style="margin: 5rem auto 2rem;"> |
|||
<div class="row" style="max-width:1540px;"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> |
|||
<h2 style="color: #212529 !important;">Need Help?</h2> |
|||
<hr |
|||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;" /> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Contact Cards --> |
|||
<div class="row d-flex justify-content-center align-items-center" |
|||
style="max-width:1540px; margin: 0 auto 2rem auto;"> |
|||
|
|||
<div class="col-lg-12" style="padding: 0rem 3rem 2rem; border-radius: 10px; margin-right: 3rem; "> |
|||
|
|||
<div class="row mt-4"> |
|||
<div class="col-lg-6"> |
|||
<a href="mailto:odoo@cybrosys.com" target="_blank" class="btn btn-block mb-2 deep_hover" |
|||
style="text-decoration: none; background-color: #4d4d4d; color: #FFF; border-radius: 4px;"><i |
|||
class="fa fa-envelope mr-2"></i>odoo@cybrosys.com</a> |
|||
</div> |
|||
<div class="col-lg-6"> |
|||
<a href="https://api.whatsapp.com/send?phone=918606827707" target="_blank" |
|||
class="btn btn-block mb-2 deep_hover" |
|||
style="text-decoration: none; background-color: #25D366; color: #FFF; border-radius: 4px;"><i |
|||
class="fa fa-whatsapp mr-2"></i>+91 86068 27707</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
<!-- End of Contact Cards --> |
|||
</section> |
|||
<!-- Footer --> |
|||
<section class="oe_container" style="padding: 2rem 3rem 1rem;"> |
|||
<div class="row" style="max-width:1540px; margin: 0 auto; margin-right: 3rem; "> |
|||
<!-- Logo --> |
|||
<div class="col-lg-12 d-flex justify-content-center align-items-center" style="margin-top: 3rem;"> |
|||
<img src="https://www.cybrosys.com/images/logo.png" width="200px" height="auto" /> |
|||
</div> |
|||
<!-- End of Logo --> |
|||
<div class="col-lg-12"> |
|||
<hr |
|||
style="margin-top: 3rem;background: linear-gradient(90deg, rgba(2,0,36,0) 0%, rgba(229,229,229,1) 33%, rgba(229,229,229,1) 58%, rgba(0,212,255,0) 100%); height: 2px; border-style: none;"> |
|||
<!-- End of Footer Section --> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<!-- END OF FOOTER --> |
|||
|
|||
</div> |
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0"?> |
|||
<odoo> |
|||
<!-- Activity types config --> |
|||
<record id="action_config_subscription_package_mail_activity" model="ir.actions.act_window"> |
|||
<field name="name">Activity Types</field> |
|||
<field name="res_model">mail.activity.type</field> |
|||
<field name="view_mode">tree,form</field> |
|||
<field name="domain">['|', ('res_model', '=', False), ('res_model', '=', 'subscription.package')]</field> |
|||
<field name="context">{'default_res_model': 'subscription.package'}</field> |
|||
</record> |
|||
|
|||
<menuitem id="subscription_config_menu_mail_activity" |
|||
name="Activity Types" |
|||
parent="subscription_package.subscription_menu_config" |
|||
action="subscription_package.action_config_subscription_package_mail_activity" |
|||
sequence="28"/> |
|||
|
|||
</odoo> |
@ -0,0 +1,27 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
|
|||
<record id="inherit_subscription_partner_form" model="ir.ui.view"> |
|||
<field name="name">inherit.subscription.partner.form</field> |
|||
<field name="model">res.partner</field> |
|||
<field name="inherit_id" ref="base.view_partner_form"/> |
|||
<field name="arch" type="xml"> |
|||
<page name="sales_purchases" position="after"> |
|||
<page string="Subscription"> |
|||
<group string="Subscriptions" |
|||
name="subscription_product_id"> |
|||
<field name="subscription_product_line_ids" nolabel="1"> |
|||
<tree editable="bottom"> |
|||
<field name="product_id"/> |
|||
<field name="uom_catg_id"/> |
|||
<field name="product_uom_id"/> |
|||
<field name="unit_price"/> |
|||
</tree> |
|||
</field> |
|||
</group> |
|||
</page> |
|||
</page> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,27 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
|
|||
<record id="action_config_subscription_stop" model="ir.actions.act_window"> |
|||
<field name="name">Subscription Stop Reason</field> |
|||
<field name="res_model">subscription.package.stop</field> |
|||
<field name="view_mode">tree</field> |
|||
</record> |
|||
|
|||
<record id="subscription_close_reason_tree" model="ir.ui.view"> |
|||
<field name="name">Subscription Stop Reason Tree</field> |
|||
<field name="model">subscription.package.stop</field> |
|||
<field name="arch" type="xml"> |
|||
<tree editable="bottom"> |
|||
<field name="sequence" widget="handle"/> |
|||
<field name="name" colspan="3"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<menuitem id="subscription_menu_close_reason" |
|||
name="Reason to Close" |
|||
parent="subscription_package.subscription_menu_config" |
|||
action="subscription_package.action_config_subscription_stop" |
|||
sequence="27"/> |
|||
|
|||
</odoo> |
@ -0,0 +1,272 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
|
|||
<data noupdate="1"> |
|||
<record id="sequence_reference_code" model="ir.sequence"> |
|||
<field name="name">Reference Code</field> |
|||
<field name="code">sequence.reference.code</field> |
|||
<field name="prefix">SUB</field> |
|||
<field name="padding">4</field> |
|||
</record> |
|||
</data> |
|||
|
|||
<record id="subscription_action_subscriptions" model="ir.actions.act_window"> |
|||
<field name="name">Subscriptions</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">subscription.package</field> |
|||
<field name="view_mode">kanban,tree,form,pivot</field> |
|||
<field name="help" type="html"> |
|||
<p class="o_view_nocontent_smiling_face"> |
|||
Create a new subscription package ! |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="subscription_action_subscriptions_customers" model="ir.actions.act_window"> |
|||
<field name="name">Subscriptions Customers</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">res.partner</field> |
|||
<field name="view_mode">kanban,tree,form</field> |
|||
<field name="domain">[('active_subscription', '=', True)]</field> |
|||
<field name="help" type="html"> |
|||
<p class="o_view_nocontent_smiling_face"> |
|||
Create a new subscription package ! |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="subscription_action_subscriptions_to_renew" model="ir.actions.act_window"> |
|||
<field name="name">Subscriptions to Renew</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">subscription.package</field> |
|||
<field name="domain">[('to_renew', '=', True)]</field> |
|||
<field name="view_mode">kanban,tree,form,pivot</field> |
|||
<field name="help" type="html"> |
|||
<p class="o_view_nocontent_smiling_face"> |
|||
Create a new subscription package ! |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="subscription_package_tree" model="ir.ui.view"> |
|||
<field name="name">subscription.package.tree</field> |
|||
<field name="model">subscription.package</field> |
|||
<field name="arch" type="xml"> |
|||
<tree> |
|||
<field name="name"/> |
|||
<field name="stage_id"/> |
|||
<field name="partner_id"/> |
|||
<field name="reference_code"/> |
|||
<field name="start_date"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="subscription_package_form" model="ir.ui.view"> |
|||
<field name="name">subscription.package.form</field> |
|||
<field name="model">subscription.package</field> |
|||
<field name="groups_id" eval="[(4, ref('subscription_package.group_subscription_user'))]"/> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<header> |
|||
<field name="current_stage" invisible="1"/> |
|||
<field name="is_closed" invisible="1"/> |
|||
<button name="button_start_date" string="START" |
|||
type="object" class="btn-primary oe_read_only" attrs="{'invisible': [('stage_category','!=', 'draft')]}"/> |
|||
<button name="button_sale_order" string="Create Sale Order" |
|||
type="object" class="btn-primary oe_read_only" attrs="{'invisible': [('so_count','>',0)]}"/> |
|||
<button name="button_payment" string="Invoice" |
|||
type="object" class="btn-primary oe_read_only" |
|||
attrs="{'invisible': [('so_count', '=', 0)]}" |
|||
invisible="1"/> |
|||
<button name="button_close" string="Close Subscription" |
|||
type="object" class="btn-primary oe_read_only" |
|||
attrs="{'invisible': [('stage_category', 'in', ['draft', 'closed'])]}"/> |
|||
<button name="action_renew" string="Renew" type="object" class="btn-primary oe_read_only" attrs="{'invisible': [('so_count', '=', 0)]}"/> |
|||
<field name="stage_id" widget="statusbar" options="{'clickable' :0}"/> |
|||
</header> |
|||
<sheet> |
|||
<div class="oe_button_box" name="button_box"> |
|||
<button name="button_sale_count" type="object" class="oe_stat_button" |
|||
icon="fa-credit-card" attrs="{'invisible': [('sale_order', '=', False)]}"> |
|||
<div class="o_field_widget o_stat_info"> |
|||
<span class="o_stat_value"> |
|||
<field name="so_count"/> |
|||
</span> |
|||
<span class="o_stat_text"> |
|||
Sale Order |
|||
</span> |
|||
</div> |
|||
</button> |
|||
<button name="button_invoice_count" type="object" class="oe_stat_button" |
|||
icon="fa-book" attrs="{'invisible': [('invoice_count','<=',0)]}"> |
|||
<div class="o_field_widget o_stat_info"> |
|||
<span class="o_stat_value"> |
|||
<field name="invoice_count"/> |
|||
</span> |
|||
<span class="o_stat_text"> |
|||
Invoices |
|||
</span> |
|||
</div> |
|||
</button> |
|||
</div> |
|||
<div class="text-truncate w-100"> |
|||
<h1> |
|||
<field name="name" |
|||
placeholder="e.g. Monthly Subscriptions" |
|||
attrs="{'readonly': 1}"/> |
|||
</h1> |
|||
<div class="badge-pill badge-danger float-right" |
|||
attrs="{'invisible': [('to_renew', '=', False)]}"> |
|||
For Renewal |
|||
</div> |
|||
</div> |
|||
<group> |
|||
<group> |
|||
<field name="partner_id" attrs="{'required': True}"/> |
|||
<field name="partner_invoice_id"/> |
|||
<field name="partner_shipping_id"/> |
|||
<field name="start_date"/> |
|||
<field name="next_invoice_date"/> |
|||
</group> |
|||
<group> |
|||
<field name="plan_id" attrs="{'required': True}"/> |
|||
<field name="to_renew"/> |
|||
<field name="reference_code"/> |
|||
<field name="analytic_account_id"/> |
|||
<field name="tag_ids" widget="many2many_tags" |
|||
options="{'limit': 2, 'create': false, 'create_edit': false}"/> |
|||
<field name="user_id"/> |
|||
<field name="company_id"/> |
|||
<field name="stage_category" invisible="1"/> |
|||
<field name="invoice_mode" invisible="1"/> |
|||
</group> |
|||
</group> |
|||
<notebook> |
|||
<page string="Subscriptions" name="subscription_products_line"> |
|||
<field name="product_line_ids"> |
|||
<tree string="Product lines" editable="bottom"> |
|||
<field name="sequence" widget="handle"/> |
|||
<field name="product_id" required="1"/> |
|||
<field name="uom_catg_id" invisible="1"/> |
|||
<field name="product_qty" required="1"/> |
|||
<field name="product_uom_id" required="1"/> |
|||
<field name="currency_id" invisible="1"/> |
|||
<field name="unit_price" required="1"/> |
|||
<field name="total_amount" readonly="1"/> |
|||
</tree> |
|||
</field> |
|||
<group name="note_group" col="6" class="mt-2 mt-md-0"> |
|||
<group class="oe_subtotal_footer oe_right" colspan="2" name="recurring_total"> |
|||
<field name="total_recurring_price"/> |
|||
</group> |
|||
</group> |
|||
</page> |
|||
<page string="Terms and Conditions" name="terms_and_conditions"> |
|||
<field name="description" placeholder="Terms and Conditions."/> |
|||
</page> |
|||
<page string="Other Info" name="other_info"> |
|||
<group> |
|||
<group> |
|||
<field name="user_id"/> |
|||
<field name="sale_order"/> |
|||
</group> |
|||
<group> |
|||
</group> |
|||
</group> |
|||
</page> |
|||
</notebook> |
|||
</sheet> |
|||
<div class="oe_chatter"> |
|||
<field name="message_follower_ids" widget="mail_followers"/> |
|||
<field name="message_ids" widget="mail_thread"/> |
|||
<field name="activity_ids" widget="mail_activity"/> |
|||
</div> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
|
|||
<record id="subscription_package_kanban" model="ir.ui.view"> |
|||
<field name="name">subscription.package.kanban</field> |
|||
<field name="model">subscription.package</field> |
|||
<field name="arch" type="xml"> |
|||
<kanban default_group_by="stage_id" quick_create="false" class="o_kanban_mobile" sample="1"> |
|||
<field name="stage_id"/> |
|||
<field name="user_id"/> |
|||
<field name="to_renew"/> |
|||
<field name="partner_id"/> |
|||
<field name="reference_code"/> |
|||
<progressbar field='stage_id' |
|||
colors='{"progress_stage": "success", "draft_stage": "warning", "closed_stage": "muted"}'/> |
|||
<templates> |
|||
<t t-name="kanban-box"> |
|||
<div class="oe_kanban_card oe_kanban_global_click"> |
|||
<div class="oe_kanban_content"> |
|||
<div class="o_kanban_record_title"> |
|||
<field name="partner_id"/> |
|||
</div> |
|||
<div class="o_kanban_record_body"> |
|||
<field name="reference_code"/> |
|||
<br/> |
|||
<div class="badge badge-pill badge-info badge-danger mt4 mr16" |
|||
attrs="{'invisible': [('to_renew', '=', False)]}"> |
|||
To Renew |
|||
</div> |
|||
</div> |
|||
<div class="o_kanban_record_bottom"> |
|||
<div class="oe_kanban_bottom_left"> |
|||
<field name="activity_ids" widget="kanban_activity"/> |
|||
</div> |
|||
<div class="oe_kanban_bottom_right"> |
|||
<field name="user_id" widget="many2one_avatar_user"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="oe_clear"/> |
|||
</div> |
|||
</t> |
|||
</templates> |
|||
</kanban> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="subscription_package_pivot" model="ir.ui.view"> |
|||
<field name="name">subscription.package.pivot</field> |
|||
<field name="model">subscription.package</field> |
|||
<field name="arch" type="xml"> |
|||
<pivot string="Pivot View"> |
|||
<field name="name" type="row"/> |
|||
</pivot> |
|||
</field> |
|||
</record> |
|||
|
|||
<menuitem id="subscription_menu_root" |
|||
name="Subscription" |
|||
action="subscription_package.subscription_action_subscriptions" |
|||
sequence="1" groups="group_subscription_user"/> |
|||
|
|||
<menuitem id="subscription_menu_subscriptions" |
|||
name="Subscriptions" |
|||
parent="subscription_package.subscription_menu_root" |
|||
sequence="3"/> |
|||
|
|||
<menuitem id="subscriptions_menu_subscriptions" |
|||
name="Subscriptions" |
|||
parent="subscription_package.subscription_menu_subscriptions" |
|||
action="subscription_package.subscription_action_subscriptions" |
|||
sequence="5"/> |
|||
<menuitem id="subscriptions_menu_subscriptions_to_renew" |
|||
name="Subscriptions to Renew" |
|||
parent="subscription_package.subscription_menu_subscriptions" |
|||
action="subscription_package.subscription_action_subscriptions_to_renew" |
|||
sequence="6"/> |
|||
|
|||
<menuitem id="subscriptions_menu_subscriptions_customers" |
|||
name="Customers" |
|||
parent="subscription_package.subscription_menu_subscriptions" |
|||
action="subscription_package.subscription_action_subscriptions_customers" |
|||
sequence="7"/> |
|||
|
|||
</odoo> |
|||
|
@ -0,0 +1,108 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
|
|||
<record id="action_conf_subscription_plan" model="ir.actions.act_window"> |
|||
<field name="name">Subscription Plan</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">subscription.package.plan</field> |
|||
<field name="view_mode">tree,form</field> |
|||
<field name="help" type="html"> |
|||
<p class="o_view_nocontent_smiling_face"> |
|||
Create a new subscription plan ! |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="subscription_plan_tree" model="ir.ui.view"> |
|||
<field name="name">subscription.package.plan.tree</field> |
|||
<field name="model">subscription.package.plan</field> |
|||
<field name="arch" type="xml"> |
|||
<tree> |
|||
<field name="name"/> |
|||
<field name="renewal_period"/> |
|||
<field name="company_id"/> |
|||
<field name="short_code"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="subscription_plan_form" model="ir.ui.view"> |
|||
<field name="name">subscription.package.plan.form</field> |
|||
<field name="model">subscription.package.plan</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<sheet> |
|||
<div class="oe_button_box" name="button_box"> |
|||
<button name="button_product_count" type="object" |
|||
class="oe_stat_button" icon="fa-shopping-cart"> |
|||
<div class="o_field_widget o_stat_info"> |
|||
<span class="o_stat_value"> |
|||
<field name="product_count"/> |
|||
</span> |
|||
<span class="o_stat_text"> |
|||
Products |
|||
</span> |
|||
</div> |
|||
</button> |
|||
<button name="button_sub_count" class="oe_stat_button" |
|||
icon="fa-book" type="object"> |
|||
<div class="o_field_widget o_stat_info"> |
|||
<span class="o_stat_value"> |
|||
<field name="subscription_count"/> |
|||
</span> |
|||
<span class="o_stat_text"> |
|||
Subscriptions |
|||
</span> |
|||
</div> |
|||
</button> |
|||
</div> |
|||
<div class="oe_title"> |
|||
<h1><field name="name" placeholder="e.g. Yearly Subscription"/> |
|||
</h1> |
|||
</div> |
|||
<group id="conditions"> |
|||
<group id="invoicing_left"> |
|||
<label string="Invoice on" for="renewal_value"/> |
|||
<div class="o_row"> |
|||
Every |
|||
<field name="renewal_value" attrs="{'required': True}"/> |
|||
<field name="renewal_period" attrs="{'required': True}"/> |
|||
</div> |
|||
<field name="limit_choice" string="Number of Occurrence" |
|||
widget="radio"/> |
|||
<label string="Renewal Limit" for="limit_count" attrs="{'invisible': [('limit_choice', '!=', 'custom')]}"/> |
|||
<div class="o_row" attrs="{'invisible': [('limit_choice', '!=', 'custom')]}"> |
|||
<field name="limit_count" attrs="{'required': [('limit_choice', '=', 'custom')]}" readonly="0"/> |
|||
term(s) |
|||
</div> |
|||
</group> |
|||
<group id="invoicing_right"> |
|||
<field name="renewal_time" invisible="1"/> |
|||
<field name="days_to_end" invisible="1"/> |
|||
<field name="invoice_mode" string="Create Invoice" |
|||
widget="radio" attrs="{'required': True}"/> |
|||
<field name="short_code"/> |
|||
<field name="journal_id"/> |
|||
<field name="company_id"/> |
|||
</group> |
|||
</group> |
|||
<separator string="Terms and conditions"/> |
|||
<field name="terms_and_conditions" |
|||
placeholder="Terms and conditions."/> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<menuitem id="subscription_menu_config" |
|||
name="Configuration" |
|||
parent="subscription_package.subscription_menu_root" |
|||
sequence="21" groups="group_subscription_manager"/> |
|||
|
|||
<menuitem id="subscription_config_menu_subscription_template" |
|||
name="Subscription Plan" |
|||
parent="subscription_package.subscription_menu_config" |
|||
action="subscription_package.action_conf_subscription_plan" |
|||
sequence="23" groups="group_subscription_manager"/> |
|||
|
|||
</odoo> |
@ -0,0 +1,86 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
|
|||
<record id="product_template_search_view_inherit" model="ir.ui.view"> |
|||
<field name="name">Inherit Product Search</field> |
|||
<field name="model">product.template</field> |
|||
<field name="inherit_id" ref="product.product_template_search_view"/> |
|||
<field name="priority">25</field> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//filter[@name='filter_to_sell']" position="before"> |
|||
<filter string="Is Subscription Product" |
|||
name="filter_is_subscription" |
|||
domain="[('is_subscription','=',True)]"/> |
|||
<separator/> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="product_inherit_subscription" model="ir.ui.view"> |
|||
<field name="name">Inherit Product Product: Is Subscription Product</field> |
|||
<field name="model">product.product</field> |
|||
<field name="inherit_id" ref="product.product_normal_form_view"/> |
|||
<field name="priority">25</field> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//page[@name='sales']" position="after"> |
|||
<page name="subscription" string="Subscription"> |
|||
<group> |
|||
<group name="subscription" string="Subscription"> |
|||
<field name="is_subscription"/> |
|||
<field name="subscription_plan_id" |
|||
attrs="{'required': [('is_subscription', '=', True)], |
|||
'invisible': [('is_subscription', '!=', True)],}"/> |
|||
</group> |
|||
</group> |
|||
</page> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="product_template_inherit_subscription" model="ir.ui.view"> |
|||
<field name="name">Inherit Product Template: Product Subscription</field> |
|||
<field name="model">product.template</field> |
|||
<field name="inherit_id" ref="product.product_template_only_form_view"/> |
|||
<field name="priority">25</field> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//page[@name='sales']" position="after"> |
|||
<page name="subscription" string="Subscription"> |
|||
<group> |
|||
<group name="subscription" string="Subscription"> |
|||
<field name="is_subscription"/> |
|||
<field name="subscription_plan_id" |
|||
attrs="{'required': [('is_subscription', '=', True)], |
|||
'invisible': [('is_subscription', '!=', True)],}"/> |
|||
</group> |
|||
</group> |
|||
</page> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_subscription_products" model="ir.actions.act_window"> |
|||
<field name="name">Products</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">product.template</field> |
|||
<field name="view_mode">kanban,tree,form,activity</field> |
|||
<field name="view_id" ref="product.product_template_kanban_view"/> |
|||
<field name="search_view_id" ref="product.product_template_search_view"/> |
|||
<field name="context">{ |
|||
'search_default_filter_is_subscription': True, |
|||
'search_default_filter_to_sell':1, |
|||
'default_type':'service', |
|||
'default_is_subscription':True}</field> |
|||
<field name="help" type="html"> |
|||
<p class="o_view_nocontent_smiling_face"> |
|||
Create a new product |
|||
</p> |
|||
</field> |
|||
</record> |
|||
|
|||
<menuitem id="subscription_menu_subscription_products" |
|||
name="Products" |
|||
parent="subscription_package.subscription_menu_subscriptions" |
|||
action="subscription_package.action_subscription_products" |
|||
sequence="9"/> |
|||
|
|||
</odoo> |
@ -0,0 +1,21 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
|
|||
<record id="view_order_form_subscription" model="ir.ui.view"> |
|||
<field name="name">sale.order.form.subscription.info</field> |
|||
<field name="model">sale.order</field> |
|||
<field name="inherit_id" ref="sale.view_order_form"/> |
|||
<field name="arch" type="xml"> |
|||
<data> |
|||
<xpath expr="//group[@name='sales_person']" position='after'> |
|||
<group string="Subscription" name="subscription_info"> |
|||
<field name="is_subscription"/> |
|||
<field name="subscription_id"/> |
|||
<field name="sub_reference"/> |
|||
</group> |
|||
</xpath> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,51 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
|
|||
<record id="action_config_subscription_stages" model="ir.actions.act_window"> |
|||
<field name="name">Stages</field> |
|||
<field name="res_model">subscription.package.stage</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
|
|||
<record id="subscription_stages_tree" model="ir.ui.view"> |
|||
<field name="name">Subscription Stage Tree</field> |
|||
<field name="model">subscription.package.stage</field> |
|||
<field name="arch" type="xml"> |
|||
<tree> |
|||
<field name="sequence" widget="handle"/> |
|||
<field name="name"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="subscription_stages_form" model="ir.ui.view"> |
|||
<field name="name">Subscription Stage Form</field> |
|||
<field name="model">subscription.package.stage</field> |
|||
<field name="arch" type="xml"> |
|||
<form> |
|||
<sheet> |
|||
<group> |
|||
<group> |
|||
<field name="name" attrs="{'required': True}"/> |
|||
<field name="sequence"/> |
|||
</group> |
|||
<group> |
|||
<field name="fold"/> |
|||
<field name="category" widget="radio"/> |
|||
</group> |
|||
</group> |
|||
<separator string="Conditions"/> |
|||
<field name="condition" |
|||
placeholder="Specify the conditions that need to be satisfied to move to this stage."/> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<menuitem id="subscription_config_menu_subscription_stages" |
|||
name="Stages" |
|||
parent="subscription_package.subscription_menu_config" |
|||
action="subscription_package.action_config_subscription_stages" |
|||
sequence="25"/> |
|||
|
|||
</odoo> |
@ -0,0 +1,23 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from . import subscription_close_wizard |
@ -0,0 +1,45 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################# |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################# |
|||
|
|||
from odoo import models, fields, api |
|||
|
|||
|
|||
class SubscriptionCloseWizard(models.TransientModel): |
|||
_name = 'subscription.close.wizard' |
|||
_description = 'Subscription Close Wizard' |
|||
|
|||
close_reason = fields.Many2one('subscription.package.stop', string='Close Reason') |
|||
closed_by = fields.Many2one('res.users', string='Closed By', default=lambda self: self.env.user) |
|||
close_date = fields.Date(string='Closed On', default=lambda self: fields.Date.today()) |
|||
|
|||
def button_submit(self): |
|||
self.ensure_one() |
|||
this_sub_id = self.env.context.get('active_id') |
|||
sub = self.env['subscription.package'].search([('id', '=', this_sub_id)]) |
|||
sub.is_closed = True |
|||
sub.close_reason = self.close_reason |
|||
sub.closed_by = self.closed_by |
|||
sub.close_date = self.close_date |
|||
stage = (self.env['subscription.package.stage'].search([ |
|||
('category', '=', 'closed')]).id) |
|||
values = {'stage_id': stage, 'to_renew': False} |
|||
sub.write(values) |
@ -0,0 +1,23 @@ |
|||
<?xml version="1.0" encoding="utf-8" ?> |
|||
<odoo> |
|||
|
|||
<record id="subscription_close_wizard_view" model="ir.ui.view"> |
|||
<field name="name">subscription.close.wizard.view</field> |
|||
<field name="model">subscription.close.wizard</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Subscription Close Wizard"> |
|||
<group class="oe_title"> |
|||
<field name="close_reason"/> |
|||
<field name="closed_by"/> |
|||
<field name="close_date"/> |
|||
</group> |
|||
<footer> |
|||
<button name="button_submit" string="Submit" type="object" class="btn-primary"/> |
|||
<button string="Cancel" class="btn-secondary" |
|||
special="cancel"/> |
|||
</footer> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
</odoo> |