@ -0,0 +1,48 @@ | 
				
			|||
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg | 
				
			|||
    :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html | 
				
			|||
    :alt: License: AGPL-3 | 
				
			|||
 | 
				
			|||
Purchase Recurring Orders | 
				
			|||
========================= | 
				
			|||
This module allows you to create recurring orders for purchases. | 
				
			|||
 | 
				
			|||
Configuration | 
				
			|||
============= | 
				
			|||
No additional configuration required | 
				
			|||
 | 
				
			|||
Company | 
				
			|||
------- | 
				
			|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | 
				
			|||
 | 
				
			|||
License | 
				
			|||
------- | 
				
			|||
Affero General Public License v3.0 (AGPL v3) | 
				
			|||
 | 
				
			|||
https://www.gnu.org/licenses/agpl-3.0-standalone.html | 
				
			|||
 | 
				
			|||
Credits | 
				
			|||
------- | 
				
			|||
Developer: (V14) Ruksana P, Contact:odoo@cybrosys.com | 
				
			|||
 | 
				
			|||
Contacts | 
				
			|||
-------- | 
				
			|||
* Mail Contact : odoo@cybrosys.com | 
				
			|||
* Website : https://cybrosys.com | 
				
			|||
 | 
				
			|||
Bug Tracker | 
				
			|||
----------- | 
				
			|||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if | 
				
			|||
your issue has already been reported. | 
				
			|||
 | 
				
			|||
Maintainer | 
				
			|||
========== | 
				
			|||
.. image:: https://cybrosys.com/images/logo.png | 
				
			|||
   :target: https://cybrosys.com | 
				
			|||
 | 
				
			|||
This module is maintained by Cybrosys Technologies. | 
				
			|||
 | 
				
			|||
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ | 
				
			|||
 | 
				
			|||
Further information | 
				
			|||
=================== | 
				
			|||
HTML Description: `<static/description/index.html>`__ | 
				
			|||
@ -0,0 +1,23 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
################################################################################ | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			|||
#    Author: Ruksana P (odoo@cybrosys.com) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU AFFERO | 
				
			|||
#    GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | 
				
			|||
#    (AGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
################################################################################ | 
				
			|||
from . import models | 
				
			|||
from . import wizards | 
				
			|||
@ -0,0 +1,48 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
################################################################################ | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			|||
#    Author: Ruksana P (odoo@cybrosys.com) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU AFFERO | 
				
			|||
#    GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | 
				
			|||
#    (AGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
################################################################################ | 
				
			|||
{ | 
				
			|||
    'name': 'Purchase Recurring Orders', | 
				
			|||
    'version': '14.0.1.0.0', | 
				
			|||
    'category': 'Purchases', | 
				
			|||
    'summary': 'Helps to create purchase recurring orders', | 
				
			|||
    'description': """ This module Helps to create recurring orders for  | 
				
			|||
     Purchases based on the information provided.""", | 
				
			|||
    'author': 'Cybrosys Techno Solutions', | 
				
			|||
    'company': 'Cybrosys Techno Solutions', | 
				
			|||
    'maintainer': 'Cybrosys Techno Solutions', | 
				
			|||
    'website': 'https://www.cybrosys.com', | 
				
			|||
    'depends': ['purchase'], | 
				
			|||
    'data': [ | 
				
			|||
        'security/ir.model.access.csv', | 
				
			|||
        'data/ir_cron_data.xml', | 
				
			|||
        'data/ir_sequence_data.xml', | 
				
			|||
        'wizards/agreement_renewal_views.xml', | 
				
			|||
        'views/purchase_recurring_agreement_views.xml', | 
				
			|||
        'views/purchase_order_views.xml', | 
				
			|||
        'views/res_partner_views.xml', | 
				
			|||
    ], | 
				
			|||
    'images': ['static/description/banner.png'], | 
				
			|||
    'license': 'AGPL-3', | 
				
			|||
    'installable': True, | 
				
			|||
    'auto_install': False, | 
				
			|||
    'application': False, | 
				
			|||
} | 
				
			|||
@ -0,0 +1,44 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8"?> | 
				
			|||
<odoo noupdate="1"> | 
				
			|||
    <!--      Scheduled Action for Prolongation check of recurring orders | 
				
			|||
    agreements--> | 
				
			|||
    <record id="ir_cron_recurring_orders_prolong_check" model="ir.cron"> | 
				
			|||
        <field name="name">Prolongation Check for Recurring Orders | 
				
			|||
            Agreements | 
				
			|||
        </field> | 
				
			|||
        <field name="model_id" ref="model_purchase_recurring_agreement"/> | 
				
			|||
        <field name="type">ir.actions.server</field> | 
				
			|||
        <field name="state">code</field> | 
				
			|||
        <field name="code">model.revise_agreements_expirations_planned() | 
				
			|||
        </field> | 
				
			|||
        <field name="interval_number">1</field> | 
				
			|||
        <field name="doall" eval="False"/> | 
				
			|||
        <field name="interval_type">days</field> | 
				
			|||
        <field name="numbercall">-1</field> | 
				
			|||
    </record> | 
				
			|||
    <!--      Scheduled Action for Confirming current orders--> | 
				
			|||
    <record id="ir_cron_recurring_orders_confirm_orders" model="ir.cron"> | 
				
			|||
        <field name="name">Confirm Current Orders</field> | 
				
			|||
        <field name="model_id" ref="model_purchase_recurring_agreement"/> | 
				
			|||
        <field name="type">ir.actions.server</field> | 
				
			|||
        <field name="state">code</field> | 
				
			|||
        <field name="code">model.confirm_current_orders_planned()</field> | 
				
			|||
        <field name="interval_number">1</field> | 
				
			|||
        <field name="doall" eval="False"/> | 
				
			|||
        <field name="interval_type">days</field> | 
				
			|||
        <field name="numbercall">-1</field> | 
				
			|||
    </record> | 
				
			|||
    <!--      Scheduled Action for Generating recurring orders for next | 
				
			|||
    year--> | 
				
			|||
    <record id="ir_cron_recurring_orders_generate_orders" model="ir.cron"> | 
				
			|||
        <field name="name">Generate Recurring Orders for Next Year</field> | 
				
			|||
        <field name="model_id" ref="model_purchase_recurring_agreement"/> | 
				
			|||
        <field name="type">ir.actions.server</field> | 
				
			|||
        <field name="state">code</field> | 
				
			|||
        <field name="code">model.generate_next_orders_planned()</field> | 
				
			|||
        <field name="interval_number">1</field> | 
				
			|||
        <field name="interval_type">days</field> | 
				
			|||
        <field name="numbercall">-1</field> | 
				
			|||
    </record> | 
				
			|||
</odoo> | 
				
			|||
 | 
				
			|||
@ -0,0 +1,11 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8"?> | 
				
			|||
<odoo noupdate="1"> | 
				
			|||
    <!--  Sequence Generator--> | 
				
			|||
    <record model="ir.sequence" id="ir_sequence_recurring_agreement"> | 
				
			|||
        <field name="name">Agreement Sequence</field> | 
				
			|||
        <field name="code">purchase.r_o.agreement.sequence</field> | 
				
			|||
        <field name="padding">4</field> | 
				
			|||
        <field name="prefix">AG-%(y)s-</field> | 
				
			|||
        <field name="company_id" eval="False"/> | 
				
			|||
    </record> | 
				
			|||
</odoo> | 
				
			|||
@ -0,0 +1,6 @@ | 
				
			|||
## Module <purchase_recurring_orders> | 
				
			|||
 | 
				
			|||
#### 14.08.2023 | 
				
			|||
#### Version 14.0.1.0.0 | 
				
			|||
#### ADD | 
				
			|||
- Initial commit for Purchase Recurring Orders | 
				
			|||
@ -0,0 +1,26 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
################################################################################ | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			|||
#    Author: Ruksana P (odoo@cybrosys.com) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU AFFERO | 
				
			|||
#    GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | 
				
			|||
#    (AGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
################################################################################ | 
				
			|||
from . import agreement_renewal_line | 
				
			|||
from . import purchase_order | 
				
			|||
from . import purchase_recurring_agreement | 
				
			|||
from . import recurring_agreement_line | 
				
			|||
from . import res_partner | 
				
			|||
@ -0,0 +1,36 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
################################################################################ | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			|||
#    Author: Ruksana P (odoo@cybrosys.com) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU AFFERO | 
				
			|||
#    GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | 
				
			|||
#    (AGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
################################################################################ | 
				
			|||
from odoo import fields, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class AgreementRenewalLine(models.Model): | 
				
			|||
    """ Purchase recurring agreement renewal records """ | 
				
			|||
    _name = 'agreement.renewal.line' | 
				
			|||
    _description = "Purchase Agreement Renewal Records" | 
				
			|||
 | 
				
			|||
    recurring_agreement_id = fields.Many2one('purchase.recurring.agreement', | 
				
			|||
                                             string='Agreement Reference', | 
				
			|||
                                             ondelete='cascade', | 
				
			|||
                                             help='Recurring agreement for ' | 
				
			|||
                                                  'renewal') | 
				
			|||
    date = fields.Datetime(string='Date', help="Date of the Renewal") | 
				
			|||
    comments = fields.Char(string='Comments', size=200, help='Renewal comments') | 
				
			|||
@ -0,0 +1,83 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
################################################################################ | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			|||
#    Author: Ruksana P  (odoo@cybrosys.com) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU AFFERO | 
				
			|||
#    GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | 
				
			|||
#    (AGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
################################################################################ | 
				
			|||
from odoo import api, fields, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class PurchaseOrder(models.Model): | 
				
			|||
    """ Purchase order inherited for adding two fields is_agreement and | 
				
			|||
     recurring_agreement_id """ | 
				
			|||
    _inherit = 'purchase.order' | 
				
			|||
 | 
				
			|||
    is_agreement = fields.Boolean(string='From Agreement?', copy=False, | 
				
			|||
                                  help="Checking this box represents that " | 
				
			|||
                                       "purchase order is from agreement.") | 
				
			|||
    recurring_agreement_id = fields.Many2one('purchase.recurring.agreement', | 
				
			|||
                                             string='Agreement Reference', | 
				
			|||
                                             help="This indicates the Purchase" | 
				
			|||
                                                  " Agreement", | 
				
			|||
                                             ondelete='restrict') | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def _prepare_agreement_vals(self, order): | 
				
			|||
        """ Method for creating agreement values""" | 
				
			|||
        return { | 
				
			|||
            'partner_id': order.partner_id.id, | 
				
			|||
            'company_id': order.company_id.id, | 
				
			|||
            'start_date': fields.Datetime.now(), | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def _prepare_agreement_line_vals(self, order_ids, agreement): | 
				
			|||
        """ Returns the Agreement Line Values in a Dictionary Format""" | 
				
			|||
        return { | 
				
			|||
            'recurring_agreement_id': agreement.id, | 
				
			|||
            'product_id': order_ids.product_id.id, | 
				
			|||
            'quantity': order_ids.product_qty, | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    def action_generate_agreement(self): | 
				
			|||
        """Generates Purchase Recurring Agreement""" | 
				
			|||
        agreements = [] | 
				
			|||
        for purchase_order in self: | 
				
			|||
            agreement_vals = self._prepare_agreement_vals(purchase_order) | 
				
			|||
            agreement = self.env[ | 
				
			|||
                'purchase.recurring.agreement'].create(agreement_vals) | 
				
			|||
            agreements.append(agreement) | 
				
			|||
            for order_id in purchase_order.order_line: | 
				
			|||
                agreement_line_vals = self._prepare_agreement_line_vals( | 
				
			|||
                    order_id, agreement) | 
				
			|||
                self.env['recurring.agreement.line'].create(agreement_line_vals) | 
				
			|||
        if len(agreements) == 1: | 
				
			|||
            view = self.env.ref( | 
				
			|||
                'purchase_recurring_orders.' | 
				
			|||
                'purchase_recurring_agreement_view_form') | 
				
			|||
            return { | 
				
			|||
                'type': 'ir.actions.act_window', | 
				
			|||
                'view_mode': 'form', | 
				
			|||
                'res_model': 'purchase.recurring.agreement', | 
				
			|||
                'views': [(view.id, 'form')], | 
				
			|||
                'view_id': view.id, | 
				
			|||
                'target': 'new', | 
				
			|||
                'res_id': agreement[0].id, | 
				
			|||
                'nodestroy': True, | 
				
			|||
            } | 
				
			|||
        return True | 
				
			|||
@ -0,0 +1,403 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
################################################################################ | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			|||
#    Author: Ruksana P (odoo@cybrosys.com) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU AFFERO | 
				
			|||
#    GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | 
				
			|||
#    (AGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
################################################################################ | 
				
			|||
from datetime import timedelta | 
				
			|||
from dateutil.relativedelta import relativedelta | 
				
			|||
from odoo import api, exceptions, fields, models, _ | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class PurchaseRecurringAgreement(models.Model): | 
				
			|||
    """Model for generating purchase recurring agreement""" | 
				
			|||
    _name = 'purchase.recurring.agreement' | 
				
			|||
    _inherit = 'mail.thread' | 
				
			|||
    _description = "Purchase Recurring Agreement" | 
				
			|||
 | 
				
			|||
    def _default_company_id(self): | 
				
			|||
        """Returns the Current Company id""" | 
				
			|||
        company = self.env['res.company']._company_default_get('purchase') | 
				
			|||
        return company | 
				
			|||
 | 
				
			|||
    name = fields.Char(string='Sequence Number', index=True, size=32, | 
				
			|||
                       help="Number of agreement. Keep empty to get the " | 
				
			|||
                            "number assigned by a sequence.", copy=False, | 
				
			|||
                       default=_('New'), readonly=True) | 
				
			|||
    active = fields.Boolean(string='Active', default=True, | 
				
			|||
                            help='Unchecking this field, quotation for ' | 
				
			|||
                                 'corresponding product is not generated') | 
				
			|||
    partner_id = fields.Many2one('res.partner', string='Supplier', index=True, | 
				
			|||
                                 change_default=True, required=True, | 
				
			|||
                                 help="Supplier you are making the agreement") | 
				
			|||
    company_id = fields.Many2one('res.company', string='Company', required=True, | 
				
			|||
                                 help="Company that signs the agreement", | 
				
			|||
                                 default=_default_company_id) | 
				
			|||
    start_date = fields.Date(string='Start Date', index=True, copy=False, | 
				
			|||
                             help="Beginning of the agreement. Keep empty to " | 
				
			|||
                                  "use the current date") | 
				
			|||
    prolong = fields.Selection( | 
				
			|||
        selection=[('recurrent', 'Renewable Fixed Term'), | 
				
			|||
                   ('unlimited', 'Unlimited Term'), | 
				
			|||
                   ('fixed', 'Fixed Term')], | 
				
			|||
        string='Prolongation', default='unlimited', | 
				
			|||
        help="Sets the term of the agreement. 'Renewable fixed term': It sets " | 
				
			|||
             "a fixed term, but with possibility of manual renew; 'Unlimited " | 
				
			|||
             "term': Renew is made automatically; 'Fixed term': The term is " | 
				
			|||
             "fixed and there is no possibility to renew.") | 
				
			|||
    end_date = fields.Date(string='End date', help="End Date of the Agreement") | 
				
			|||
    prolong_interval = fields.Integer( | 
				
			|||
        string='Interval', default=1, | 
				
			|||
        help="Interval in time units to prolong the agreement until new " | 
				
			|||
             "renewable (that is automatic for unlimited term, manual for " | 
				
			|||
             "renewable fixed term).") | 
				
			|||
    prolong_unit = fields.Selection([('days', 'Days'), ('weeks', 'Weeks'), | 
				
			|||
                                     ('months', 'Months'), ('years', 'Years')], | 
				
			|||
                                    string='Interval Unit', default='years', | 
				
			|||
                                    help='Time unit for the prolongation ' | 
				
			|||
                                         'interval') | 
				
			|||
    agreement_line_ids = fields.One2many('recurring.agreement.line', | 
				
			|||
                                         inverse_name='recurring_agreement_id', | 
				
			|||
                                         string='Agreement Lines', | 
				
			|||
                                         help='Agreement product records') | 
				
			|||
    order_ids = fields.One2many('purchase.order', copy=False, readonly=True, | 
				
			|||
                                inverse_name='recurring_agreement_id', | 
				
			|||
                                string='Orders') | 
				
			|||
    renewal_ids = fields.One2many('agreement.renewal.line', readonly=True, | 
				
			|||
                                  copy=False, sring='Renewal Lines', | 
				
			|||
                                  help='Renewal records', | 
				
			|||
                                  inverse_name='recurring_agreement_id') | 
				
			|||
    last_renovation_date = fields.Datetime( | 
				
			|||
        string='Last Renovation Date', | 
				
			|||
        help="Last date when agreement was renewed (same as start date if not " | 
				
			|||
             "renewed)") | 
				
			|||
    next_expiration_date = fields.Datetime( | 
				
			|||
        compute="_compute_next_expiration_date", | 
				
			|||
        help="Date when agreement will expired ", | 
				
			|||
        string='Next Expiration Date') | 
				
			|||
    state = fields.Selection([('empty', 'Without Orders'), | 
				
			|||
                              ('first', 'First Order Created'), | 
				
			|||
                              ('orders', 'With Orders')], string='State', | 
				
			|||
                             readonly=True, default='empty', | 
				
			|||
                             help="Indicates the state of recurring agreement") | 
				
			|||
    renewal_state = fields.Selection([('not_renewed', 'Agreement not Renewed'), | 
				
			|||
                                      ('renewed', 'Agreement Renewed')], | 
				
			|||
                                     string='Renewal State', readonly=True, | 
				
			|||
                                     help="Renewal status of the recurring" | 
				
			|||
                                          " agreement", default='not_renewed') | 
				
			|||
    notes = fields.Text('Notes', help="Notes regarding renewal agreement") | 
				
			|||
    order_count = fields.Integer(compute='_compute_order_count', | 
				
			|||
                                 string='Order Count', | 
				
			|||
                                 help="Indicates the no. of orders generated " | 
				
			|||
                                      "with this agreement") | 
				
			|||
    _sql_constraints = [ | 
				
			|||
        ('name_uniq', 'unique(name)', 'Agreement Number Must be Unique !'), | 
				
			|||
    ] | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def _get_next_term_date(self, date, unit, interval): | 
				
			|||
        """Returns the Next Term Date""" | 
				
			|||
        if unit == 'days': | 
				
			|||
            date = date + timedelta(days=interval) | 
				
			|||
        elif unit == 'weeks': | 
				
			|||
            date = date + timedelta(weeks=interval) | 
				
			|||
        elif unit == 'months': | 
				
			|||
            date = date + relativedelta(months=interval) | 
				
			|||
        elif unit == 'years': | 
				
			|||
            date = date + relativedelta(years=interval) | 
				
			|||
        return date | 
				
			|||
 | 
				
			|||
    def _compute_next_expiration_date(self): | 
				
			|||
        """Calculates the Next Expiration Date According to the Prolongation | 
				
			|||
        Unit Chosen""" | 
				
			|||
        for agreement in self: | 
				
			|||
            if agreement.prolong == 'fixed': | 
				
			|||
                agreement.next_expiration_date = agreement.end_date | 
				
			|||
            elif agreement.prolong == 'unlimited': | 
				
			|||
                now = fields.Date.from_string(fields.Datetime.today()) | 
				
			|||
                date = self._get_next_term_date( | 
				
			|||
                    fields.Date.from_string(agreement.start_date), | 
				
			|||
                    agreement.prolong_unit, agreement.prolong_interval) | 
				
			|||
                while date < now: | 
				
			|||
                    date = self._get_next_term_date( | 
				
			|||
                        date, agreement.prolong_unit, | 
				
			|||
                        agreement.prolong_interval) | 
				
			|||
                agreement.next_expiration_date = date | 
				
			|||
            else: | 
				
			|||
                agreement.next_expiration_date = self._get_next_term_date( | 
				
			|||
                    fields.Datetime.from_string( | 
				
			|||
                        agreement.last_renovation_date or | 
				
			|||
                        agreement.start_date), | 
				
			|||
                    agreement.prolong_unit, agreement.prolong_interval) | 
				
			|||
 | 
				
			|||
    def _compute_order_count(self): | 
				
			|||
        """Finds the count of orders generated from the Agreement""" | 
				
			|||
        for record in self: | 
				
			|||
            record.order_count = self.env['purchase.order'].search_count( | 
				
			|||
                [('recurring_agreement_id', '=', self.id)]) | 
				
			|||
 | 
				
			|||
    @api.constrains('start_date', 'end_date') | 
				
			|||
    def _check_dates(self): | 
				
			|||
        """Method for ensuring start date will be always less than | 
				
			|||
         or equal to end date""" | 
				
			|||
        for record in self: | 
				
			|||
            if record.end_date and record.end_date < record.start_date: | 
				
			|||
                raise exceptions.Warning( | 
				
			|||
                    _('Agreement End Date must be Greater than Start Date')) | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def create(self, vals): | 
				
			|||
        """Function that supering create function""" | 
				
			|||
        if not vals.get('start_date'): | 
				
			|||
            vals['start_date'] = fields.Datetime.today() | 
				
			|||
        if vals.get('name', _('New')) == _('New'): | 
				
			|||
            vals['name'] = self.env['ir.sequence'].get( | 
				
			|||
                'purchase.r_o.agreement.sequence') | 
				
			|||
        return super().create(vals) | 
				
			|||
 | 
				
			|||
    def write(self, vals): | 
				
			|||
        """Function that supering write function""" | 
				
			|||
        value = super().write(vals) | 
				
			|||
        if (any(vals.get(x) is not None for x in | 
				
			|||
                ['active', 'name', 'agreement_line_ids', 'prolong', | 
				
			|||
                 'end_date', | 
				
			|||
                 'prolong_interval', 'prolong_unit', 'partner_id'])): | 
				
			|||
            self.unlink_orders(fields.Datetime.today()) | 
				
			|||
        return value | 
				
			|||
 | 
				
			|||
    @api.returns('self', lambda value: value.id) | 
				
			|||
    def copy(self, default=None): | 
				
			|||
        default = dict(default or {}) | 
				
			|||
        if 'name' not in default: | 
				
			|||
            default['name'] = _("%s (Copy)") % self.name | 
				
			|||
        return super().copy(default=default) | 
				
			|||
 | 
				
			|||
    def unlink(self): | 
				
			|||
        """Function that supering unlink function which will unlink Self and | 
				
			|||
        the Current record""" | 
				
			|||
        for agreement in self: | 
				
			|||
            if any(agreement.mapped('order_ids')): | 
				
			|||
                raise exceptions.Warning( | 
				
			|||
                    _('You Cannot Remove Agreements with Confirmed Orders!')) | 
				
			|||
        self.unlink_orders(fields.Datetime.from_string(fields.Datetime.today())) | 
				
			|||
        return models.Model.unlink(self) | 
				
			|||
 | 
				
			|||
    @api.onchange('start_date') | 
				
			|||
    def _onchange_last_renovation_date(self): | 
				
			|||
        """Method for updating last renovation date""" | 
				
			|||
        self.last_renovation_date = self.start_date | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def revise_agreements_expirations_planned(self): | 
				
			|||
        """Method for changing the prolong as unlimited""" | 
				
			|||
        for agreement in self.search([('prolong', '=', 'unlimited')]): | 
				
			|||
            if agreement.next_expiration_date <= fields.Datetime.today(): | 
				
			|||
                agreement.write({'prolong': 'unlimited'}) | 
				
			|||
        return True | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def _prepare_purchase_order_vals(self, agreement, date): | 
				
			|||
        """Creates purchase order values""" | 
				
			|||
        # Order Values | 
				
			|||
        order_vals = {'date_order': date, | 
				
			|||
                      'origin': agreement.name, | 
				
			|||
                      'partner_id': agreement.partner_id.id, | 
				
			|||
                      'state': 'draft', 'company_id': agreement.company_id.id, | 
				
			|||
                      'is_agreement': True, | 
				
			|||
                      'recurring_agreement_id': agreement.id, | 
				
			|||
                      'date_planned': date, | 
				
			|||
                      'payment_term_id': agreement.partner_id. | 
				
			|||
                      property_supplier_payment_term_id.id, | 
				
			|||
                      'currency_id': | 
				
			|||
                          agreement.partner_id.property_purchase_currency_id.id | 
				
			|||
                          or self.env.user.company_id.currency_id.id, | 
				
			|||
                      'user_id': agreement.partner_id.user_id.id} | 
				
			|||
        return order_vals | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def _prepare_purchase_order_line_vals(self, agreement_line_ids, order): | 
				
			|||
        """Returns the Purchase Order Line Values as a Dictionary Which can be | 
				
			|||
         Used While creating the Purchase Order""" | 
				
			|||
        product = agreement_line_ids.product_id | 
				
			|||
        product_lang = product.with_context({ | 
				
			|||
            'lang': order.partner_id.lang, | 
				
			|||
            'partner_id': order.partner_id.id, | 
				
			|||
        }) | 
				
			|||
        fpos = order.fiscal_position_id | 
				
			|||
        # Order Line Values as a Dictionary | 
				
			|||
        order_line_vals = { | 
				
			|||
            'order_id': order.id, | 
				
			|||
            'product_id': product.id, | 
				
			|||
            'product_qty': agreement_line_ids.quantity, | 
				
			|||
            'date_planned': order.date_planned, | 
				
			|||
            'price_unit': product._get_tax_included_unit_price( | 
				
			|||
                order.company_id, order.currency_id, order.date_order, | 
				
			|||
                'purchase', | 
				
			|||
                fiscal_position=order.fiscal_position_id, | 
				
			|||
                product_uom=product.uom_po_id), | 
				
			|||
            'product_uom': product.uom_po_id.id or product.uom_id.id, | 
				
			|||
            'name': product_lang.display_name, | 
				
			|||
            'taxes_id': fpos.map_tax( | 
				
			|||
                product.supplier_taxes_id.filtered( | 
				
			|||
                    lambda r: r.company_id.id == self.company_id.id).ids) | 
				
			|||
        } | 
				
			|||
        # product price changed if specific price is added | 
				
			|||
        if agreement_line_ids.specific_price: | 
				
			|||
            order_line_vals['price_unit'] = agreement_line_ids.specific_price | 
				
			|||
        order_line_vals['taxes_id'] = [ | 
				
			|||
            (6, 0, tuple(order_line_vals['taxes_id']))] | 
				
			|||
        # product price changed if specific price is added | 
				
			|||
        if agreement_line_ids.additional_description: | 
				
			|||
            order_line_vals['name'] += " %s" % ( | 
				
			|||
                agreement_line_ids.additional_description) | 
				
			|||
        return order_line_vals | 
				
			|||
 | 
				
			|||
    def create_order(self, date, agreement_lines): | 
				
			|||
        """Create Purchase Order from Recurring Agreement """ | 
				
			|||
        self.ensure_one() | 
				
			|||
        order_line_obj = self.env['purchase.order.line'].with_context( | 
				
			|||
            company_id=self.company_id.id) | 
				
			|||
        order_vals = self._prepare_purchase_order_vals(self, date) | 
				
			|||
        order = self.env['purchase.order'].create(order_vals) | 
				
			|||
        for agreement_line in agreement_lines: | 
				
			|||
            # Create Purchase Order Line Values | 
				
			|||
            order_line_vals = self._prepare_purchase_order_line_vals( | 
				
			|||
                agreement_line, order) | 
				
			|||
            order_line_obj.create(order_line_vals) | 
				
			|||
        agreement_lines.write({'last_order_date': fields.Datetime.today()}) | 
				
			|||
        if self.state != 'orders': | 
				
			|||
            self.state = 'orders' | 
				
			|||
        return order | 
				
			|||
 | 
				
			|||
    def _get_next_order_date(self, line, start_date): | 
				
			|||
        """Return The date of Next Purchase order generated from the | 
				
			|||
         Agreement""" | 
				
			|||
        self.ensure_one() | 
				
			|||
        next_date = fields.Datetime.from_string(self.start_date) | 
				
			|||
        while next_date <= start_date: | 
				
			|||
            next_date = self._get_next_term_date( | 
				
			|||
                next_date, line.ordering_unit, line.ordering_interval) | 
				
			|||
        return next_date | 
				
			|||
 | 
				
			|||
    def generate_agreement_orders(self, start_date, end_date): | 
				
			|||
        """Method for generating agreement orders""" | 
				
			|||
        self.ensure_one() | 
				
			|||
        if not self.active: | 
				
			|||
            return | 
				
			|||
        lines_to_order = {} | 
				
			|||
        # Get next expiration date | 
				
			|||
        exp_date = fields.Datetime.from_string(self.next_expiration_date) | 
				
			|||
        if exp_date < end_date and self.prolong != 'unlimited': | 
				
			|||
            end_date = exp_date | 
				
			|||
        for line in self.agreement_line_ids: | 
				
			|||
            if not line.is_active: | 
				
			|||
                continue | 
				
			|||
            # Get Date of Next Order | 
				
			|||
            next_order_date = self._get_next_order_date(line, start_date) | 
				
			|||
            while next_order_date <= end_date: | 
				
			|||
                if not lines_to_order.get(next_order_date): | 
				
			|||
                    lines_to_order[next_order_date] = self.env[ | 
				
			|||
                        'recurring.agreement.line'] | 
				
			|||
                lines_to_order[next_order_date] |= line | 
				
			|||
                next_order_date = self._get_next_order_date( | 
				
			|||
                    line, next_order_date) | 
				
			|||
        dates = lines_to_order.keys() | 
				
			|||
        sorted(dates) | 
				
			|||
        for date in dates: | 
				
			|||
            order = self.order_ids.filtered( | 
				
			|||
                lambda x: ( | 
				
			|||
                        fields.Date.to_string( | 
				
			|||
                            fields.Datetime.from_string(x.date_order)) == | 
				
			|||
                        fields.Date.to_string(date))) | 
				
			|||
            if not order: | 
				
			|||
                self.create_order( | 
				
			|||
                    fields.Datetime.to_string(date), lines_to_order[date]) | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def generate_next_orders_planned(self, years=1, start_date=None): | 
				
			|||
        """Method for generating the planned orders""" | 
				
			|||
        if start_date: | 
				
			|||
            start_date = fields.Datetime.from_string(start_date) | 
				
			|||
        self.search([]).generate_next_orders( | 
				
			|||
            years=years, start_date=start_date) | 
				
			|||
 | 
				
			|||
    def action_generate_next_year_orders(self): | 
				
			|||
        """This will Generate Orders for Next year""" | 
				
			|||
        return self.generate_next_orders(years=1) | 
				
			|||
 | 
				
			|||
    def generate_next_orders(self, years=1, start_date=None): | 
				
			|||
        if not start_date: | 
				
			|||
            start_date = fields.Datetime.from_string(fields.Date.today()) | 
				
			|||
        end_date = start_date + relativedelta(years=years) | 
				
			|||
        for agreement in self: | 
				
			|||
            agreement.generate_agreement_orders(start_date, end_date) | 
				
			|||
        return True | 
				
			|||
 | 
				
			|||
    @api.model | 
				
			|||
    def confirm_current_orders_planned(self): | 
				
			|||
        """This will Confirm All Orders satisfying the Domain""" | 
				
			|||
        tomorrow = fields.Date.to_string( | 
				
			|||
            fields.Datetime.from_string(fields.Datetime.today()) + timedelta( | 
				
			|||
                days=1)) | 
				
			|||
        orders = self.env['purchase.order'].search([ | 
				
			|||
            ('recurring_agreement_id', '!=', False), | 
				
			|||
            ('state', 'in', ('draft', 'sent')), | 
				
			|||
            ('date_order', '<', tomorrow) | 
				
			|||
        ]) | 
				
			|||
        for order in orders: | 
				
			|||
            order.signal_workflow('order_confirm') | 
				
			|||
 | 
				
			|||
    def unlink_orders(self, start_date): | 
				
			|||
        """ Remove the relation between ``self`` and the related record.""" | 
				
			|||
        orders = self.mapped('order_ids').filtered( | 
				
			|||
            lambda x: (x.state in ('draft', 'sent') and | 
				
			|||
                       x.date_order >= start_date)) | 
				
			|||
        orders.unlink() | 
				
			|||
 | 
				
			|||
    def action_generate_initial_order(self): | 
				
			|||
        """This will generate the Initial purchase Order from the Purchase | 
				
			|||
        Agreement""" | 
				
			|||
        self.ensure_one() | 
				
			|||
        agreement_lines = self.mapped('agreement_line_ids').filtered( | 
				
			|||
            'is_active') | 
				
			|||
        order = self.create_order(self.start_date, agreement_lines) | 
				
			|||
        self.write({'state': 'first'}) | 
				
			|||
        order.button_confirm() | 
				
			|||
        return { | 
				
			|||
            'domain': "[('id', '=', %s)]" % order.id, | 
				
			|||
            'view_type': 'form', | 
				
			|||
            'view_mode': 'form', | 
				
			|||
            'res_model': 'purchase.order', | 
				
			|||
            'context': self.env.context, | 
				
			|||
            'res_id': order.id, | 
				
			|||
            'view_id': [self.env.ref('purchase.purchase_order_form').id], | 
				
			|||
            'type': 'ir.actions.act_window', | 
				
			|||
            'nodestroy': True | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
    def action_view_purchase_orders(self): | 
				
			|||
        """Returns All Orders Generated from the Agreement""" | 
				
			|||
        self.ensure_one() | 
				
			|||
        return { | 
				
			|||
            'type': 'ir.actions.act_window', | 
				
			|||
            'name': 'Orders', | 
				
			|||
            'views': [[False, 'tree'], [False, 'form']], | 
				
			|||
            'res_model': 'purchase.order', | 
				
			|||
            'domain': [('recurring_agreement_id', '=', self.id)], | 
				
			|||
            'context': "{'create': False}" | 
				
			|||
        } | 
				
			|||
@ -0,0 +1,73 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
################################################################################ | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			|||
#    Author: Ruksana P (odoo@cybrosys.com) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU AFFERO | 
				
			|||
#    GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | 
				
			|||
#    (AGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
################################################################################ | 
				
			|||
from odoo import fields, models | 
				
			|||
from odoo.addons.base.models.decimal_precision import dp | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class RecurringAgreementLine(models.Model): | 
				
			|||
    """Model generating purchase recurring agreement line""" | 
				
			|||
    _name = 'recurring.agreement.line' | 
				
			|||
    _description = 'Recurring Agreement Records' | 
				
			|||
 | 
				
			|||
    is_active = fields.Boolean(string='Active', default=True, | 
				
			|||
                               help='Unchecking this field, this quotation for' | 
				
			|||
                                    'this product is not generated') | 
				
			|||
    recurring_agreement_id = fields.Many2one('purchase.recurring.agreement', | 
				
			|||
                                             string='Agreement Reference', | 
				
			|||
                                             ondelete='cascade', | 
				
			|||
                                             help="The Corresponding purchase" | 
				
			|||
                                                  " order agreement") | 
				
			|||
    product_id = fields.Many2one('product.product', string='Product', | 
				
			|||
                                 ondelete='restrict', required=True) | 
				
			|||
    uom_id = fields.Many2one(related='product_id.product_tmpl_id.uom_id', | 
				
			|||
                             help="UOM of the product", string="Uom") | 
				
			|||
    additional_description = fields.Char(string='Description', size=30, | 
				
			|||
                                         help='Additional description that will' | 
				
			|||
                                              ' be added to the product ' | 
				
			|||
                                              'description on orders.') | 
				
			|||
    quantity = fields.Float(string='Quantity', required=True, | 
				
			|||
                            help='Quantity of the product', default=1.0) | 
				
			|||
    ordering_interval = fields.Integer(string='Interval', required=True, | 
				
			|||
                                       help="Interval in time units for making" | 
				
			|||
                                            " an order of this product", | 
				
			|||
                                       default=1) | 
				
			|||
    ordering_unit = fields.Selection([('days', 'Days'), ('weeks', 'Weeks'), | 
				
			|||
                                      ('months', 'Months'), ('years', 'Years')], | 
				
			|||
                                     string='Interval Unit', required=True, | 
				
			|||
                                     help="It indicated the recurring time unit" | 
				
			|||
                                     , default='months') | 
				
			|||
    last_order_date = fields.Datetime(help='Date of the last Purchase order ' | 
				
			|||
                                           'generated', string='Last Order') | 
				
			|||
    specific_price = fields.Float( | 
				
			|||
        string='Specific Price', | 
				
			|||
        digits_compute=dp.get_precision('Purchase Price'), | 
				
			|||
        help='Specific price for this product. Keep empty to use the list ' | 
				
			|||
             'price while generating order') | 
				
			|||
    list_price = fields.Float(related='product_id.list_price', readonly=True, | 
				
			|||
                              string="List Price", help='Unit price of product') | 
				
			|||
 | 
				
			|||
    _sql_constraints = [ | 
				
			|||
        ('line_qty_zero', 'CHECK (quantity > 0)', | 
				
			|||
         'All product quantities must be greater than 0.\n'), | 
				
			|||
        ('line_interval_zero', 'CHECK (ordering_interval > 0)', | 
				
			|||
         'All ordering intervals must be greater than 0.\n'), | 
				
			|||
    ] | 
				
			|||
@ -0,0 +1,38 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
################################################################################ | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			|||
#    Author: Ruksana P (odoo@cybrosys.com) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU AFFERO | 
				
			|||
#    GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | 
				
			|||
#    (AGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
################################################################################ | 
				
			|||
from odoo import models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class ResPartner(models.Model): | 
				
			|||
    """ Inherited for adding new smart button purchase agreement""" | 
				
			|||
    _inherit = 'res.partner' | 
				
			|||
 | 
				
			|||
    def action_purchase_agreement(self): | 
				
			|||
        """Method of agreement smart button """ | 
				
			|||
        return { | 
				
			|||
            'name': 'agreements', | 
				
			|||
            'type': 'ir.actions.act_window', | 
				
			|||
            'res_model': 'purchase.recurring.agreement', | 
				
			|||
            'view_mode': 'tree,form', | 
				
			|||
            'view_id': False, | 
				
			|||
            'domain': [('partner_id', '=', self.id)] | 
				
			|||
        } | 
				
			|||
		
		
			
  | 
| 
		 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: 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: 1.5 KiB  | 
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
| 
		 After Width: | Height: | Size: 1.9 KiB  | 
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
| 
		 After Width: | Height: | Size: 2.1 KiB  | 
| 
		 After Width: | Height: | Size: 4.4 KiB  | 
| 
		 After Width: | Height: | Size: 589 B  | 
| 
		 After Width: | Height: | Size: 3.4 KiB  | 
| 
		 After Width: | Height: | Size: 1.7 KiB  | 
| 
		 After Width: | Height: | Size: 2.3 KiB  | 
| 
		 After Width: | Height: | Size: 967 B  | 
| 
		 After Width: | Height: | Size: 1.6 KiB  | 
| 
		 After Width: | Height: | Size: 3.8 KiB  | 
| 
		 After Width: | Height: | Size: 5.0 KiB  | 
| 
		 After Width: | Height: | Size: 51 KiB  | 
| 
		 After Width: | Height: | Size: 56 KiB  | 
| 
		 After Width: | Height: | Size: 51 KiB  | 
| 
		 After Width: | Height: | Size: 70 KiB  | 
| 
		 After Width: | Height: | Size: 59 KiB  | 
| 
		 After Width: | Height: | Size: 54 KiB  | 
| 
		 After Width: | Height: | Size: 39 KiB  | 
| 
		 After Width: | Height: | Size: 299 KiB  | 
| 
		 After Width: | Height: | Size: 118 KiB  | 
| 
		 After Width: | Height: | Size: 128 KiB  | 
| 
		 After Width: | Height: | Size: 178 KiB  | 
| 
		 After Width: | Height: | Size: 166 KiB  | 
| 
		 After Width: | Height: | Size: 129 KiB  | 
| 
		 After Width: | Height: | Size: 160 KiB  | 
| 
		 After Width: | Height: | Size: 158 KiB  | 
| 
		 After Width: | Height: | Size: 185 KiB  | 
| 
		 After Width: | Height: | Size: 157 KiB  | 
| 
		 After Width: | Height: | Size: 157 KiB  | 
| 
		 After Width: | Height: | Size: 157 KiB  | 
| 
		 After Width: | Height: | Size: 272 KiB  | 
| 
		 After Width: | Height: | Size: 155 KiB  | 
| 
		 After Width: | Height: | Size: 440 KiB  | 
| 
		 After Width: | Height: | Size: 80 KiB  | 
| 
		 After Width: | Height: | Size: 7.7 KiB  | 
@ -0,0 +1,667 @@ | 
				
			|||
<div style="background-color: #714B67; min-height: 600px; width: 100%; padding: 15px; position: relative;"> | 
				
			|||
    <!-- TITLE BAR --> | 
				
			|||
    <div | 
				
			|||
            style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;"> | 
				
			|||
        <img src="assets/misc/cybrosys-logo.png" width="42" height="42" | 
				
			|||
             style="width: 42px; height: 42px;"/> | 
				
			|||
        <div> | 
				
			|||
            <div style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" | 
				
			|||
                 class="mr-2"> | 
				
			|||
                <i class="fa fa-check mr-1"></i>Community | 
				
			|||
            </div> | 
				
			|||
            <div style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" | 
				
			|||
                 class="mr-2"> | 
				
			|||
                <i class="fa fa-check mr-1"></i>Enterprise | 
				
			|||
            </div> | 
				
			|||
            <div style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" | 
				
			|||
                 class="mr-2"> | 
				
			|||
                <i class="fa fa-check mr-1"></i>Odoo.sh | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
    </div> | 
				
			|||
    <!-- END OF TITLE BAR --> | 
				
			|||
    <!-- APP HERO --> | 
				
			|||
    <h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;"> | 
				
			|||
        Purchase Recurring Orders</h1> | 
				
			|||
    <p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;"> | 
				
			|||
        Helps To Create Recurring Orders For Purchases Based On The Information | 
				
			|||
        Provided</p> | 
				
			|||
    <!-- END OF APP HERO --> | 
				
			|||
    <img src="assets/screenshots/hero.gif" | 
				
			|||
         style="width: 75%; height: auto; position: absolute; margin-left: auto; margin-right: auto; top: 45%; left: 12%; right: auto;"/> | 
				
			|||
</div> | 
				
			|||
 | 
				
			|||
<!-- NAVIGATION SECTION --> | 
				
			|||
<div class="d-flex align-items-center" | 
				
			|||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;"> | 
				
			|||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			|||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			|||
        <img src="assets/misc/compass.png"/> | 
				
			|||
    </div> | 
				
			|||
    <h2 class="mt-2" | 
				
			|||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			|||
        Explore This | 
				
			|||
        Module</h2> | 
				
			|||
</div> | 
				
			|||
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;"> | 
				
			|||
    <div class="col-sm-12 col-md-6 my-3"> | 
				
			|||
        <a href="#overview"> | 
				
			|||
            <div class="d-flex justify-content-between align-items-center" | 
				
			|||
                 style="background-color: #f5f5f5; padding: 30px; width: 100%;"> | 
				
			|||
                <div> | 
				
			|||
                    <span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span> | 
				
			|||
                    <span | 
				
			|||
                            style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33;  display: block;">Learn | 
				
			|||
                        more about this | 
				
			|||
                        module</span> | 
				
			|||
                </div> | 
				
			|||
                <img src="assets/misc/right-arrow.png" width="36" height="36"/> | 
				
			|||
            </div> | 
				
			|||
        </a> | 
				
			|||
    </div> | 
				
			|||
    <div class="col-sm-12 col-md-6 my-3"> | 
				
			|||
        <a href="#features"> | 
				
			|||
            <div class="d-flex justify-content-between align-items-center" | 
				
			|||
                 style="background-color: #f5f5f5; padding: 30px; width: 100%;"> | 
				
			|||
                <div> | 
				
			|||
                    <span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span> | 
				
			|||
                    <span | 
				
			|||
                            style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33;  display: block;">View | 
				
			|||
                        features of this | 
				
			|||
                        module</span> | 
				
			|||
                </div> | 
				
			|||
                <img src="assets/misc/right-arrow.png" width="36" height="36"/> | 
				
			|||
            </div> | 
				
			|||
        </a> | 
				
			|||
    </div> | 
				
			|||
    <div class="col-sm-12 col-md-6 my-3"> | 
				
			|||
        <a href="#screenshots"> | 
				
			|||
            <div class="d-flex justify-content-between align-items-center" | 
				
			|||
                 style="background-color: #f5f5f5; padding: 30px; width: 100%;"> | 
				
			|||
                <div> | 
				
			|||
                    <span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span> | 
				
			|||
                    <span | 
				
			|||
                            style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33;  display: block;">View | 
				
			|||
                        screenshots for this | 
				
			|||
                        module</span> | 
				
			|||
                </div> | 
				
			|||
                <img src="assets/misc/right-arrow.png" width="36" height="36"/> | 
				
			|||
            </div> | 
				
			|||
        </a> | 
				
			|||
    </div> | 
				
			|||
</div> | 
				
			|||
<!-- END OF NAVIGATION SECTION --> | 
				
			|||
 | 
				
			|||
<!-- OVERVIEW SECTION --> | 
				
			|||
<div class="d-flex align-items-center" | 
				
			|||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="overview"> | 
				
			|||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			|||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			|||
        <img src="assets/misc/pie-chart.png"/> | 
				
			|||
    </div> | 
				
			|||
    <h2 class="mt-2" | 
				
			|||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			|||
        Overview | 
				
			|||
    </h2> | 
				
			|||
</div> | 
				
			|||
<div class="row" | 
				
			|||
     style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> | 
				
			|||
    <div class="col-sm-12 py-4"> | 
				
			|||
        This module is useful to create recurring orders for Purchases based | 
				
			|||
        on information(prolongation, Interval, etc.,) provided. | 
				
			|||
 | 
				
			|||
    </div> | 
				
			|||
</div> | 
				
			|||
<!-- END OF OVERVIEW SECTION --> | 
				
			|||
 | 
				
			|||
<!-- FEATURES SECTION --> | 
				
			|||
<div class="d-flex align-items-center" | 
				
			|||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="features"> | 
				
			|||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			|||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			|||
        <img src="assets/misc/features.png"/> | 
				
			|||
    </div> | 
				
			|||
    <h2 class="mt-2" | 
				
			|||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			|||
        Features | 
				
			|||
    </h2> | 
				
			|||
</div> | 
				
			|||
<div class="row" | 
				
			|||
     style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> | 
				
			|||
    <div class="col-sm-12 col-md-6"> | 
				
			|||
        <div class="d-flex align-items-center" | 
				
			|||
             style="margin-top: 40px; margin-bottom: 40px"> | 
				
			|||
            <img src="assets/misc/check-box.png" class="mr-2"/> | 
				
			|||
            <span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Creates recurring orders for purchase</span> | 
				
			|||
        </div> | 
				
			|||
        <div class="d-flex align-items-center" | 
				
			|||
             style="margin-top: 40px; margin-bottom: 40px"> | 
				
			|||
            <img src="assets/misc/check-box.png" class="mr-2"/> | 
				
			|||
            <span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Scheduled action for creating recurring orders</span> | 
				
			|||
        </div> | 
				
			|||
 | 
				
			|||
    </div> | 
				
			|||
</div> | 
				
			|||
<!-- END OF FEATURES SECTION --> | 
				
			|||
 | 
				
			|||
<!-- SCREENSHOTS SECTION --> | 
				
			|||
<div class="d-flex align-items-center" | 
				
			|||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;" | 
				
			|||
     id="screenshots"> | 
				
			|||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			|||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			|||
        <img src="assets/misc/pictures.png"/> | 
				
			|||
    </div> | 
				
			|||
    <h2 class="mt-2" | 
				
			|||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			|||
        Screenshots | 
				
			|||
    </h2> | 
				
			|||
</div> | 
				
			|||
<div class="row"> | 
				
			|||
    <div class="col-sm-12"> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Menu for viewing and creating Recurring Order Agreements</h3> | 
				
			|||
 | 
				
			|||
            <img src="assets/screenshots/1.png" class="img-thumbnail"/> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Create Recurring Order Agreement</h3> | 
				
			|||
            <p>Create new recurring order agreement by filling the details in | 
				
			|||
                the form and add the products in Agreement Order Line.</p> | 
				
			|||
            <img src="assets/screenshots/2.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Generate Initial Order</h3> | 
				
			|||
            <p>Click on the Generate Initial Order button for generating the | 
				
			|||
                first order.</p> | 
				
			|||
 | 
				
			|||
            <img src="assets/screenshots/3.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Initial order generated</h3> | 
				
			|||
            <p> | 
				
			|||
                First Purchase Order Generated according to the details added in | 
				
			|||
                the Recurring purchase agreement. | 
				
			|||
            </p> | 
				
			|||
            <img src="assets/screenshots/4.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Smart button for Orders</h3> | 
				
			|||
            <p> | 
				
			|||
                We can see all orders created from the recurring purchase | 
				
			|||
                agreement from the smart button which shows the number of | 
				
			|||
                orders. | 
				
			|||
            </p> | 
				
			|||
            <img src="assets/screenshots/5.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Generate Next year Orders</h3> | 
				
			|||
            <p> | 
				
			|||
                It is possible to create next year orders at one click. | 
				
			|||
            </p> | 
				
			|||
            <img src="assets/screenshots/6.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Number of Orders increased | 
				
			|||
            </h3> | 
				
			|||
            <img src="assets/screenshots/7.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Generated Orders</h3> | 
				
			|||
            <p> | 
				
			|||
                All orders generated including Initial and Next year Orders. | 
				
			|||
            </p> | 
				
			|||
            <img src="assets/screenshots/8.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Renew Agreement</h3> | 
				
			|||
            <img src="assets/screenshots/9.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Update the Comments for Agreement Renewal </h3> | 
				
			|||
 | 
				
			|||
            <img src="assets/screenshots/10.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Fixed Term Purchase Recurring Agreement </h3> | 
				
			|||
            <p> | 
				
			|||
                Enter the start and end date of fixed term agreement. | 
				
			|||
            </p> | 
				
			|||
 | 
				
			|||
            <img src="assets/screenshots/16.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Scheduled Action for generating Recurring Orders for Next | 
				
			|||
                Year</h3> | 
				
			|||
            <img src="assets/screenshots/11.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Generate Agreement button in Purchase Order</h3> | 
				
			|||
            <img src="assets/screenshots/12.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
        <div style="display: block; margin: 30px auto;"> | 
				
			|||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
				
			|||
                Current Purchase Order set as new Purchase Agreement.</h3> | 
				
			|||
            <img src="assets/screenshots/13.png" class="img-thumbnail"> | 
				
			|||
        </div> | 
				
			|||
    </div> | 
				
			|||
</div> | 
				
			|||
<!-- END OF SCREENSHOTS SECTION --> | 
				
			|||
 | 
				
			|||
<!-- RELATED PRODUCTS --> | 
				
			|||
<div class="d-flex align-items-center" | 
				
			|||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | 
				
			|||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			|||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			|||
        <img src="assets/misc/categories.png"/> | 
				
			|||
    </div> | 
				
			|||
    <h2 class="mt-2" | 
				
			|||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			|||
        Related | 
				
			|||
        Products | 
				
			|||
    </h2> | 
				
			|||
</div> | 
				
			|||
<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/14.0/product_brand_purchase/" | 
				
			|||
                           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_brand.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/14.0/no_automatic_subscription/" | 
				
			|||
                           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/automatic_subscription.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/14.0/follower_restrict/" | 
				
			|||
                           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/follower_restrict.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/14.0/mrp_work_order_print/" | 
				
			|||
                           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/print_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/14.0/product_import/" | 
				
			|||
                           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_url.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/14.0/sale_purchase_previous_product_cost/" | 
				
			|||
                           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/multiple_reference.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 RELATED PRODUCTS --> | 
				
			|||
 | 
				
			|||
<!-- OUR SERVICES --> | 
				
			|||
<div class="d-flex align-items-center" | 
				
			|||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | 
				
			|||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			|||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			|||
        <img src="assets/misc/star.png"/> | 
				
			|||
    </div> | 
				
			|||
    <h2 class="mt-2" | 
				
			|||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			|||
        Our Services | 
				
			|||
    </h2> | 
				
			|||
</div> | 
				
			|||
<div class="container my-5"> | 
				
			|||
    <div class="row"> | 
				
			|||
        <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> | 
				
			|||
</div> | 
				
			|||
<!--END OF OUR SERVICES --> | 
				
			|||
 | 
				
			|||
<!-- OUR INDUSTRIES --> | 
				
			|||
<div class="d-flex align-items-center" | 
				
			|||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | 
				
			|||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			|||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			|||
        <img src="assets/misc/corporate.png"/> | 
				
			|||
    </div> | 
				
			|||
    <h2 class="mt-2" | 
				
			|||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			|||
        Our | 
				
			|||
        Industries | 
				
			|||
    </h2> | 
				
			|||
</div> | 
				
			|||
<div class="container my-5"> | 
				
			|||
    <div class="row"> | 
				
			|||
        <div class="col-lg-3"> | 
				
			|||
            <div class="my-4 d-flex flex-column justify-content-center" | 
				
			|||
                 style="background-color: #f6f8f9 !important; border-radius: 0px; 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: 0px; 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: 0px; 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: 0px; 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: 0px; 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: 0px; 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: 0px; 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: 0px; 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> | 
				
			|||
</div> | 
				
			|||
<!--  END OF OUR INDUSTRIES --> | 
				
			|||
 | 
				
			|||
<!-- SUPPORT --> | 
				
			|||
<div class="d-flex align-items-center" | 
				
			|||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | 
				
			|||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
				
			|||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
				
			|||
        <img src="assets/misc/customer-support.png"/> | 
				
			|||
    </div> | 
				
			|||
    <h2 class="mt-2" | 
				
			|||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
				
			|||
        Support | 
				
			|||
    </h2> | 
				
			|||
</div> | 
				
			|||
<div class="container mt-5"> | 
				
			|||
    <div class="row"> | 
				
			|||
        <div class="col-sm-12 col-md-6"> | 
				
			|||
            <div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> | 
				
			|||
                <div class="mr-4" | 
				
			|||
                     style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> | 
				
			|||
                    <img src="assets/misc/support.png" height="48" width="48" | 
				
			|||
                         style="width: 42px; height: 42px;"/> | 
				
			|||
                </div> | 
				
			|||
                <div> | 
				
			|||
                    <h4>Need Help?</h4> | 
				
			|||
                    <p style="line-height: 100%;">Got questions or need help? | 
				
			|||
                        Get in touch.</p> | 
				
			|||
                    <a href="mailto:odoo@cybrosys.com"> | 
				
			|||
                        <p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> | 
				
			|||
                            odoo@cybrosys.com</p> | 
				
			|||
                    </a> | 
				
			|||
                </div> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-sm-12 col-md-6"> | 
				
			|||
            <div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> | 
				
			|||
                <div class="mr-4" | 
				
			|||
                     style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> | 
				
			|||
                    <img src="assets/misc/whatsapp.png" height="52" width="52" | 
				
			|||
                         style="width: 52px; height: 52px;"/> | 
				
			|||
                </div> | 
				
			|||
                <div> | 
				
			|||
                    <h4>WhatsApp</h4> | 
				
			|||
                    <p style="line-height: 100%;">Say hi to us on WhatsApp!</p> | 
				
			|||
                    <a href="https://api.whatsapp.com/send?phone=918606827707"> | 
				
			|||
                        <p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> | 
				
			|||
                            +91 86068 | 
				
			|||
                            27707</p> | 
				
			|||
                    </a> | 
				
			|||
                </div> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
    </div> | 
				
			|||
    <div class="row"> | 
				
			|||
        <div class="col-sm-12 my-5 d-flex justify-content-center align-items-center"> | 
				
			|||
            <img src="assets/misc/logo.png" width="144" height="31" | 
				
			|||
                 style="width:144px; height: 31px; margin-top: 40px;"/> | 
				
			|||
        </div> | 
				
			|||
    </div> | 
				
			|||
</div> | 
				
			|||
<!-- END OF SUPPORT --> | 
				
			|||
@ -0,0 +1,31 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8"?> | 
				
			|||
<odoo> | 
				
			|||
    <!--Generate Agreement Button in Purchase Order --> | 
				
			|||
    <record id="purchase_order_form" model="ir.ui.view"> | 
				
			|||
        <field name="name"> | 
				
			|||
            purchase.order.view.form.inherit.purchase.recurring.orders | 
				
			|||
        </field> | 
				
			|||
        <field name="model">purchase.order</field> | 
				
			|||
        <field name="inherit_id" ref="purchase.purchase_order_form"/> | 
				
			|||
        <field name="arch" type="xml"> | 
				
			|||
            <button name="button_cancel" position="after"> | 
				
			|||
                <button name="action_generate_agreement" | 
				
			|||
                        string="Generate agreement" type="object"/> | 
				
			|||
            </button> | 
				
			|||
        </field> | 
				
			|||
    </record> | 
				
			|||
    <record id="view_purchase_order_filter" model="ir.ui.view"> | 
				
			|||
        <field name="name"> | 
				
			|||
            purchase.order.view.list.inherit.purchase.recurring.orders | 
				
			|||
        </field> | 
				
			|||
        <field name="model">purchase.order</field> | 
				
			|||
        <field name="inherit_id" ref="purchase.view_purchase_order_filter"/> | 
				
			|||
        <field name="arch" type="xml"> | 
				
			|||
            <field name="name" position="after"> | 
				
			|||
                <filter string="Not from agreements" name="is_agreement" | 
				
			|||
                        domain="[('is_agreement','=',False)]"/> | 
				
			|||
                <separator/> | 
				
			|||
            </field> | 
				
			|||
        </field> | 
				
			|||
    </record> | 
				
			|||
</odoo> | 
				
			|||
@ -0,0 +1,172 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8"?> | 
				
			|||
<odoo> | 
				
			|||
    <!--    Purchase Recurring Agreement tree View--> | 
				
			|||
    <record id="purchase_recurring_agreement_view_tree" model="ir.ui.view"> | 
				
			|||
        <field name="name">purchase.recurring.agreement.view.tree</field> | 
				
			|||
        <field name="model">purchase.recurring.agreement</field> | 
				
			|||
        <field name="type">tree</field> | 
				
			|||
        <field name="priority" eval="6"/> | 
				
			|||
        <field name="arch" type="xml"> | 
				
			|||
            <tree string="Recurring Orders Agreements"> | 
				
			|||
                <field name="name"/> | 
				
			|||
                <field name="partner_id"/> | 
				
			|||
                <field name="start_date"/> | 
				
			|||
                <field name="prolong"/> | 
				
			|||
                <field name="next_expiration_date"/> | 
				
			|||
                <field name="company_id" groups="base.group_multi_company"/> | 
				
			|||
            </tree> | 
				
			|||
        </field> | 
				
			|||
    </record> | 
				
			|||
    <!--    Purchase Recurring Agreement Form View--> | 
				
			|||
    <record id="purchase_recurring_agreement_view_form" model="ir.ui.view"> | 
				
			|||
        <field name="name">purchase.recurring.agreement.view.form</field> | 
				
			|||
        <field name="model">purchase.recurring.agreement</field> | 
				
			|||
        <field name="priority">6</field> | 
				
			|||
        <field name="arch" type="xml"> | 
				
			|||
            <form> | 
				
			|||
                <header> | 
				
			|||
                    <button name="action_generate_initial_order" | 
				
			|||
                            class="oe_highlight" | 
				
			|||
                            states="empty" | 
				
			|||
                            string="Generate Initial Order" | 
				
			|||
                            type="object"/> | 
				
			|||
                    <button name="action_generate_next_year_orders" | 
				
			|||
                            string="Generate Next Year Orders" type="object" | 
				
			|||
                            icon="fa-envelope"/> | 
				
			|||
                    <button name="%(agreement_renewal_action)d" | 
				
			|||
                            type="action" | 
				
			|||
                            string="Renew Agreement" | 
				
			|||
                            attrs="{'invisible': [('prolong','!=', 'recurrent')]}"/> | 
				
			|||
                </header> | 
				
			|||
                <sheet> | 
				
			|||
                    <div name="button_box" class="oe_button_box"> | 
				
			|||
                        <button class="oe_stat_button" type="object" | 
				
			|||
                                name="action_view_purchase_orders" | 
				
			|||
                                attrs="{'invisible' : [('order_count','=',0)]}" | 
				
			|||
                                icon="fa-file"> | 
				
			|||
                            <field string="Orders" name="order_count" | 
				
			|||
                                   widget="statinfo"/> | 
				
			|||
                        </button> | 
				
			|||
                    </div> | 
				
			|||
                    <div class="oe_title"> | 
				
			|||
                        <h1> | 
				
			|||
                            <field name="name"/> | 
				
			|||
                        </h1> | 
				
			|||
                    </div> | 
				
			|||
                    <group> | 
				
			|||
                        <group> | 
				
			|||
                            <field name="partner_id"/> | 
				
			|||
                            <field name="company_id" | 
				
			|||
                                   groups="base.group_multi_company"/> | 
				
			|||
                            <field name="prolong" | 
				
			|||
                                   attrs="{'readonly':[('renewal_state','!=','not_renewed')]}"/> | 
				
			|||
 | 
				
			|||
                            <field name="last_renovation_date" readonly="1" | 
				
			|||
                                   attrs="{'invisible': [('prolong','!=', 'recurrent')]}"/> | 
				
			|||
                            <field name="state" invisible="1"/> | 
				
			|||
                            <field name="renewal_state" invisible="1"/> | 
				
			|||
                        </group> | 
				
			|||
                        <group> | 
				
			|||
                            <field name="active" invisible="1"/> | 
				
			|||
                            <field name="name" invisible="1"/> | 
				
			|||
                            <field name="start_date" | 
				
			|||
                                   attrs="{'readonly':[('state','!=','empty')]}"/> | 
				
			|||
                            <field name="next_expiration_date"/> | 
				
			|||
                            <field name="prolong_unit" | 
				
			|||
                                   attrs="{'required': [('prolong', '!=', 'fixed')]}"/> | 
				
			|||
                        </group> | 
				
			|||
                        <group> | 
				
			|||
                            <group> | 
				
			|||
                                <group attrs="{'invisible': [('prolong','=', 'fixed')]}" | 
				
			|||
                                       colspan="4" col="4"> | 
				
			|||
                                    <field name="prolong_interval" | 
				
			|||
                                           attrs="{'required': [('prolong', '!=', 'fixed')]}"/> | 
				
			|||
                                </group> | 
				
			|||
                                <group attrs="{'invisible': [('prolong','!=', 'fixed')]}" | 
				
			|||
                                       colspan="4" col="2"> | 
				
			|||
                                    <field name="end_date" | 
				
			|||
                                           attrs="{'required': [('prolong', '=', 'fixed')]}"/> | 
				
			|||
                                </group> | 
				
			|||
                            </group> | 
				
			|||
                        </group> | 
				
			|||
                    </group> | 
				
			|||
                    <notebook colspan="4"> | 
				
			|||
                        <page string="Lines"> | 
				
			|||
                            <field name="agreement_line_ids"> | 
				
			|||
                                <tree string="Agreement lines" | 
				
			|||
                                      editable="bottom"> | 
				
			|||
                                    <field name="is_active" optional="hide"/> | 
				
			|||
                                    <field name="product_id"/> | 
				
			|||
                                    <field name="additional_description"/> | 
				
			|||
                                    <field name="quantity"/> | 
				
			|||
                                    <field name="uom_id"/> | 
				
			|||
                                    <field name="list_price"/> | 
				
			|||
                                    <field name="specific_price"/> | 
				
			|||
                                    <field name="ordering_interval"/> | 
				
			|||
                                    <field name="ordering_unit"/> | 
				
			|||
                                    <field name="last_order_date" | 
				
			|||
                                           readonly="True"/> | 
				
			|||
                                </tree> | 
				
			|||
                            </field> | 
				
			|||
                        </page> | 
				
			|||
                        <page string="Renewals" | 
				
			|||
                              attrs="{'invisible': [('prolong','!=', 'recurrent')]}"> | 
				
			|||
                            <field colspan="4" mode="tree" name="renewal_ids" | 
				
			|||
                                   widget="one2many_list" nolabel="1"> | 
				
			|||
                                <tree string="Agreement Renewals"> | 
				
			|||
                                    <field name="date"/> | 
				
			|||
                                    <field name="comments"/> | 
				
			|||
                                </tree> | 
				
			|||
                            </field> | 
				
			|||
                        </page> | 
				
			|||
                    </notebook> | 
				
			|||
                    <div class="oe_clear"/> | 
				
			|||
                    <field name="notes"/> | 
				
			|||
                </sheet> | 
				
			|||
                <div class="oe_chatter"> | 
				
			|||
                    <field name="message_follower_ids" widget="mail_followers" | 
				
			|||
                           groups="base.group_user"/> | 
				
			|||
                    <field name="message_ids" widget="mail_thread" | 
				
			|||
                           placeholder="Share a message..."/> | 
				
			|||
                </div> | 
				
			|||
            </form> | 
				
			|||
        </field> | 
				
			|||
    </record> | 
				
			|||
    <!--    Purchase Recurring Agreement search View--> | 
				
			|||
    <record id="purchases_recurring_agreement_view_search" model="ir.ui.view"> | 
				
			|||
        <field name="name">purchase.recurring.agreement.view.search</field> | 
				
			|||
        <field name="model">purchase.recurring.agreement</field> | 
				
			|||
        <field name="arch" type="xml"> | 
				
			|||
            <search> | 
				
			|||
                <field name="name" | 
				
			|||
                       filter_domain="[('name', 'ilike', self)]"/> | 
				
			|||
                <field name="partner_id" | 
				
			|||
                       filter_domain="[('partner_id', 'child_of', self)]"/> | 
				
			|||
            </search> | 
				
			|||
        </field> | 
				
			|||
    </record> | 
				
			|||
    <!--  Recurring Orders Agreement Menu Action--> | 
				
			|||
    <record id="action_recurring_orders_agreement" | 
				
			|||
            model="ir.actions.act_window"> | 
				
			|||
        <field name="name">Recurring Order Agreement</field> | 
				
			|||
        <field name="res_model">purchase.recurring.agreement</field> | 
				
			|||
        <field name="view_mode">tree,form</field> | 
				
			|||
        <field name="help" type="html"> | 
				
			|||
            <p class="oe_view_nocontent_create"> | 
				
			|||
                Click to set a new agreement. | 
				
			|||
            </p> | 
				
			|||
            <p> | 
				
			|||
                Agreements are the way you define the commercial relation with | 
				
			|||
                your customers which specify certain | 
				
			|||
                products/services that you are providing them which requires a | 
				
			|||
                recurring order. | 
				
			|||
            </p> | 
				
			|||
        </field> | 
				
			|||
    </record> | 
				
			|||
    <!--   Menu Recurring Order Agreement--> | 
				
			|||
    <menuitem name="Recurring Order Agreement" | 
				
			|||
              id="menu_recurring_order_agreement" | 
				
			|||
              parent="purchase.menu_procurement_management" | 
				
			|||
              action="action_recurring_orders_agreement" | 
				
			|||
              sequence="4"/> | 
				
			|||
</odoo> | 
				
			|||
@ -0,0 +1,21 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8"?> | 
				
			|||
<odoo> | 
				
			|||
    <!--      Agreement Smart Button--> | 
				
			|||
    <record id="view_partner_form" model="ir.ui.view"> | 
				
			|||
        <field name="name"> | 
				
			|||
            res.partner.view.form.inherit.purchase.recurring.orders | 
				
			|||
        </field> | 
				
			|||
        <field name="model">res.partner</field> | 
				
			|||
        <field name="inherit_id" ref="base.view_partner_form"/> | 
				
			|||
        <field name="priority" eval="20"/> | 
				
			|||
        <field name="arch" type="xml"> | 
				
			|||
            <xpath expr="//div[@name='button_box']" position="inside"> | 
				
			|||
                <button name="action_purchase_agreement" | 
				
			|||
                        type="object" | 
				
			|||
                        class="oe_stat_button" | 
				
			|||
                        icon="fa-file-text-o" | 
				
			|||
                        string="Agreements"/> | 
				
			|||
            </xpath> | 
				
			|||
        </field> | 
				
			|||
    </record> | 
				
			|||
</odoo> | 
				
			|||
@ -0,0 +1,22 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
################################################################################ | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			|||
#    Author: Ruksana P (odoo@cybrosys.com) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU AFFERO | 
				
			|||
#    GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | 
				
			|||
#    (AGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
############################################################################### | 
				
			|||
from . import agreement_renewal | 
				
			|||
@ -0,0 +1,54 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
################################################################################ | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | 
				
			|||
#    Author: Ruksana P (odoo@cybrosys.com) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU AFFERO | 
				
			|||
#    GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | 
				
			|||
#    (AGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
################################################################################ | 
				
			|||
from odoo import fields, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class AgreementRenewal(models.TransientModel): | 
				
			|||
    """ New wizard for creating new renewal for agreement """ | 
				
			|||
    _name = "agreement.renewal" | 
				
			|||
    _description = "Agreement Renewal Form" | 
				
			|||
 | 
				
			|||
    def _default_date(self): | 
				
			|||
        """Method for getting the renewal date""" | 
				
			|||
        agreements = self.env['purchase.recurring.agreement'].browse( | 
				
			|||
            self.env.context.get('active_ids', [])) | 
				
			|||
        return agreements[:1].next_expiration_date | 
				
			|||
 | 
				
			|||
    date = fields.Date(string='Renewal Date', required=True, | 
				
			|||
                       default=_default_date, | 
				
			|||
                       help="Effective date of the renewal. This date is the " | 
				
			|||
                            "one taken into account in the next renewal") | 
				
			|||
    comments = fields.Char(string='Comments', size=200, help='Renewal comments') | 
				
			|||
 | 
				
			|||
    def action_renewal(self): | 
				
			|||
        """Method for renewal of purchase recurring agreement""" | 
				
			|||
        self.ensure_one() | 
				
			|||
        agreement_ids = self.env.context.get('active_ids', []) | 
				
			|||
        for agreement_id in agreement_ids: | 
				
			|||
            self.env['agreement.renewal.line'].create( | 
				
			|||
                {'recurring_agreement_id': agreement_id, | 
				
			|||
                 'date': self.date, | 
				
			|||
                 'comments': self.comments}) | 
				
			|||
        self.env['purchase.recurring.agreement'].browse(agreement_ids).write( | 
				
			|||
            {'last_renovation_date': self.date, | 
				
			|||
             'renewal_state': 'renewed'}) | 
				
			|||
        return True | 
				
			|||
@ -0,0 +1,38 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8"?> | 
				
			|||
<odoo> | 
				
			|||
    <!-- Purchase Agreement Renewal Wizard Form View --> | 
				
			|||
    <record id="agreement_renewal_view_form" model="ir.ui.view"> | 
				
			|||
        <field name="name">agreement.renewal.view.form</field> | 
				
			|||
        <field name="model">agreement.renewal</field> | 
				
			|||
        <field name="arch" type="xml"> | 
				
			|||
            <form> | 
				
			|||
                <sheet> | 
				
			|||
                    <group> | 
				
			|||
                        <group> | 
				
			|||
                            <field name="date"/> | 
				
			|||
                            <separator string="" colspan="4"/> | 
				
			|||
                            <field name="comments" default_focus="1"/> | 
				
			|||
                            <separator string="" colspan="4"/> | 
				
			|||
                        </group> | 
				
			|||
                    </group> | 
				
			|||
                </sheet> | 
				
			|||
                <footer> | 
				
			|||
                    <button special="cancel" class="oe_highlight" | 
				
			|||
                            string="Cancel" icon="fa-close"/> | 
				
			|||
                    <button name="action_renewal" class="oe_highlight" | 
				
			|||
                            string="Renew Agreement" type="object" | 
				
			|||
                            icon="fa-refresh"/> | 
				
			|||
                </footer> | 
				
			|||
            </form> | 
				
			|||
        </field> | 
				
			|||
    </record> | 
				
			|||
    <!-- Purchase Agreement Renewal Wizard Action --> | 
				
			|||
    <record id="agreement_renewal_action" model="ir.actions.act_window"> | 
				
			|||
        <field name="type">ir.actions.act_window</field> | 
				
			|||
        <field name="name">Renew Agreement</field> | 
				
			|||
        <field name="res_model">agreement.renewal</field> | 
				
			|||
        <field name="view_mode">form</field> | 
				
			|||
        <field name="view_id" ref="agreement_renewal_view_form"/> | 
				
			|||
        <field name="target">new</field> | 
				
			|||
    </record> | 
				
			|||
</odoo> | 
				
			|||