diff --git a/quotation_handler/README.rst b/quotation_handler/README.rst
new file mode 100644
index 000000000..a3f4632b5
--- /dev/null
+++ b/quotation_handler/README.rst
@@ -0,0 +1,19 @@
+Quotation Revised History v10
+=============================
+The clients will require negotiations whenever we sent a quotation to them.In such cases we need to edit the
+Quotation's order lines. We have included the 'Revise the Quotation' button for it. The order lines can be edited
+by a click on this button. At the same time a history or copy of the quotation will also be generated automatically.
+We can track the history using the smart buttons.
+Every quotations have a expiration date which we set manually.On configuring the above shown settings we can
+automatically set the expiration date very easily.
+
+Features
+========
+
+* Retrieve the History of Revised Quotations.
+* Automatically Set Expiration Date For Quotation.
+* Email Template Contains The Expiration Date.
+
+Credits
+=======
+Nikhil Krishnan @ cybrosys, nikhil@cybrosys.in
\ No newline at end of file
diff --git a/quotation_handler/__init__.py b/quotation_handler/__init__.py
new file mode 100644
index 000000000..5b63ab14d
--- /dev/null
+++ b/quotation_handler/__init__.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+##############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2017-TODAY Cybrosys Technologies().
+# Author: Nikhil krishnan()
+# you can modify it under the terms of the GNU LESSER
+# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
+#
+# It is forbidden to publish, distribute, sublicense, or sell copies
+# of the Software or modified copies of the Software.
+#
+# 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
+# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
+# If not, see .
+#
+##############################################################################
+
+import models
diff --git a/quotation_handler/__manifest__.py b/quotation_handler/__manifest__.py
new file mode 100644
index 000000000..19a9cddef
--- /dev/null
+++ b/quotation_handler/__manifest__.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+
+##############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2017-TODAY Cybrosys Technologies().
+# Author: Nikhil krishnan()
+# you can modify it under the terms of the GNU LESSER
+# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
+#
+# It is forbidden to publish, distribute, sublicense, or sell copies
+# of the Software or modified copies of the Software.
+#
+# 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
+# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
+# If not, see .
+#
+##############################################################################
+
+{
+ 'name': 'Quotation Revised History',
+ 'version': '10.0.1.0.0',
+ 'summary': """We Can Retrieve the History of Revised Quotations.""",
+ 'description': """ Negotiations with clients and we resent multiple Quotations,
+ This module store the History of Every Quotations""",
+ 'author': 'Cybrosys Techno Solutions',
+ 'company': 'Cybrosys Techno Solutions',
+ 'website': 'http://www.cybrosys.com',
+ 'category': 'Sales Management',
+ 'depends': ['sale'],
+ 'license': 'LGPL-3',
+ 'data': [
+ 'views/quotation_handler.xml',
+ 'views/sale_config_settings_exp_date_views.xml',
+ 'data/mail_template_data_exp_date.xml',
+ ],
+ 'demo': [],
+ 'images': ['static/description/banner.jpg'],
+ 'installable': True,
+ 'auto_install': False,
+}
diff --git a/quotation_handler/data/mail_template_data_exp_date.xml b/quotation_handler/data/mail_template_data_exp_date.xml
new file mode 100644
index 000000000..915d5f8fb
--- /dev/null
+++ b/quotation_handler/data/mail_template_data_exp_date.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+ Sales Order - Send by Email
+ ${(object.user_id.email and '%s <%s>' % (object.user_id.name, object.user_id.email) or '')|safe}
+ ${object.company_id.name} ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'} (Ref ${object.name or 'n/a' })
+ ${object.partner_id.id}
+
+
+
+ ${(object.name or '').replace('/','_')}_${object.state == 'draft' and 'draft' or ''}
+ ${object.partner_id.lang}
+ Dear ${object.partner_id.name}
+% set access_action = object.get_access_action()
+% set doc_name = 'quotation' if object.state in ('draft', 'sent') else 'order confirmation'
+% set is_online = access_action and access_action['type'] == 'ir.actions.act_url'
+% set access_name = is_online and object.template_id and 'Accept and pay %s online' % doc_name or 'View %s' % doc_name
+% set access_url = is_online and access_action['url'] or object.get_signup_url()
+
+% if object.partner_id.parent_id:
+ (${object.partner_id.parent_id.name})
+% endif
+,
+
+Here is your ${doc_name} ${object.name}
+% if object.origin:
+(with reference: ${object.origin} )
+% endif
+amounting in ${object.amount_total} ${object.pricelist_id.currency_id.name}
+from ${object.company_id.name}.
+
+
+% endif
+% if object.state in ('draft', 'sent'):
+% if object.state == "pre" or object.state == "draft" or object.state == "sent" :
+ % if object.validity_date:
+
Your quotation will expire on ${object.validity_date}.
+ % endif
+% endif
+
You can reply to this email if you have any questions.
+
+
Thank you,
+
+
+% if object.user_id and object.user_id.signature:
+ ${object.user_id.signature | safe}
+% endif
+
+]]>
+
+
+
diff --git a/quotation_handler/models/__init__.py b/quotation_handler/models/__init__.py
new file mode 100644
index 000000000..1c12e02d9
--- /dev/null
+++ b/quotation_handler/models/__init__.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+
+##############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2017-TODAY Cybrosys Technologies().
+# Author: Nikhil krishnan()
+# you can modify it under the terms of the GNU LESSER
+# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
+#
+# It is forbidden to publish, distribute, sublicense, or sell copies
+# of the Software or modified copies of the Software.
+#
+# 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
+# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
+# If not, see .
+#
+##############################################################################
+
+import sale
+import sale_config_settings_exp_date_views
diff --git a/quotation_handler/models/sale.py b/quotation_handler/models/sale.py
new file mode 100644
index 000000000..7a08da2e6
--- /dev/null
+++ b/quotation_handler/models/sale.py
@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*-
+
+##############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2017-TODAY Cybrosys Technologies().
+# Author: Nikhil krishnan()
+# you can modify it under the terms of the GNU LESSER
+# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
+#
+# It is forbidden to publish, distribute, sublicense, or sell copies
+# of the Software or modified copies of the Software.
+#
+# 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
+# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
+# If not, see .
+#
+##############################################################################
+
+from odoo import models, fields, api, _
+from datetime import timedelta, datetime
+
+
+class SaleOrder(models.Model):
+ _inherit = 'sale.order'
+
+ name = fields.Char(string='Order Reference', required=True, copy=False, readonly=True,
+ index=True, default='New')
+ parent_so_id = fields.Many2one('sale.order', 'Parent SO')
+ revised_order_count = fields.Integer(string='# of Revised Orders', compute='_revised_count')
+ validity_date = fields.Date(string='Expiration Date', readonly=True, states={'draft': [('readonly', False)],
+ 'pre': [('readonly', False)]},
+ help="Automatically expiration date of your quotation (offer) will set as 14 days "
+ "later, or it will set the date automatically based on the settings, We can set "
+ "it manually too.")
+
+ state = fields.Selection([
+ ('pre', 'Revised Quotation'),
+ ('draft', 'Quotation'),
+ ('sent', 'Quotation Sent'),
+ ('revised', 'Revised'),
+ ('sale', 'Sale Order'),
+ ('done', 'Done'),
+ ('cancel', 'Cancelled'),
+ ], string='Status', readonly=True, copy=False, index=True, track_visibility='onchange', default='draft')
+ revision_number = fields.Integer(string='Revision', copy=False, default=1)
+ org_name = fields.Char(string='Origin', copy=False)
+
+ @api.model
+ def create(self, vals):
+ date_start = self.env['ir.values'].get_default('sale.config.settings', 'so_expiration_date_start')
+ if not date_start:
+ if 'validity_date' in vals:
+ if vals.get('validity_date'):
+ pass
+ else:
+ date_no = self.env['ir.values'].get_default('sale.config.settings', 'so_expiration_date_no')
+ date_today = fields.Date.today()
+ date_object = datetime.strptime(date_today, '%Y-%m-%d')
+ if not date_no:
+ pass
+ else:
+ v_date = date_object + timedelta(days=date_no)
+ vals['validity_date'] = v_date
+
+ return super(SaleOrder, self).create(vals)
+
+ @api.multi
+ def _revised_count(self):
+ for sale in self:
+ revised_count = sale.search([('parent_so_id', '=', sale.id)])
+ sale.revised_order_count = len(revised_count)
+
+ # ********************Overwrite the print button to give expiration date********************
+ @api.multi
+ def print_quotation(self):
+ is_date = self.env['ir.values'].get_default('sale.config.settings', 'so_expiration_date')
+ date_start = self.env['ir.values'].get_default('sale.config.settings', 'so_expiration_date_start')
+ date_no = self.env['ir.values'].get_default('sale.config.settings', 'so_expiration_date_no')
+ if is_date:
+ if date_start:
+ if date_no:
+ for doc in self:
+ if doc.state in ['pre', 'draft']:
+ date_today = fields.Date.today()
+ date_object = datetime.strptime(date_today, '%Y-%m-%d')
+ v_date = date_object + timedelta(days=date_no)
+ doc.validity_date = v_date
+ self.filtered(lambda s: s.state == 'pre').write({'state': 'sent'})
+ return super(SaleOrder, self).print_quotation()
+
+ @api.multi
+ def make_revision(self):
+ for rec in self:
+ if not rec.org_name:
+ namee = rec.name + '/R' + str(rec.revision_number)
+ rec.org_name = rec.name
+ else:
+ namee = rec.org_name + '/R' + str(rec.revision_number)
+ if not rec.org_name:
+ names = rec.name
+ else:
+ names = rec.org_name
+ vals = {
+ 'name': names + "-" + str(rec.revision_number),
+ 'state': 'revised',
+ 'parent_so_id': rec.id
+ }
+ new_so_copy = rec.copy(default=vals)
+ rec.state = 'pre'
+ rec.name = namee
+ rec.revision_number += 1
+ date_start = self.env['ir.values'].get_default('sale.config.settings', 'so_expiration_date_start')
+ if date_start:
+ rec.validity_date = False
+
+
+class MailComposeMessage(models.TransientModel):
+ _inherit = 'mail.compose.message'
+
+ @api.multi
+ def send_mail(self, auto_commit=False):
+ if self._context.get('default_model') == 'sale.order' and self._context.get('default_res_id') and self._context.get('mark_so_as_sent'):
+ order = self.env['sale.order'].browse([self._context['default_res_id']])
+ # ********************Email Sent action Change the State in pre stage too********************
+ if order.state in ('draft', 'pre'):
+ order.state = 'sent'
+ date_start = self.env['ir.values'].get_default('sale.config.settings', 'so_expiration_date_start')
+ if date_start:
+ # ********************Email Sent action Set the Exp Date From settings********************
+ date_no = self.env['ir.values'].get_default('sale.config.settings', 'so_expiration_date_no')
+ date_today = fields.Date.today()
+ date_object = datetime.strptime(date_today, '%Y-%m-%d')
+ if date_no:
+ v_date = date_object + timedelta(days=date_no)
+ order.validity_date = v_date
+
+ self = self.with_context(mail_post_autofollow=True)
+ return super(MailComposeMessage, self).send_mail(auto_commit=auto_commit)
+
diff --git a/quotation_handler/models/sale_config_settings_exp_date_views.py b/quotation_handler/models/sale_config_settings_exp_date_views.py
new file mode 100644
index 000000000..3c9c280c1
--- /dev/null
+++ b/quotation_handler/models/sale_config_settings_exp_date_views.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+
+##############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2017-TODAY Cybrosys Technologies().
+# Author: Nikhil krishnan()
+# you can modify it under the terms of the GNU LESSER
+# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
+#
+# It is forbidden to publish, distribute, sublicense, or sell copies
+# of the Software or modified copies of the Software.
+#
+# 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
+# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
+# If not, see .
+#
+##############################################################################
+
+from odoo import api, fields, models
+
+
+class SaleConfiguration(models.TransientModel):
+ _inherit = 'sale.config.settings'
+
+ so_expiration_date = fields.Selection([(0, "No Default Expiration Date"), (1, "Default 14 days"),
+ (2, 'Created as company rule')], "Expiration Date",
+ help="Allows you to set Expiration Date.")
+ so_expiration_date_start = fields.Selection([(0, "Quotation Creation Date"),
+ (1, "Quotation Sent Date")],
+ "Expiration Date Start from",
+ help="Allows you to set Expiration Date Start from.")
+ so_expiration_date_no = fields.Integer(string="No.of Days")
+
+ @api.multi
+ def set_default_so_expiration_date(self):
+ return self.env['ir.values'].sudo().set_default(
+ 'sale.config.settings', 'so_expiration_date', self.so_expiration_date)
+
+ @api.multi
+ def set_default_so_expiration_date_start(self):
+ return self.env['ir.values'].sudo().set_default(
+ 'sale.config.settings', 'so_expiration_date_start', self.so_expiration_date_start)
+
+ @api.multi
+ def set_default_so_expiration_date_no(self):
+ a = self.env['ir.values'].get_default('sale.config.settings', 'so_expiration_date', self.so_expiration_date)
+ if a == 0:
+ so_expiration_date_no = False
+ elif a == 1:
+ so_expiration_date_no = 14
+ else:
+ so_expiration_date_no = self.so_expiration_date_no
+ return self.env['ir.values'].sudo().set_default(
+ 'sale.config.settings', 'so_expiration_date_no', so_expiration_date_no)
+
+
diff --git a/quotation_handler/static/description/banner.jpg b/quotation_handler/static/description/banner.jpg
new file mode 100644
index 000000000..33b4c1ed7
Binary files /dev/null and b/quotation_handler/static/description/banner.jpg differ
diff --git a/quotation_handler/static/description/cybro_logo.png b/quotation_handler/static/description/cybro_logo.png
new file mode 100644
index 000000000..bb309114c
Binary files /dev/null and b/quotation_handler/static/description/cybro_logo.png differ
diff --git a/quotation_handler/static/description/editable line.png b/quotation_handler/static/description/editable line.png
new file mode 100644
index 000000000..8f023fa34
Binary files /dev/null and b/quotation_handler/static/description/editable line.png differ
diff --git a/quotation_handler/static/description/email template.png b/quotation_handler/static/description/email template.png
new file mode 100644
index 000000000..71029c6d3
Binary files /dev/null and b/quotation_handler/static/description/email template.png differ
diff --git a/quotation_handler/static/description/icon.png b/quotation_handler/static/description/icon.png
new file mode 100644
index 000000000..17aa2186d
Binary files /dev/null and b/quotation_handler/static/description/icon.png differ
diff --git a/quotation_handler/static/description/index.html b/quotation_handler/static/description/index.html
new file mode 100644
index 000000000..b3acf358a
--- /dev/null
+++ b/quotation_handler/static/description/index.html
@@ -0,0 +1,189 @@
+
+
☑ Automatically set expiration date for quotation.
+
☑ Email template contains the expiration date.
+
+
+
+
+
+
+
+
Quotation in "Quotation Sent" state
+
+
+
+
+
+
+
+
+ The clients will require negotiations whenever we sent a quotation to them.In such cases we need to edit the Quotation's order lines.
+ We have included the 'Revise the Quotation' button for it. The order lines can be edited by a click on this button.
+ At the same time a history or copy of the quotation will also be generated automatically.We can track the history using the smart buttons.
+
+
+
+
+
+
+
+
+
+
Quotation in "Revised Quotation" state
+
+
+
+
+
+
+
+
+ In the Revised Quotation state, we can edit the order lines and resent to the client.
+
Quotation Sent ---> Revised Quotation ---> Quotation Sent
+
The smart button on the top right of the form will provide the entire revised history of quotation.
+ The revised quotation will be indicated by a change in name format as (initial name/R1) in a recurring manner.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
In the Quotation Sent state we can't edit the Order lines. When we need to revise just click on
+ the "Revise the Quotation" button.
+
+
+
+
+
+
+
+
In the Revised Quotation state we can edit the order lines and resend it through mail or
+ take print out with new order lines.
+
+
+
+
+
+
+
+
Quotation History
+
+
+
+
Smart button redirect you to the Quotation History.
+
+
+
Tree view of the Revised Quotations of the particular parent quotation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Quotation in "Revised" state
+
+
+
+
+
+
+
+
+ In this state we can't edit anything, it's just for a view.
+
+
+
+
+
+
+
+
+
+
Quotation Email template
+
+
+
+
+
+
+
+ If we gave expiration date then it will mention in the Email
+
+ Every quotations have a expiration date which we set manually.On configuring the above shown settings we can
+ automatically set the expiration date very easily.
+
+
No Expiration date: No changes(we have to set the date manually)
+
Default 14 days: The expiration date calculated from Quotation Creation Date or form Quotation Sent Date is set for 14 days.
+
Created as company rule: The quotation will expire as per the custom days set by user from Quotation Creation Date or from the Quotation Sent Date .
+
+
Expiration Date Calculated From : Choose either of the two, Quotation Creation Date or Quotation Sent Date
+ Create a Quotation, the first step of a new sale.
+
+ Once the quotation is confirmed, it becomes a sales order.
+ You'll be able to invoice it and collect payments.
+ From the Sales Orders menu, you can track delivery
+ orders or services.
+