| @ -0,0 +1,46 @@ | |||
| .. 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 | |||
| 
 | |||
| All in One Sales Kit | |||
| ==================== | |||
| This module combines a variety of sales features. | |||
| 
 | |||
| Configuration | |||
| ============= | |||
| * No Additional configuration is needed. | |||
| 
 | |||
| Company | |||
| ------- | |||
| * `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | |||
| 
 | |||
| License | |||
| ------- | |||
| General Public License, Version 3 (AGPL-3). | |||
| (https://www.gnu.org/licenses/agpl-3.0-standalone.html) | |||
| 
 | |||
| Credits | |||
| ------- | |||
| Developer: (V16) Swetha Anand, 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,25 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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 controllers | |||
| from . import models | |||
| from . import report | |||
| from . import wizard | |||
| @ -0,0 +1,102 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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': 'Odoo16 All in One Sales Kit', | |||
|     'version': '16.0.1.0.0', | |||
|     'category': 'Sales', | |||
|     'summary': 'This module combines a variety of sales features.', | |||
|     'description': 'Sale Order Line Images, Barcode Scan Support for Sales, ' | |||
|                    'Advanced Sale Reports (Product Profit Report, ' | |||
|                    'Sales Invoice Analysis Report, Sales Category Report, ' | |||
|                    'Sales Indent Report, Sales Analysis Report, ' | |||
|                    'Hourly Sales Report), Product Pack, and ' | |||
|                    'Salesperson Signature for Confirm Order are some of the ' | |||
|                    'features included in this module.' | |||
|                    'Previous Sale Product Rate, Create Various Sale Order ' | |||
|                    'Versions, Create Custom Fields for Sale Orders, ' | |||
|                    'Recognise Previous Sales of Products,' | |||
|                    'A separate quotation number,' | |||
|                    'Multiple warehouses in sale order lines,' | |||
|                    'sales order and quotation line views,' | |||
|                    'approval of the sale order discount,sales restrictions ' | |||
|                    'for out-of-stock items depending on forecast and ' | |||
|                    'stock level,automate the sale process,' | |||
|                    'Sales one-stop report generation,Add more than one ' | |||
|                    'item to the quotation,pivot view for partner sales,' | |||
|                    'sale order archive,Dashboard.', | |||
|     'author': 'Cybrosys Techno Solutions', | |||
|     'company': 'Cybrosys Techno Solutions', | |||
|     'maintainer': 'Cybrosys Techno Solutions', | |||
|     'website': 'https://www.cybrosys.com', | |||
|     'depends': ['sale_management', 'delivery', 'stock','sale'], | |||
|     'data': [ | |||
|         'security/all_in_one_sales_kit_groups.xml', | |||
|         'security/ir.model.access.csv', | |||
|         'data/field_widget_data.xml', | |||
|         'data/ir_sequence_data.xml', | |||
|         'wizard/product_sale_order_history_views.xml', | |||
|         'wizard/sale_order_dynamic_fields_views.xml', | |||
|         'wizard/sale_report_advance_views.xml', | |||
|         'wizard/sale_report_analysis_views.xml', | |||
|         'wizard/sale_report_category_views.xml', | |||
|         'wizard/sale_report_indent_views.xml', | |||
|         'wizard/sale_report_invoice_views.xml', | |||
|         'wizard/sale_report_weekly_views.xml', | |||
|         'wizard/select_product_pack_views.xml', | |||
|         'views/res_config_settings_views.xml', | |||
|         'views/all_in_one_sales_kit_menus.xml', | |||
|         'views/sale_order_views.xml', | |||
|         'views/sale_order_line_views.xml', | |||
|         'views/res_users_views.xml', | |||
|         'views/sale_report_views.xml', | |||
|         'views/product_template_views.xml', | |||
|         'views/ir_fields_search_views.xml', | |||
|         'views/product_product_views.xml', | |||
|         'views/dashboard_menu.xml', | |||
|         'report/invoice_analysis_templates.xml', | |||
|         'report/sale_order_document_templates.xml', | |||
|         'report/sale_order_report_templates.xml', | |||
|         'report/sale_profit_templates.xml', | |||
|         'report/sale_reports.xml', | |||
|         'report/sales_analysis_templates.xml', | |||
|         'report/sales_category_templates.xml', | |||
|         'report/sales_indent_templates.xml', | |||
|         'report/sales_weekly_templates.xml' | |||
|     ], | |||
|     'assets': { | |||
|         'web.assets_backend': [ | |||
|             'all_in_one_sales_kit/static/src/css/sale_report.css', | |||
|             'all_in_one_sales_kit/static/src/scss/dashboard.scss', | |||
|             'all_in_one_sales_kit/static/src/js/action_manager.js', | |||
|             'all_in_one_sales_kit/static/src/js/sale_report.js', | |||
|             'all_in_one_sales_kit/static/src/js/dashboard.js', | |||
|             'all_in_one_sales_kit/static/src/xml/sale_report_templates.xml', | |||
|             'all_in_one_sales_kit/static/src/xml/dashboard_templates.xml', | |||
|             'https://cdn.jsdelivr.net/npm/chart.js', | |||
|         ], | |||
|     }, | |||
|     'images': ['static/description/banner.jpg'], | |||
|     'license': 'AGPL-3', | |||
|     'installable': True, | |||
|     'auto_install': False, | |||
|     'application': False, | |||
| } | |||
| @ -0,0 +1,22 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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 all_in_one_sales_kit | |||
| @ -0,0 +1,55 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.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/>. | |||
| # | |||
| ############################################################################# | |||
| import json | |||
| from odoo import http | |||
| from odoo.http import content_disposition, request | |||
| from odoo.tools import html_escape | |||
| 
 | |||
| 
 | |||
| class XLSXReportController(http.Controller): | |||
|     """This class is to add sales xlsx reports.""" | |||
| 
 | |||
|     @http.route('/xlsx_reports', type='http', auth='user', | |||
|                 methods=['POST'], csrf=False) | |||
|     def get_report_xlsx(self, model, options, output_format, | |||
|                         report_name, **kw): | |||
|         """This is to pass data required for the xlsx report.""" | |||
|         token = 'dummy-because-api-expects-one' | |||
|         try: | |||
|             if output_format == 'xlsx': | |||
|                 response = request.make_response( | |||
|                     None, | |||
|                     headers=[('Content-Type', 'application/vnd.ms-excel'), | |||
|                              ('Content-Disposition', | |||
|                               content_disposition(report_name + '.xlsx')) | |||
|                              ] | |||
|                 ) | |||
|                 request.env[model].sudo().browse( | |||
|                     request.session.uid).get_xlsx_report(json.loads(options), | |||
|                                                          response) | |||
|             response.set_cookie('fileToken', token) | |||
|             return response | |||
|         except Exception: | |||
|             error = { | |||
|                 'code': 200, | |||
|                 'message': 'Odoo Server Error', | |||
|             } | |||
|             return request.make_response(html_escape(json.dumps(error))) | |||
| @ -0,0 +1,77 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <data noupdate="1"> | |||
|         <!-- Widget 'image' for 'binary' field --> | |||
|         <record id="field_widget_image_widget" model="field.widget"> | |||
|             <field name="name">image</field> | |||
|             <field name="description">Image</field> | |||
|         </record> | |||
|         <!-- Widget 'many2many_tags' for 'many2many' field --> | |||
|         <record id="field_widget_many2many_tag_widget" model="field.widget"> | |||
|             <field name="name">many2many_tags</field> | |||
|             <field name="description">Many2many Tags</field> | |||
|         </record> | |||
|         <!-- Widget 'binary' for 'many2many' field --> | |||
|         <record id="field_widget_many2many_binary_widget" | |||
|                 model="field.widget"> | |||
|             <field name="name">binary</field> | |||
|             <field name="description">Binary</field> | |||
|         </record> | |||
|         <!-- Widget 'radio' for 'selection' field --> | |||
|         <record id="field_widget_radio_widget" model="field.widget"> | |||
|             <field name="name">radio</field> | |||
|             <field name="description">Radio</field> | |||
|         </record> | |||
|         <!-- Widget 'priority' for 'selection' field --> | |||
|         <record id="field_widget_priority_widget" model="field.widget"> | |||
|             <field name="name">priority</field> | |||
|             <field name="description">Priority</field> | |||
|         </record> | |||
|         <!-- Widget 'monetory' for 'float' field --> | |||
|         <record id="field_widgets_monetory_widget" model="field.widget"> | |||
|             <field name="name">monetary</field> | |||
|             <field name="description">Monetary</field> | |||
|         </record> | |||
|         <!-- Widget 'selection' for 'Many2one' field --> | |||
|         <record id="field_widget_selection_widget" model="field.widget"> | |||
|             <field name="name">selection</field> | |||
|             <field name="description">Selection</field> | |||
|         </record> | |||
|         <!-- Widget 'image' for 'binary' field --> | |||
|         <record id="field_widget_image_widget" model="field.widget"> | |||
|             <field name="name">image</field> | |||
|             <field name="description">Image</field> | |||
|         </record> | |||
|         <!-- Widget 'many2many_tags' for 'many2many' field --> | |||
|         <record id="field_widget_many2many_tag_widget" model="field.widget"> | |||
|             <field name="name">many2many_tags</field> | |||
|             <field name="description">Many2many Tags</field> | |||
|         </record> | |||
|         <!-- Widget 'binary' for 'many2many' field --> | |||
|         <record id="field_widget_many2many_binary_widget" | |||
|                 model="field.widget"> | |||
|             <field name="name">binary</field> | |||
|             <field name="description">Binary</field> | |||
|         </record> | |||
|         <!-- Widget 'radio' for 'selection' field --> | |||
|         <record id="field_widget_radio_widget" model="field.widget"> | |||
|             <field name="name">radio</field> | |||
|             <field name="description">Radio</field> | |||
|         </record> | |||
|         <!-- Widget 'priority' for 'selection' field --> | |||
|         <record id="field_widget_priority_widget" model="field.widget"> | |||
|             <field name="name">priority</field> | |||
|             <field name="description">Priority</field> | |||
|         </record> | |||
|         <!-- Widget 'monetory' for 'float' field --> | |||
|         <record id="field_widget_monetory_widget" model="field.widget"> | |||
|             <field name="name">monetary</field> | |||
|             <field name="description">Monetary</field> | |||
|         </record> | |||
|         <!-- Widget 'selection' for 'Many2one' field --> | |||
|         <record id="field_widget_selection_widget" model="field.widget"> | |||
|             <field name="name">selection</field> | |||
|             <field name="description">Selection</field> | |||
|         </record> | |||
|     </data> | |||
| </odoo> | |||
| @ -0,0 +1,11 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo noupdate="1"> | |||
|     <!--    Sequence for the quotation  --> | |||
|     <record id="seq_quotation" model="ir.sequence"> | |||
|         <field name="name">Quotation</field> | |||
|         <field name="code">sale.order</field> | |||
|         <field name="prefix">SQ</field> | |||
|         <field name="padding">5</field> | |||
|         <field name="company_id" eval="False"/> | |||
|     </record> | |||
| </odoo> | |||
| @ -0,0 +1,7 @@ | |||
| ## Module <all_in_one_sales_kit> | |||
| 
 | |||
| #### 07.12.2023 | |||
| #### Version 16.0.1.0.0 | |||
| #### ADD | |||
| 
 | |||
| - Initial commit for All in One Sales Kit | |||
| @ -0,0 +1,32 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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 field_widget | |||
| from . import ir_model_fields | |||
| from . import pack_product | |||
| from . import product_product | |||
| from . import product_template | |||
| from . import res_config_settings | |||
| from . import res_partner | |||
| from . import res_users | |||
| from . import sale_order | |||
| from . import sale_order_line | |||
| from . import sales_report | |||
| @ -0,0 +1,39 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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 FieldWidget(models.Model): | |||
|     """ | |||
|     Need of this model is because we can't filter a selection field dynamically | |||
|     so when we select a field its widgets also need to change according to | |||
|     field type, we can't do it by a 'selection' field, | |||
|     need a 'Many2one' field. | |||
|    """ | |||
| 
 | |||
|     _name = 'field.widget' | |||
|     _description = 'Field Widgets' | |||
|     _rec_name = 'description' | |||
| 
 | |||
|     name = fields.Char(string="Name", help="Name of widget.") | |||
|     description = fields.Char( | |||
|         string="Description", help="Description about the widget.") | |||
| @ -0,0 +1,32 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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 IrModelFields(models.Model): | |||
|     """Adding a new field to understand the dynamically created fields.""" | |||
| 
 | |||
|     _inherit = 'ir.model.fields' | |||
| 
 | |||
|     is_dynamic = fields.Boolean( | |||
|         string="Dynamic Field", | |||
|         help="To make sure it is a dynamically created field.") | |||
| @ -0,0 +1,84 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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, _ | |||
| from odoo.exceptions import ValidationError | |||
| 
 | |||
| 
 | |||
| class PackProduct(models.Model): | |||
|     """ A new model is created to store products as pack.""" | |||
| 
 | |||
|     _name = 'pack.product' | |||
|     _rec_name = 'product_tmpl_id' | |||
|     _description = 'Select Pack Products' | |||
| 
 | |||
|     product_id = fields.Many2one( | |||
|         'product.product', string='Product', required=True, | |||
|         domain=[('is_pack', '=', False)], help="Product") | |||
|     product_tmpl_id = fields.Many2one( | |||
|         'product.template', string='Product', help="Product") | |||
|     price = fields.Float( | |||
|         string='Price', compute='_compute_price', store=True, | |||
|         help="Computed price of product according to the quantity.") | |||
|     quantity = fields.Integer( | |||
|         string='Quantity', default=1, | |||
|         help="Quantity of product that should be in the pack.") | |||
|     qty_available = fields.Float( | |||
|         string='Quantity Available', compute='_compute_qty_available', | |||
|         store=True, readonly=False, help="Available quantity of product.") | |||
|     total_available_quantity = fields.Float( | |||
|         string='Total Quantity', | |||
|         help="Total Quantity available of that product") | |||
| 
 | |||
|     @api.depends('product_id', | |||
|                  'total_available_quantity', | |||
|                  'product_id.qty_available') | |||
|     def _compute_qty_available(self): | |||
|         """It is to compute the available quantity.""" | |||
|         for record in self: | |||
|             location_id = record.product_tmpl_id.pack_location_id | |||
|             if location_id: | |||
|                 stock_quant = self.env['stock.quant'].search( | |||
|                     [('product_id', '=', record.product_id.id), | |||
|                      ('location_id', '=', location_id.id)]) | |||
|                 if stock_quant: | |||
|                     record.qty_available = stock_quant.quantity | |||
|                 else: | |||
|                     record.qty_available = False | |||
|             else: | |||
|                 record.qty_available = False | |||
| 
 | |||
|     @api.depends('product_id', 'quantity') | |||
|     def _compute_price(self): | |||
|         """It is to compute price of each product compared to quantity.""" | |||
|         for record in self: | |||
|             record.price = record.product_id.lst_price * record.quantity | |||
| 
 | |||
|     @api.onchange('quantity') | |||
|     def _onchange_quantity(self): | |||
|         """It is to set price.""" | |||
|         self.price = self.product_id.lst_price * self.quantity | |||
| 
 | |||
|     @api.constrains('quantity') | |||
|     def _check_quantity(self): | |||
|         """This function is to ensure product quantity is positive.""" | |||
|         if any([product.quantity < 0 for product in self]): | |||
|             raise ValidationError(_('You can not enter negative quantities.')) | |||
| @ -0,0 +1,74 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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.exceptions import UserError | |||
| 
 | |||
| 
 | |||
| class ProductProduct(models.Model): | |||
|     """Inherits product.product.""" | |||
|     _inherit = "product.product" | |||
| 
 | |||
|     order_partner_id = fields.Many2one( | |||
|         'res.partner', string="Partner", help="Current Partner") | |||
| 
 | |||
|     def action_sale_product_prices(self): | |||
|         """It is to show to product history.""" | |||
|         rel_view_id = self.env.ref( | |||
|             'all_in_one_sales_kit.last_sale_product_prices_view') | |||
|         if self.order_partner_id.id: | |||
|             sale_lines = self.env['sale.order.line'].search( | |||
|                 [('product_id', '=', self.id), | |||
|                  ('order_partner_id', '=', self.order_partner_id.id)], | |||
|                 order='create_date DESC').ids | |||
|         else: | |||
|             sale_lines = self.env['sale.order.line'].search( | |||
|                 [('product_id', '=', self.id)], | |||
|                 order='create_date DESC').ids | |||
|         if not sale_lines: | |||
|             raise UserError("No sales history found.!") | |||
|         else: | |||
|             return { | |||
|                 'domain': [('id', 'in', sale_lines)], | |||
|                 'views': [(rel_view_id.id, 'tree')], | |||
|                 'name': 'Sales History', | |||
|                 'res_model': 'sale.order.line', | |||
|                 'view_id': False, | |||
|                 'type': 'ir.actions.act_window', | |||
|             } | |||
| 
 | |||
|     def action_add_quotation(self): | |||
|         """It is a button function on clicking the product is entered to | |||
|          the order line.""" | |||
|         order_id = self.env.context.get('order_id') | |||
|         list = self.env['sale.order.line'].search( | |||
|             [('order_id', '=', order_id)]).mapped('product_id') | |||
|         if self in list: | |||
|             order_line_id = self.env['sale.order.line'].search( | |||
|                 [('order_id', '=', order_id), ('product_id', '=', self.id)]) | |||
|             order_line_id.product_uom_qty += 1 | |||
|         else: | |||
|             self.env['sale.order.line'].create({ | |||
|                 'product_id': self.id, | |||
|                 'order_id': order_id, | |||
|                 'qty_available': self.qty_available, | |||
|                 'forecast_quantity': self.virtual_available, | |||
|             }) | |||
| @ -0,0 +1,139 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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, _ | |||
| from odoo.exceptions import UserError | |||
| 
 | |||
| 
 | |||
| class ProductTemplate(models.Model): | |||
|     """Inherits product.template.""" | |||
|     _inherit = 'product.template' | |||
| 
 | |||
|     def default_pack_location(self): | |||
|         """Sets the default value for the 'location_id' field based | |||
|         on the current user's warehouse.""" | |||
|         warehouse = self.env['stock.warehouse'].search( | |||
|             [('company_id', '=', self.env.company.id)], limit=1) | |||
|         if warehouse: | |||
|             return warehouse.lot_stock_id.id | |||
| 
 | |||
|     is_pack = fields.Boolean(string='Is a Pack', help="The product is a pack.") | |||
|     pack_price = fields.Integer( | |||
|         string="Pack Price", compute='_compute_pack_price', store=True, | |||
|         help="Total price of products inside the pack") | |||
|     pack_products_ids = fields.One2many( | |||
|         'pack.product', 'product_tmpl_id', | |||
|         string='Pack Products', copy=True, help="Products inside the pack") | |||
|     pack_quantity = fields.Integer( | |||
|         string='Pack Quantity', help="Pack quantity available") | |||
|     pack_location_id = fields.Many2one( | |||
|         'stock.location', | |||
|         domain=[('usage', 'in', ['internal', 'transit'])], | |||
|         default=default_pack_location, help="Warehouse", string="Warehouse") | |||
| 
 | |||
|     @api.depends('pack_products_ids', 'pack_products_ids.price') | |||
|     def _compute_pack_price(self): | |||
|         """It is to set total price of the pack according to the | |||
|         products in the pack.""" | |||
|         price = 0 | |||
|         for record in self: | |||
|             for line in record.pack_products_ids: | |||
|                 price = price + line.price | |||
|             record.pack_price = price | |||
| 
 | |||
|     @api.model | |||
|     def create(self, values): | |||
|         """Here create function is over ride to check whether the product is | |||
|         a pack or not.""" | |||
|         if values.get('is_pack', False): | |||
|             if not values.get('pack_products_ids', []): | |||
|                 raise UserError(_( | |||
|                     'You need to add atleast one product in the Pack...!')) | |||
|             if values.get('type', False) == 'service': | |||
|                 raise UserError(_( | |||
|                     'You cannot define a pack product as a service..!')) | |||
|         return super(ProductTemplate, self).create(values) | |||
| 
 | |||
|     def write(self, values): | |||
|         """Here, the write function is overridden to determine if | |||
|         there is at least one product inside the package.""" | |||
|         super(ProductTemplate, self).write(values) | |||
|         if self.is_pack: | |||
|             if not self.pack_products_ids: | |||
|                 raise UserError(_( | |||
|                     'You need to add atleast one product in the Pack...!')) | |||
|             if self.type == 'service': | |||
|                 raise UserError( | |||
|                     _('You cannot define a pack product as a service..!')) | |||
| 
 | |||
|     def action_update_price_product(self): | |||
|         """Updates the 'list_price' field of the current object | |||
|          based on the value of the 'pack_price' field on button click.""" | |||
|         self.list_price = self.pack_price | |||
| 
 | |||
|     def action_get_quantity(self): | |||
|         """It is to return the pack quantity.""" | |||
|         total_quantity = 1 | |||
|         flag = 1 | |||
|         while flag: | |||
|             for line in self.pack_products_ids: | |||
|                 if line.qty_available >= line.quantity * total_quantity: | |||
|                     continue | |||
|                 else: | |||
|                     if line.product_id.type != 'product': | |||
|                         continue | |||
|                     flag = 0 | |||
|                     break | |||
|             if flag: | |||
|                 total_quantity = total_quantity + 1 | |||
|         self.pack_quantity = total_quantity - 1 | |||
| 
 | |||
|     def action_update_quantity(self): | |||
|         """It is to return the  updated pack quantity.""" | |||
|         product_id = len( | |||
|             self.product_variant_ids) == 1 and self.product_variant_id.id | |||
|         location_id = self.pack_location_id.id | |||
|         if not location_id: | |||
|             warehouse = self.env['stock.warehouse'].search( | |||
|                 [('company_id', '=', self.env.company.id)], limit=1) | |||
|             location_id = warehouse.lot_stock_id.id | |||
|             if not location_id: | |||
|                 raise UserError(_( | |||
|                     'You need to select the location to update' | |||
|                     ' the pack quantity...!')) | |||
|         self.env['stock.quant'].with_context(inventory_mode=True).sudo( | |||
|         ).create({ | |||
|             'product_id': product_id, | |||
|             'location_id': location_id, | |||
|             'inventory_quantity': self.pack_quantity, | |||
|         }) | |||
| 
 | |||
|     @api.onchange('pack_location_id') | |||
|     def _onchange_pack_location_id(self): | |||
|         """It is to change the available quantity based on location.""" | |||
|         for line in self.pack_products_ids: | |||
|             stock_quant = self.env['stock.quant'].search( | |||
|                 [('product_id', '=', line.product_id.id), | |||
|                  ('location_id', '=', self.pack_location_id.id)]) | |||
|             if stock_quant: | |||
|                 line.total_available_quantity = stock_quant.quantity | |||
|             else: | |||
|                 line.total_available_quantity = stock_quant.quantity | |||
| @ -0,0 +1,90 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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 ResConfigSettings(models.TransientModel): | |||
|     """ This is to add new fields to the settings.res.config.settings is | |||
|     inherited.""" | |||
|     _inherit = 'res.config.settings' | |||
| 
 | |||
|     show_product_image_in_sale_report = fields.Boolean( | |||
|         string="Show Product Image", default=False, | |||
|         help="Enable Show Product Image") | |||
|     sale_document_approve = fields.Boolean( | |||
|         config_parameter='all_in_one_sales_kit.sale_document_approve', | |||
|         string="Sale Document Approval", | |||
|         help="Sale Approval") | |||
|     product_restriction = fields.Boolean( | |||
|         string='Out Of Stock Product Restriction', | |||
|         help='Enable Out Of Stock Product Restriction') | |||
|     check_stock = fields.Selection( | |||
|         [('on_hand_quantity', 'On Hand Quantity'), | |||
|          ('forecast_quantity', 'Forecast Quantity')], string="Based On", | |||
|         help='Choose the type of restriction') | |||
|     automate_invoice = fields.Boolean( | |||
|         string='Create Invoice', default=False, | |||
|         help="Create invoices for sales order") | |||
|     automate_validate_invoice = fields.Boolean( | |||
|         string='Validate Invoice', default=False, | |||
|         help="Automate validation of invoice") | |||
|     automate_print_invoices = fields.Boolean( | |||
|         string='Print Invoices', default=False, | |||
|         help="Print invoice from corresponding sales order") | |||
| 
 | |||
|     @api.model | |||
|     def set_values(self): | |||
|         """The function set_values() is to store the new fields values.""" | |||
|         self.env['ir.config_parameter'].sudo().set_param( | |||
|             'sale_product_image.show_product_image_in_sale_report', | |||
|             self.show_product_image_in_sale_report) | |||
|         self.env['ir.config_parameter'].sudo().set_param( | |||
|             'sale_stock_restrict.product_restriction', | |||
|             self.product_restriction) | |||
|         self.env['ir.config_parameter'].sudo().set_param( | |||
|             'sale_stock_restrict.check_stock', self.check_stock) | |||
|         self.env['ir.config_parameter'].sudo().set_param( | |||
|             'automate_print_invoices', self.automate_print_invoices) | |||
|         self.env['ir.config_parameter'].sudo().set_param( | |||
|             'automate_invoice', self.automate_invoice) | |||
|         self.env['ir.config_parameter'].sudo().set_param( | |||
|             'automate_validate_invoice', self.automate_validate_invoice) | |||
|         res = super(ResConfigSettings, self).set_values() | |||
|         return res | |||
| 
 | |||
|     def get_values(self): | |||
|         """Show the new field values.""" | |||
|         res = super(ResConfigSettings, self).get_values() | |||
|         ir_config_param = self.env['ir.config_parameter'].sudo().get_param | |||
|         res.update( | |||
|             show_product_image_in_sale_report=ir_config_param( | |||
|                 'sale_product_image.show_product_image_in_sale_report', | |||
|                 self.show_product_image_in_sale_report), | |||
|             product_restriction=ir_config_param( | |||
|                 'sale_stock_restrict.product_restriction'), | |||
|             check_stock=ir_config_param('sale_stock_restrict.check_stock'), | |||
|             automate_print_invoices=ir_config_param('automate_print_invoices'), | |||
|             automate_invoice=ir_config_param('automate_invoice'), | |||
|             automate_validate_invoice=ir_config_param( | |||
|                 'automate_validate_invoice'), | |||
|         ) | |||
|         return res | |||
| @ -0,0 +1,40 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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): | |||
|     """res.partner is inherited.""" | |||
|     _inherit = 'res.partner' | |||
| 
 | |||
|     def action_view_sale_order(self): | |||
|         """This is to add a new pivot view to customer to show | |||
|         their sale orders.""" | |||
|         action = self.env['ir.actions.act_window']._for_xml_id( | |||
|             'sale.act_res_partner_2_sale_order') | |||
|         all_child = self.with_context(active_test=False).search( | |||
|             [('id', 'child_of', self.ids)]) | |||
|         action["domain"] = [("partner_id", "in", all_child.ids)] | |||
|         action["view_mode"] = "tree,kanban,form,graph,pivot" | |||
|         action["views"] = [(False, 'tree'), (False, 'kanban'), | |||
|                            (False, 'form'), (False, 'graph'), (False, 'pivot')] | |||
|         return action | |||
| @ -0,0 +1,35 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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 ResUsers(models.Model): | |||
|     """Here res.users is inherited to add two fields.""" | |||
| 
 | |||
|     _inherit = 'res.users' | |||
| 
 | |||
|     discount_control = fields.Boolean( | |||
|         string='Discount Control', default=False, | |||
|         help="Enable to set a discount limit value.") | |||
|     allow_discount = fields.Float( | |||
|         string='Allow Discount', | |||
|         help="Enter the discount limit in percentage here.") | |||
| @ -0,0 +1,492 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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/>. | |||
| # | |||
| ############################################################################### | |||
| import itertools | |||
| from odoo import api, fields, models, _ | |||
| from odoo.exceptions import UserError | |||
| 
 | |||
| 
 | |||
| class SaleOrder(models.Model): | |||
|     """Inherits Sales""" | |||
|     _inherit = "sale.order" | |||
| 
 | |||
|     is_version = fields.Boolean(string="Is Version", | |||
|                                 help="For checking version or not") | |||
|     version_count = fields.Integer(string="Sale Version Count", | |||
|                                    compute='_compute_version_count', | |||
|                                    help="Count of version created") | |||
|     current_version_id = fields.Many2one("sale.order", | |||
|                                          string="Current Version", | |||
|                                          help="For creating versions") | |||
|     version_ids = fields.One2many("sale.order", | |||
|                                   string="Version", | |||
|                                   inverse_name="current_version_id", | |||
|                                   help="Versions created") | |||
|     quotation_ref = fields.Char(string='Quotation Reference', | |||
|                                 copy=False, readonly=True, tracking=True, | |||
|                                 help="Quotation Reference") | |||
|     state = fields.Selection( | |||
|         selection_add=[('waiting_for_approval', 'Waiting For Approval'), | |||
|                        ('sale',)]) | |||
|     approval_user_id = fields.Many2one('res.users', | |||
|                                        string='Discount Approved By', | |||
|                                        help="Discount approving person.") | |||
|     onhand_check = fields.Boolean(string='Enable OnHand', | |||
|                                   help='To check whether it is based on' | |||
|                                        ' on hand quantity') | |||
|     forecast_check = fields.Boolean(string='Enable Forecast', | |||
|                                     help='To check whether it is based on' | |||
|                                          ' Forecast quantity') | |||
|     automate_print_invoices = fields.Boolean( | |||
|         string='Print Invoices', | |||
|         help="Print invoices for corresponding sale orders") | |||
|     signature = fields.Binary(string='Signature', | |||
|                               help="Field for adding " | |||
|                                    "the signature of the " | |||
|                                    "sales person") | |||
|     check_signature = fields.Boolean(compute='_compute_check_signature', | |||
|                                      help="To check signature approval is " | |||
|                                           "needed") | |||
|     settings_approval = fields.Boolean(compute='_compute_settings_approval', | |||
|                                      help="To check signature approval is " | |||
|                                        "enabled in settings") | |||
|     active = fields.Boolean(string='Active', help='Active', default=True) | |||
|     user_salesperson = fields.Boolean(string="User Salesperson", | |||
|                                       compute="_compute_user_salesperson", | |||
|                                       help="Check if user is salesperson") | |||
| 
 | |||
|     @api.depends('user_salesperson') | |||
|     def _compute_user_salesperson(self): | |||
|         """Computes the user_salesperson field based on login user""" | |||
|         for rec in self: | |||
|             if rec.user_id == rec.env.user: | |||
|                 rec.user_salesperson = True | |||
|             else: | |||
|                 rec.user_salesperson = False | |||
| 
 | |||
|     @api.depends('signature') | |||
|     def _compute_check_signature(self): | |||
|         """In this function computes the value of | |||
|         the boolean field check signature | |||
|         which is used to hide/unhide the validate | |||
|          button in the current document""" | |||
|         if self.env['ir.config_parameter'].sudo().get_param( | |||
|                 'all_in_one_sales_kit.sale_document_approve'): | |||
|             if self.signature: | |||
|                 self.check_signature = True | |||
|             else: | |||
|                 self.check_signature = False | |||
|         else: | |||
|             self.check_signature = True | |||
| 
 | |||
|     def action_create_versions(self): | |||
|         """For creating the versions of the sale order""" | |||
|         sale_order_copy_id = self.copy() | |||
|         sale_order_copy_id.is_version = True | |||
|         length = len(self.version_ids) | |||
|         sale_order_copy_id.name = "%s-%s" % (self.name, str(length + 1)) | |||
| 
 | |||
|         self.write({'version_ids': [(4, sale_order_copy_id.id)]}) | |||
| 
 | |||
|     @api.depends('version_ids') | |||
|     def _compute_version_count(self): | |||
|         """For calculating the number of versions created""" | |||
|         for sale in self: | |||
|             sale.version_count = len(sale.version_ids) | |||
| 
 | |||
|     @api.depends('partner_id') | |||
|     def _compute_settings_approval(self): | |||
|         """Computes the settings_approval field based on settings field.""" | |||
|         for rec in self: | |||
|             if rec.env['ir.config_parameter'].sudo().get_param( | |||
|                     'all_in_one_sales_kit.sale_document_approve'): | |||
|                 rec.settings_approval = True | |||
|             else: | |||
|                 rec.settings_approval = False | |||
| 
 | |||
|     def action_view_versions(self): | |||
|         """Action for viewing versions""" | |||
|         action = { | |||
|             "type": "ir.actions.act_window", | |||
|             "view_mode": "kanban,tree,form", | |||
|             "name": _("Sale Order Versions"), | |||
|             "res_model": self._name, | |||
|             "domain": [('id', 'in', self.version_ids.ids)], | |||
|             "target": "current", | |||
|         } | |||
|         return action | |||
| 
 | |||
|     def action_confirm(self): | |||
|         """Override the confirm button of the sale order for cancelling the | |||
|         other versions and making the current version main,also method for | |||
|          confirming the sale order discount and sending mail for the approving | |||
|          person if approval limit crossed.Super the method create to confirm | |||
|           quotation, create and validate invoice""" | |||
|         res = super().action_confirm() | |||
|         automate_invoice = self.env[ | |||
|             'ir.config_parameter'].sudo().get_param( | |||
|             'automate_invoice') | |||
|         automate_print_invoices = self.env[ | |||
|             'ir.config_parameter'].sudo().get_param( | |||
|             'automate_print_invoices') | |||
|         automate_validate_invoice = self.env[ | |||
|             'ir.config_parameter'].sudo().get_param( | |||
|             'automate_validate_invoice') | |||
|         if automate_print_invoices: | |||
|             self.automate_print_invoices = True | |||
|         if automate_invoice: | |||
|             self._create_invoices() | |||
|             if automate_validate_invoice: | |||
|                 self.invoice_ids.action_post() | |||
|         if not self.version_ids: | |||
|             parent_sale = self.current_version_id | |||
|             versions = parent_sale.mapped('version_ids').ids | |||
|             if versions: | |||
|                 versions.append(parent_sale.id) | |||
|             for version in parent_sale.version_ids: | |||
|                 if version.state == 'sale': | |||
|                     # Updating the version name into main version name and | |||
|                     # other versions state into cancel | |||
|                     version.current_version_id.update({'is_version': True, | |||
|                                                        'state': 'cancel'}) | |||
|                     version.update({'version_ids': versions, | |||
|                                     "name": version.current_version_id.name, | |||
|                                     'is_version': False}) | |||
|                 if version.state == 'draft': | |||
|                     version.update({'state': 'cancel'}) | |||
|         else: | |||
|             if self.state == 'sale': | |||
|                 for sale in self.version_ids: | |||
|                     sale.update({'state': 'cancel'}) | |||
|         low_qty = ["Can't confirm the sale order due to: \n"] | |||
|         for rec in self.order_line: | |||
|             product_restriction = self.env[ | |||
|                 'ir.config_parameter'].sudo().get_param( | |||
|                 'sale_stock_restrict.product_restriction') | |||
|             check_stock = self.env[ | |||
|                 'ir.config_parameter'].sudo().get_param( | |||
|                 'sale_stock_restrict.check_stock') | |||
|             if product_restriction: | |||
|                 if rec.product_id.detailed_type == 'product': | |||
|                     if check_stock == 'on_hand_quantity': | |||
|                         if rec.product_uom_qty > rec.qty_available: | |||
|                             self.onhand_check = True | |||
|                             onhand_qty_list = "You have added %s units of %s" \ | |||
|                                               " but you only have %s units" \ | |||
|                                               " available.\n" % ( | |||
|                                                   rec.product_uom_qty, | |||
|                                                   rec.product_id.name, | |||
|                                                   rec.qty_available) | |||
|                             low_qty.append(onhand_qty_list) | |||
| 
 | |||
|                     if check_stock == 'forecast_quantity': | |||
|                         if rec.product_uom_qty > rec.forecast_quantity: | |||
|                             self.forecast_check = True | |||
|                             forecast_qty_list = "You have added %s" \ | |||
|                                                 " units of %s but " \ | |||
|                                                 "you only have" \ | |||
|                                                 " %s units available.\n" % ( | |||
|                                                     rec.product_uom_qty, | |||
|                                                     rec.product_id.name, | |||
|                                                     rec.forecast_quantity) | |||
|                             low_qty.append(forecast_qty_list) | |||
|         listToStr = ' '.join(map(str, low_qty)) | |||
|         if self.onhand_check: | |||
|             raise UserError(listToStr) | |||
|         if self.forecast_check: | |||
|             raise UserError(listToStr) | |||
|         to_approve = False | |||
|         discount_vals = self.order_line.mapped('discount') | |||
|         approval_users = self.env.ref( | |||
|             'all_in_one_sales_kit.group_approval_manager').users | |||
|         user_discount = self.env.user.allow_discount | |||
|         if self.env.user.discount_control == True: | |||
|             for rec in discount_vals: | |||
|                 if rec > user_discount: | |||
|                     to_approve = True | |||
|                     break | |||
|         if to_approve: | |||
|             display_id = self.id | |||
|             action_id = self.env.ref( | |||
|                 'sale.action_quotations_with_onboarding').id | |||
|             base_url = self.env['ir.config_parameter'].sudo().get_param( | |||
|                 'web.base.url') | |||
|             redirect_link = "/web#id=%s&cids=1&menu_id=178&action=%s" \ | |||
|                             "&model" \ | |||
|                             "=sale.order&view_type=form" % ( | |||
|                                 display_id, action_id) | |||
|             url = base_url + redirect_link | |||
|             for user in approval_users: | |||
|                 mail_body = """ | |||
|                         <p>Hello,</p> | |||
|                                <p>New sale order '%s'  | |||
|                                Created with Discount by '%s'  | |||
|                                need your approval on it.</p> | |||
|                                <p>To Approve, Cancel Order, | |||
|                                 Click on the Following  | |||
|                                Link: | |||
|                                <a href='%s' style="display: inline-block;  | |||
|                                padding: 10px; text-decoration: none;  | |||
|                                font-size: 12px; | |||
|                                background-color: #875A7B; color: #fff;  | |||
|                                border-radius: 5px;"> | |||
|                                <strong>Click Me</strong></a> | |||
|                                </p> | |||
|                                <p>Thank You.</p>""" % (self.name, | |||
|                                                        self.env.user.name, | |||
|                                                        url) | |||
|                 mail_values = { | |||
|                     'subject': "'%s' Discount Approval Request" % (self.name), | |||
|                     'body_html': mail_body, | |||
|                     'email_to': user.partner_id.email, | |||
|                     'model': 'sale.order', | |||
|                 } | |||
|                 mail_id = self.env['mail.mail'].sudo().create(mail_values) | |||
|                 mail_id.sudo().send() | |||
|             self.state = 'waiting_for_approval' | |||
|         for line in self.order_line: | |||
|             if line.product_id.is_pack: | |||
|                 for record in line.product_id.pack_products_ids: | |||
|                     dest_loc = self.env.ref( | |||
|                         'stock.stock_location_customers').id | |||
|                     self.env['stock.move'].create({ | |||
|                         'name': record.product_id.name, | |||
|                         'product_id': record.product_id.id, | |||
|                         'product_uom_qty': | |||
|                             record.quantity * line.product_uom_qty, | |||
|                         'product_uom': record.product_id.uom_id.id, | |||
|                         'picking_id': self.picking_ids[0].id, | |||
|                         'location_id': | |||
|                             self.picking_ids.picking_type_id.default_location_src_id.id, | |||
|                         'location_dest_id': dest_loc, | |||
|                     }) | |||
|             return res | |||
| 
 | |||
|     @api.model | |||
|     def create(self, vals): | |||
|         """Method for generating sequence for quotation """ | |||
|         res = super(SaleOrder, self).create(vals) | |||
|         seq_val = self.env.ref( | |||
|             'all_in_one_sales_kit.seq_quotation').id | |||
|         res.quotation_ref = self.env['ir.sequence'].browse( | |||
|             seq_val).next_by_id() | |||
|         return res | |||
| 
 | |||
|     def action_waiting_approval(self): | |||
|         """Method for approving the sale order discount""" | |||
|         self.approval_user_id = self.env.user.id | |||
|         self.state = 'sale' | |||
| 
 | |||
|     def action_print_invoice(self): | |||
|         """Method to print invoice""" | |||
|         data = self.invoice_ids | |||
|         return self.env.ref('account.account_invoices').report_action(data) | |||
| 
 | |||
|     @api.model | |||
|     def get_data(self): | |||
|         """To get data to the sales dashboard.""" | |||
|         domain = [('user_id', '=', self.env.user.id)] | |||
|         quotation = self.env['sale.order'].search( | |||
|             domain + [('state', '=', 'draft')]) | |||
|         my_sale_order_templates = self.env['sale.order'].search( | |||
|             domain + [('state', '=', 'sale')]) | |||
|         quotation_sent = self.env['sale.order'].search( | |||
|             domain + [('state', '=', 'sent')]) | |||
|         quotation_cancel = self.env['sale.order'].search( | |||
|             domain + [('state', '=', 'cancel')]) | |||
|         customers = self.env['res.partner'].search([]) | |||
|         to_invoice = self.env['sale.order'].search( | |||
|             domain + [('invoice_status', '=', 'to invoice')]) | |||
|         products = self.env['product.template'].search([]) | |||
|         return { | |||
|             'quotation': len(quotation), | |||
|             'my_sale_order_templates': len(my_sale_order_templates), | |||
|             'quotation_sent': len(quotation_sent), | |||
|             'quotation_cancel': len(quotation_cancel), | |||
|             'customers': len(customers), | |||
|             'products': len(products), | |||
|             'to_invoice': len(to_invoice), | |||
|         } | |||
| 
 | |||
|     @api.model | |||
|     def get_value(self, start_date, end_date): | |||
|         """It is to pass values according to start and end date to the | |||
|         dashboard.""" | |||
|         domain = [('user_id', '=', self.env.user.id), | |||
|                   ('date_order', '>=', start_date), | |||
|                   ('date_order', '<=', end_date)] | |||
|         if start_date and end_date: | |||
|             quotation = self.env['sale.order'].search( | |||
|                 domain + [('state', '=', 'draft')]) | |||
|             my_sale_order_templates = self.env['sale.order'].search( | |||
|                 domain + [('state', '=', 'sale')]) | |||
|             quotation_sent = self.env['sale.order'].search( | |||
|                 domain + [('state', '=', 'sent')]) | |||
|             quotation_cancel = self.env['sale.order'].search( | |||
|                 domain + [('state', '=', 'cancel')]) | |||
|             customers = self.env['res.partner'].search([]) | |||
|             products = self.env['product.template'].search([]) | |||
|             to_invoice = self.env['sale.order'].search( | |||
|                 domain + [('invoice_status', '=', 'to invoice')]) | |||
|         elif start_date: | |||
|             quotation = self.env['sale.order'].search( | |||
|                 domain + [('state', '=', 'draft')]) | |||
|             my_sale_order_templates = self.env['sale.order'].search( | |||
|                 domain + [('state', '=', 'sale')]) | |||
|             quotation_sent = self.env['sale.order'].search( | |||
|                 domain + [('state', '=', 'sent')]) | |||
|             quotation_cancel = self.env['sale.order'].search( | |||
|                 domain + [('state', '=', 'cancel')]) | |||
|             customers = self.env['res.partner'].search([]) | |||
|             products = self.env['product.template'].search([]) | |||
|             to_invoice = self.env['sale.order'].search( | |||
|                 domain + [('invoice_status', '=', 'to invoice')]) | |||
|         elif end_date: | |||
|             quotation = self.env['sale.order'].search( | |||
|                 domain + [('state', '=', 'draft')]) | |||
|             my_sale_order_templates = self.env['sale.order'].search( | |||
|                 domain + [('state', '=', 'sale')]) | |||
|             quotation_sent = self.env['sale.order'].search( | |||
|                 domain + [('state', '=', 'sent')]) | |||
|             quotation_cancel = self.env['sale.order'].search( | |||
|                 domain + [('state', '=', 'cancel')]) | |||
|             customers = self.env['res.partner'].search([]) | |||
|             products = self.env['product.template'].search([]) | |||
|             to_invoice = self.env['sale.order'].search( | |||
|                 domain + [('invoice_status', '=', 'to invoice')]) | |||
|         return { | |||
|             'quotation': len(quotation), | |||
|             'my_sale_order_templates': len(my_sale_order_templates), | |||
|             'quotation_sent': len(quotation_sent), | |||
|             'quotation_cancel': len(quotation_cancel), | |||
|             'customers': len(customers), | |||
|             'products': len(products), | |||
|             'to_invoice': len(to_invoice), | |||
|         } | |||
| 
 | |||
|     @api.model | |||
|     def get_lead_customer(self): | |||
|         """Returns customer data to the graph of dashboard""" | |||
|         lead_template = {} | |||
|         sale = {} | |||
|         partner_id = self.env['res.partner'].sudo().search([]) | |||
|         vals = self.env['sale.order'].sudo().search([ | |||
|         ]).mapped('partner_id').ids | |||
|         for record in partner_id: | |||
|             if record.id in vals: | |||
|                 record.ref = vals.count(record.id) | |||
|                 sale.update({record: vals.count(record.id)}) | |||
|         sort = dict( | |||
|             sorted(sale.items(), key=lambda item: item[1], reverse=True)) | |||
|         out = dict(itertools.islice(sort.items(), 10)) | |||
|         for count in out: | |||
|             lead_template[count.name] = out[count] | |||
|         return { | |||
|             'lead_templates': lead_template, | |||
|         } | |||
| 
 | |||
|     @api.model | |||
|     def get_lead_product(self): | |||
|         """Returns product data to the graph of dashboard""" | |||
|         lead_template = {} | |||
|         sale = {} | |||
|         product_id = self.env['product.template'].search([]) | |||
|         for record in product_id: | |||
|             sale.update({record: record.sales_count}) | |||
|         sort = dict( | |||
|             sorted(sale.items(), key=lambda item: item[1], reverse=True)) | |||
|         out = dict(itertools.islice(sort.items(), 10)) | |||
|         for product in out: | |||
|             lead_template[product.name] = out[product] | |||
|         return { | |||
|             'lead_templates': lead_template, | |||
|         } | |||
| 
 | |||
|     @api.model | |||
|     def get_lead_order(self): | |||
|         """Returns lead sale order data to the graph of dashboard""" | |||
|         lead_template = {} | |||
|         sale = {} | |||
|         order_id = self.env['sale.order'].search([('state', '=', 'sale')]) | |||
|         for record in order_id: | |||
|             sale.update({record: record.amount_total}) | |||
|         sort = dict( | |||
|             sorted(sale.items(), key=lambda item: item[1], reverse=True)) | |||
|         out = dict(itertools.islice(sort.items(), 10)) | |||
|         for order in out: | |||
|             lead_template[order.name] = out[order] | |||
|         return { | |||
|             'lead_templates': lead_template, | |||
|         } | |||
| 
 | |||
|     @api.model | |||
|     def get_my_monthly_comparison(self): | |||
|         """Returns my monthly sale count data to the graph of dashboard""" | |||
|         lead_template = {} | |||
|         sales_order = self.env['sale.order'].search( | |||
|             [('user_id', '=', self.env.user.id)]) | |||
|         list = [rec.date_order.month for rec in sales_order] | |||
|         for i in range(1, 13): | |||
|             count = list.count(i) | |||
|             lead_template.update({ | |||
|                 i: count | |||
|             }) | |||
|         return { | |||
|             'lead_templates': lead_template, | |||
|         } | |||
| 
 | |||
|     @api.model | |||
|     def get_sales_team(self): | |||
|         """Returns sales team data to the graph of dashboard""" | |||
|         lead_template = {} | |||
|         sale = {} | |||
|         sales_team = self.env['crm.team'].search([]) | |||
|         for record in sales_team: | |||
|             total = sum(self.env['sale.order'].search( | |||
|                 [('state', '=', 'sale'), | |||
|                  ('team_id', '=', record.id)]).mapped('amount_total')) | |||
|             sale.update({record: total}) | |||
|         sort = dict( | |||
|             sorted(sale.items(), key=lambda item: item[1], reverse=True)) | |||
|         out = dict(itertools.islice(sort.items(), 10)) | |||
|         for team in out: | |||
|             lead_template[team.name] = out[team] | |||
|         return { | |||
|             'lead_templates': lead_template, | |||
|         } | |||
| 
 | |||
|     @api.model | |||
|     def get_least_sold(self): | |||
|         """Returns least sold product data to the graph of dashboard""" | |||
|         lead_template = {} | |||
|         sale = {} | |||
|         product_id = self.env['product.template'].search([]) | |||
|         for record in product_id: | |||
|             if record.sales_count != 0: | |||
|                 sale.update({record: record.sales_count}) | |||
|         sort = dict( | |||
|             sorted(sale.items(), key=lambda item: item[1], reverse=False)) | |||
|         out = dict(itertools.islice(sort.items(), 10)) | |||
|         for product in out: | |||
|             lead_template[product.name] = out[product] | |||
|         return { | |||
|             'lead_templates': lead_template, | |||
|         } | |||
| @ -0,0 +1,201 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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, _ | |||
| from odoo.tools import float_compare | |||
| 
 | |||
| 
 | |||
| class SaleOrderLine(models.Model): | |||
|     """Inherits sale.order.line.""" | |||
|     _inherit = 'sale.order.line' | |||
| 
 | |||
|     sale_date = fields.Datetime(comodel_name='sale.order', string='Sale Date', | |||
|                                 related='order_id.date_order', store=True, | |||
|                                 help="Sale order date") | |||
|     product_warehouse_id = fields.Many2one( | |||
|         'stock.warehouse', | |||
|         string='Warehouse', help='Warehouses') | |||
|     order_line_image = fields.Binary(string="Image", | |||
|                                      related="product_id.image_1920", | |||
|                                      help="Product image should be shown or " | |||
|                                           "not.") | |||
|     contact_email = fields.Char(string="Email", | |||
|                                 related="order_partner_id.email", | |||
|                                 help="Email of the customer.") | |||
|     contact_phone = fields.Char(string="Phone no.", | |||
|                                 related="order_partner_id.phone", | |||
|                                 help="Phone no. of the customer.") | |||
|     qty_available = fields.Float(string="On Hand Quantity", | |||
|                                  help='Count of On Hand quantity') | |||
|     forecast_quantity = fields.Float(string="Forecast Quantity", | |||
|                                      help='Count of Forecast quantity') | |||
|     discount = fields.Float(string='Discount (%)', | |||
|                             digits=(16, 2), default=0.0, | |||
|                             help="Discount in percentage.") | |||
|     total_discount = fields.Float(string="Total Discount", | |||
|                                   default=0.0, store=True, | |||
|                                   help="Total Discount.") | |||
|     barcode_scan = fields.Char(string='Product Barcode', | |||
|                                help="Here you can provide " | |||
|                                     "the barcode for the product") | |||
| 
 | |||
|     def action_get_product_form(self): | |||
|         """ | |||
|            This method returns an action that opens a form view for a specific product. | |||
|            It sets the order partner ID based on the order's partner ID and constructs an action | |||
|            to open the product's form view with the product's details. | |||
|            :return: Dictionary representing an action to open the product's form view. | |||
|            :rtype: dict | |||
|            """ | |||
|         self.product_id.order_partner_id = self.order_id.partner_id.id | |||
|         return { | |||
|             'name': self.product_id.name, | |||
|             'view_mode': 'form', | |||
|             'res_model': 'product.product', | |||
|             'type': 'ir.actions.act_window', | |||
|             'target': 'current', | |||
|             'res_id': self.product_id.id | |||
|         } | |||
| 
 | |||
|     def _action_launch_stock_rule(self, previous_product_uom_qty=False): | |||
|         """ | |||
|              Overwriting the function for adding functionalities of | |||
|              multiple warehouses in the sale order line. | |||
|              param previous_product_uom_qty(str): | |||
|              Uom quantity of previous product | |||
|              boolean: Returns True, if the picking created. | |||
|             """ | |||
|         if self._context.get("skip_procurement"): | |||
|             return True | |||
|         precision = self.env['decimal.precision'].precision_get( | |||
|             'Product Unit of Measure') | |||
|         procurements = [] | |||
|         for line in self: | |||
|             line = line.with_company(line.company_id) | |||
|             if line.state != 'sale' or not line.product_id.type in ( | |||
|                     'consu', 'product'): | |||
|                 continue | |||
|             qty = line._get_qty_procurement(previous_product_uom_qty) | |||
|             if float_compare(qty, line.product_uom_qty, | |||
|                              precision_digits=precision) == 0: | |||
|                 continue | |||
|             group_id = line._get_procurement_group() | |||
|             if not group_id: | |||
|                 group_id = self.env['procurement.group'].create( | |||
|                     line._prepare_procurement_group_vals()) | |||
|                 line.order_id.procurement_group_id = group_id | |||
|             else: | |||
|                 updated_vals = {} | |||
|                 if group_id.partner_id != line.order_id.partner_shipping_id: | |||
|                     updated_vals.update( | |||
|                         {'partner_id': line.order_id.partner_shipping_id.id}) | |||
|                 if group_id.move_type != line.order_id.picking_policy: | |||
|                     updated_vals.update( | |||
|                         {'move_type': line.order_id.picking_policy}) | |||
|                 if updated_vals: | |||
|                     group_id.write(updated_vals) | |||
|             values = line._prepare_procurement_values(group_id=group_id) | |||
|             #replacing default warehouse_id into product_warehouse_id in the | |||
|             #sale order line and adding it into procurement values. | |||
|             if line.product_warehouse_id: | |||
|                 values['warehouse_id'] = line.product_warehouse_id | |||
|             product_qty = line.product_uom_qty - qty | |||
|             line_uom = line.product_uom | |||
|             quant_uom = line.product_id.uom_id | |||
|             product_qty, procurement_uom = line_uom._adjust_uom_quantities( | |||
|                 product_qty, quant_uom) | |||
|             procurements.append(self.env['procurement.group'].Procurement( | |||
|                 line.product_id, product_qty, procurement_uom, | |||
|                 line.order_id.partner_shipping_id.property_stock_customer, | |||
|                 line.product_id.display_name, line.order_id.name, | |||
|                 line.order_id.company_id, values)) | |||
|         if procurements: | |||
|             self.env['procurement.group'].run(procurements) | |||
|         orders = self.mapped('order_id') | |||
|         for order in orders: | |||
|             pickings_to_confirm = order.picking_ids.filtered( | |||
|                 lambda p: p.state not in ['cancel', 'done']) | |||
|             if pickings_to_confirm: | |||
|                 pickings_to_confirm.action_confirm() | |||
|         return True | |||
| 
 | |||
|     @api.onchange('product_id') | |||
|     def _onchange_product_id(self): | |||
|         """it is to check product stock according th the chosen product | |||
|         restriction.""" | |||
|         product_restriction = self.env['ir.config_parameter'].sudo().get_param( | |||
|             'sale_stock_restrict.product_restriction') | |||
|         check_stock = self.env[ | |||
|             'ir.config_parameter'].sudo().get_param( | |||
|             'sale_stock_restrict.check_stock') | |||
|         if product_restriction: | |||
|             if check_stock == 'on_hand_quantity': | |||
|                 self.qty_available = self.product_id.qty_available | |||
|             if check_stock == 'forecast_quantity': | |||
|                 self.forecast_quantity = self.product_id.virtual_available | |||
| 
 | |||
|     @api.onchange('barcode_scan') | |||
|     def _onchange_barcode_scan(self): | |||
|         """It is to add the scanned products to the order line.""" | |||
|         product_rec = self.env['product.product'] | |||
|         if self.barcode_scan: | |||
|             product = product_rec.search([('barcode', '=', self.barcode_scan)]) | |||
|             self.product_id = product.id | |||
| 
 | |||
|     def action_get_product_history_data(self): | |||
|         """It is to pass previous history of the chosen product for that | |||
|          customer.""" | |||
|         values = [] | |||
|         customer_id = self.order_id.partner_id | |||
|         customer_order = self.env['sale.order'].search( | |||
|             [('partner_id', '=', customer_id.id), ( | |||
|                 'state', 'in', ('sale', 'done'))]) | |||
|         for order in customer_order: | |||
|             for line in order.order_line: | |||
|                 if line.product_id == self.product_id: | |||
|                     values.append((0, 0, {'sale_order_id': order.id, | |||
|                                           'history_price': line.price_unit, | |||
|                                           'history_qty': line.product_uom_qty, | |||
|                                           'history_total': order.amount_total | |||
|                                           })) | |||
|         history_id = self.env['product.sale.order.history'].create({ | |||
|             'product_id': self.product_id.id, | |||
|             'product_sale_history_ids': values | |||
|         }) | |||
|         return { | |||
|             'name': 'Customer Product Sales History', | |||
|             'view_mode': 'form', | |||
|             'res_model': 'product.sale.order.history', | |||
|             'type': 'ir.actions.act_window', | |||
|             'target': 'new', | |||
|             'res_id': history_id.id | |||
|         } | |||
| 
 | |||
|     def action_add_catalog_control(self): | |||
|         """It is to add function to the button catalog.""" | |||
|         return { | |||
|             'type': 'ir.actions.act_window', | |||
|             'name': _('Products'), | |||
|             'context': {'order_id': self.env.context.get('id')}, | |||
|             'res_model': 'product.product', | |||
|             'view_mode': 'kanban,tree,form', | |||
|             'target': 'current', | |||
|         } | |||
| @ -0,0 +1,540 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.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/>. | |||
| # | |||
| ############################################################################# | |||
| import io | |||
| from odoo import api, fields, models | |||
| 
 | |||
| try: | |||
|     from odoo.tools.misc import xlsxwriter | |||
| except ImportError: | |||
|     import xlsxwriter | |||
| 
 | |||
| 
 | |||
| class SalesReport(models.Model): | |||
|     """A new class sales.report is created.""" | |||
|     _name = "sales.report" | |||
|     _description = "Sales Report" | |||
| 
 | |||
|     sale_report = fields.Char(string="Sale Report", help="Sale Report") | |||
|     date_from = fields.Datetime(string="Date From", | |||
|                                 help="Date from which the report should be " | |||
|                                      "viewed.") | |||
|     date_to = fields.Datetime(string="Date to", | |||
|                               help="Date to which the report should be viewed.") | |||
|     report_type = fields.Selection([ | |||
|         ('report_by_order', 'Report By Order'), | |||
|         ('report_by_order_detail', 'Report By Order Detail'), | |||
|         ('report_by_product', 'Report By Product'), | |||
|         ('report_by_categories', 'Report By Categories'), | |||
|         ('report_by_salesperson', 'Report By Sales Person'), | |||
|         ('report_by_state', 'Report By State')], default='report_by_order', | |||
|         help="Report type", string="Report type") | |||
| 
 | |||
|     @api.model | |||
|     def sale_report(self, option): | |||
|         """This is to pass values to the sales report.""" | |||
|         report_values = self.env['sales.report'].browse(option[0]) | |||
|         data = { | |||
|             'report_type': report_values.report_type, | |||
|             'model': self, | |||
|         } | |||
|         if report_values.date_from: | |||
|             data.update({ | |||
|                 'date_from': report_values.date_from, | |||
|             }) | |||
|         if report_values.date_to: | |||
|             data.update({ | |||
|                 'date_to': report_values.date_to, | |||
|             }) | |||
|         filters = self.get_filter(option) | |||
|         lines = self._get_report_values(data).get('SALE') | |||
|         main_line = self._get_report_values(data).get('sale_main') | |||
|         return { | |||
|             'name': "Sale Orders", | |||
|             'type': 'ir.actions.client', | |||
|             'tag': 's_r', | |||
|             'orders': data, | |||
|             'filters': filters, | |||
|             'report_lines': lines, | |||
|             'report_main_line': main_line, | |||
|         } | |||
| 
 | |||
|     def get_filter(self, option): | |||
|         """It is to get value for the chosen filter.""" | |||
|         data = self.get_filter_data(option) | |||
|         filters = {} | |||
|         if data.get('report_type') == 'report_by_order': | |||
|             filters['report_type'] = 'Report By Order' | |||
|         elif data.get('report_type') == 'report_by_order_detail': | |||
|             filters['report_type'] = 'Report By Order Detail' | |||
|         elif data.get('report_type') == 'report_by_product': | |||
|             filters['report_type'] = 'Report By Product' | |||
|         elif data.get('report_type') == 'report_by_categories': | |||
|             filters['report_type'] = 'Report By Categories' | |||
|         elif data.get('report_type') == 'report_by_salesperson': | |||
|             filters['report_type'] = 'Report By Sales Person' | |||
|         elif data.get('report_type') == 'report_by_state': | |||
|             filters['report_type'] = 'Report By State' | |||
|         else: | |||
|             filters['report_type'] = 'report_by_order' | |||
|         return filters | |||
| 
 | |||
|     def get_filter_data(self, option): | |||
|         """It is to get data according to the filter selected.""" | |||
|         filter_dict = { | |||
|             'report_type': self.env['sales.report'].browse( | |||
|                 option[0]).report_type, | |||
|         } | |||
|         return filter_dict | |||
| 
 | |||
|     @api.model | |||
|     def create(self, vals): | |||
|         """It super create.""" | |||
|         res = super(SalesReport, self).create(vals) | |||
|         return res | |||
| 
 | |||
|     def write(self, vals): | |||
|         """It super write.""" | |||
|         res = super(SalesReport, self).write(vals) | |||
|         return res | |||
| 
 | |||
|     def _get_report_sub_lines(self, data): | |||
|         """This is to get the table lines according to the filter.""" | |||
|         report_sub_lines = [] | |||
|         if data.get('report_type') == 'report_by_order': | |||
|             query = ''' | |||
|                         select so.id,so.name as number,so.date_order, | |||
|                         so.partner_id,so.amount_total, | |||
|                         so.user_id,res_partner.name as customer, | |||
|                         res_users.partner_id as user_partner,so.id as id, | |||
|                         sum(sale_order_line.product_uom_qty), | |||
|                         (SELECT res_partner.name as sales_man  | |||
|                         FROM res_partner | |||
|                         WHERE res_partner.id = res_users.partner_id) | |||
|                         from sale_order as so | |||
|                         inner join res_partner  | |||
|                         on so.partner_id = res_partner.id | |||
|                         inner join res_users  | |||
|                         on so.user_id = res_users.id | |||
|                         inner join sale_order_line  | |||
|                         on so.id = sale_order_line.order_id                         | |||
|                                  ''' | |||
|             term = 'Where ' | |||
|             if data.get('date_from'): | |||
|                 query += "Where so.date_order >= '%s' " % data.get('date_from') | |||
|                 term = 'AND ' | |||
|             if data.get('date_to'): | |||
|                 query += term + "so.date_order <= '%s' " % data.get('date_to') | |||
|             query += "group by so.user_id,res_users.partner_id," \ | |||
|                      "res_partner.name,so.partner_id,so.date_order," \ | |||
|                      "so.name,so.amount_total,so.id" | |||
|             self._cr.execute(query) | |||
|             report_by_order = self._cr.dictfetchall() | |||
|             report_sub_lines.append(report_by_order) | |||
|         elif data.get('report_type') == 'report_by_order_detail': | |||
|             query = ''' | |||
|                        SELECT  so.id,so.name as number,so.date_order, | |||
|                             res_partner.name as customer, | |||
|                             rc.name as company, | |||
|                             product_template.name as product, | |||
|                             product_product.default_code, | |||
|                             so_line.product_uom_qty, | |||
|                             so_line.price_subtotal,so.amount_total, | |||
|                             so.partner_id, | |||
|                             so.user_id,ru.id,so_line.product_id, | |||
|                             sum(so_line.product_uom_qty), | |||
|                             (SELECT res_partner.name as salesman  | |||
|                             FROM res_partner | |||
|                             WHERE res_partner.id = res_users.partner_id)  | |||
|                             from sale_order as so | |||
|                             inner join sale_order_line as so_line  | |||
|                             on so.id = so_line.order_id | |||
|                             inner join product_product  | |||
|                             ON so_line.product_id=product_product.id | |||
|                             inner join product_template  | |||
|                             ON product_product.product_tmpl_id = | |||
|                              product_template.id | |||
|                             inner join res_partner  | |||
|                             on so.partner_id=res_partner.id  | |||
|                             inner join res_users on so.user_id = res_users.id | |||
|                             inner join res_company as rc on so.company_id=rc.id | |||
|                             inner join res_users as ru on so.user_id=ru.id | |||
|                         ''' | |||
|             term = 'Where ' | |||
|             if data.get('date_from'): | |||
|                 query += "Where so.date_order >= '%s' " % data.get('date_from') | |||
|                 term = 'AND ' | |||
|             if data.get('date_to'): | |||
|                 query += term + "so.date_order <= '%s' " % data.get('date_to') | |||
|             query += ''' group by so.user_id, so.name, so.id,so.date_order, | |||
|                          res_partner.name,rc.name,product_template.name, | |||
|                          product_product.default_code,so_line.product_uom_qty, | |||
|                          so_line.price_subtotal,so.amount_total,so.partner_id, | |||
|                          so.user_id,ru.id,so_line.product_id, | |||
|                          res_users.partner_id | |||
|                      ''' | |||
|             self._cr.execute(query) | |||
|             report_by_order_details = self._cr.dictfetchall() | |||
|             report_sub_lines.append(report_by_order_details) | |||
|         elif data.get('report_type') == 'report_by_product': | |||
|             query = ''' | |||
|                         SELECT  so.id,so.date_order, | |||
|                             product_template.name as product, | |||
|                             product_category.name as category, | |||
|                             product_product.default_code, | |||
|                             so_line.product_uom_qty, | |||
|                             so.amount_total,so.name as number                               | |||
|                             From sale_order as so | |||
|                             inner join sale_order_line  | |||
|                             as so_line on so.id = so_line.order_id | |||
|                             inner join product_product  | |||
|                             ON so_line.product_id=product_product.id | |||
|                             inner join product_template  | |||
|                             ON product_product.product_tmpl_id =  | |||
|                             product_template.id | |||
|                             inner join product_category  | |||
|                             on product_category.id = product_template.categ_id | |||
|                     ''' | |||
|             term = 'Where ' | |||
|             if data.get('date_from'): | |||
|                 query += "Where so.date_order >= '%s' " % data.get('date_from') | |||
|                 term = 'AND ' | |||
|             if data.get('date_to'): | |||
|                 query += term + "so.date_order <= '%s' " % data.get('date_to') | |||
|             query += "group by so.id,so.date_order,product_template.name," \ | |||
|                      "product_category.name,product_product.default_code," \ | |||
|                      "so_line.product_uom_qty" | |||
|             self._cr.execute(query) | |||
|             report_by_product = self._cr.dictfetchall() | |||
|             report_sub_lines.append(report_by_product) | |||
|         elif data.get('report_type') == 'report_by_categories': | |||
|             query = ''' | |||
|                         select product_category.name, | |||
|                             sum(so_line.product_uom_qty) as qty, | |||
|                             sum(so_line.price_subtotal) as amount_total | |||
|                             from sale_order_line as so_line | |||
|                             inner join product_template  | |||
|                             on so_line.product_id = product_template.id | |||
|                             inner join product_category  | |||
|                             on product_category.id = product_template.categ_id | |||
|                             inner join sale_order  | |||
|                             on so_line.order_id = sale_order.id | |||
|                     ''' | |||
|             term = 'Where ' | |||
|             if data.get('date_from'): | |||
|                 query += "Where sale_order.date_order >= '%s' " % data.get( | |||
|                     'date_from') | |||
|                 term = 'AND ' | |||
|             if data.get('date_to'): | |||
|                 query += term + "sale_order.date_order <= '%s' " % data.get( | |||
|                     'date_to') | |||
|             query += "group by product_category.name" | |||
|             self._cr.execute(query) | |||
|             report_by_categories = self._cr.dictfetchall() | |||
|             report_sub_lines.append(report_by_categories) | |||
|         elif data.get('report_type') == 'report_by_salesperson': | |||
|             query = ''' | |||
|                         select res_partner.name, | |||
|                             sum(sale_order_line.product_uom_qty) as qty, | |||
|                             sum(sale_order_line.price_subtotal) as amount, | |||
|                             count(so.id) as order | |||
|                             from sale_order as so | |||
|                             inner join res_users  | |||
|                             on so.user_id = res_users.id | |||
|                             inner join res_partner  | |||
|                             on res_users.partner_id = res_partner.id | |||
|                             inner join sale_order_line  | |||
|                             on so.id = sale_order_line.order_id | |||
|                     ''' | |||
|             term = 'Where ' | |||
|             if data.get('date_from'): | |||
|                 query += "Where so.date_order >= '%s' " % data.get('date_from') | |||
|                 term = 'AND ' | |||
|             if data.get('date_to'): | |||
|                 query += term + "so.date_order <= '%s' " % data.get('date_to') | |||
|             query += "group by res_partner.name" | |||
|             self._cr.execute(query) | |||
|             report_by_salesperson = self._cr.dictfetchall() | |||
|             report_sub_lines.append(report_by_salesperson) | |||
|         elif data.get('report_type') == 'report_by_state': | |||
|             query = ''' | |||
|                         select so.state,count(so.id), | |||
|                             sum(sale_order_line.product_uom_qty) as qty, | |||
|                             sum(sale_order_line.price_subtotal)  | |||
|                             as amount from sale_order as so  | |||
|                             inner join sale_order_line  | |||
|                             on so.id = sale_order_line.order_id | |||
|                     ''' | |||
|             term = 'Where ' | |||
|             if data.get('date_from'): | |||
|                 query += "Where so.date_order >= '%s' " % data.get('date_from') | |||
|                 term = 'AND ' | |||
|             if data.get('date_to'): | |||
|                 query += term + "so.date_order <= '%s' " % data.get('date_to') | |||
|             query += "group by so.state" | |||
|             self._cr.execute(query) | |||
|             report_by_state = self._cr.dictfetchall() | |||
|             report_sub_lines.append(report_by_state) | |||
|         return report_sub_lines | |||
| 
 | |||
|     def _get_report_total_value(self, data, report): | |||
|         """It is to pass total for each report type.""" | |||
|         report_main_lines = [] | |||
|         if data.get('report_type') == 'report_by_order': | |||
|             self._cr.execute(''' | |||
|                 select count(so.id) as order,sum(so.amount_total) as amount | |||
|                 from sale_order as so | |||
|                 ''') | |||
|             report_by_order = self._cr.dictfetchall() | |||
|             report_main_lines.append(report_by_order) | |||
|         elif data.get('report_type') == 'report_by_order_detail': | |||
|             self._cr.execute(''' | |||
|                             select count(so_line.id) as order, | |||
|                             sum(so_line.price_subtotal) as total | |||
|                             from sale_order_line as so_line | |||
|                             ''') | |||
|             report_by_order_detail = self._cr.dictfetchall() | |||
|             report_main_lines.append(report_by_order_detail) | |||
|         elif data.get('report_type') == 'report_by_product': | |||
|             self._cr.execute(''' | |||
|                 select count(so_line.product_id) as order, | |||
|                     sum(so_line.price_subtotal) as amount | |||
|                     from sale_order_line as so_line | |||
|                 ''') | |||
|             report_by_product = self._cr.dictfetchall() | |||
|             report_main_lines.append(report_by_product) | |||
|         else: | |||
|             report_main_lines = False | |||
|         return report_main_lines | |||
| 
 | |||
|     def _get_report_values(self, data): | |||
|         """It is to pass sublines for report.""" | |||
|         docs = data['model'] | |||
|         if data['report_type'] == 'report_by_order_detail': | |||
|             report = ['Report By Order Detail'] | |||
|         elif data['report_type'] == 'report_by_product': | |||
|             report = ['Report By Product'] | |||
|         elif data['report_type'] == 'report_by_categories': | |||
|             report = ['Report By Categories'] | |||
|         elif data['report_type'] == 'report_by_salesperson': | |||
|             report = ['Report By Sales Person'] | |||
|         elif data['report_type'] == 'report_by_state': | |||
|             report = ['Report By State'] | |||
|         else: | |||
|             report = ['Report By Order'] | |||
|         report_res_total = self._get_report_total_value(data, report) | |||
|         if data.get('report_type'): | |||
|             report_res = self._get_report_sub_lines(data)[0] | |||
|         else: | |||
|             report_res = self._get_report_sub_lines(data) | |||
|         if data.get('report_type') == 'report_by_order': | |||
|             report_res_total = self._get_report_total_value(data, report)[0] | |||
|         return { | |||
|             'doc_ids': self.ids, | |||
|             'docs': docs, | |||
|             'SALE': report_res, | |||
|             'sale_main': report_res_total, | |||
|         } | |||
| 
 | |||
|     def get_xlsx_report(self, data, response): | |||
|         """This function is to pass values to the xlsx report.""" | |||
|         report_data_main = data['report_lines'] | |||
|         output = io.BytesIO() | |||
|         filters = data['filters'] | |||
|         workbook = xlsxwriter.Workbook(output, {'in_memory': True}) | |||
|         sheet = workbook.add_worksheet() | |||
|         head = workbook.add_format({'align': 'center', 'bold': True, | |||
|                                     'font_size': '20px'}) | |||
|         heading = workbook.add_format( | |||
|             {'align': 'center', 'bold': True, 'font_size': '10px', | |||
|              'border': 2, | |||
|              'border_color': 'black'}) | |||
|         txt_l = workbook.add_format( | |||
|             {'font_size': '10px', 'border': 1, 'bold': True}) | |||
|         sheet.merge_range('A2:H3', | |||
|                           'Sales Report', | |||
|                           head) | |||
|         if filters.get('report_type') == 'Report By Order': | |||
|             sheet.merge_range('B5:D5', 'Report Type: ' + | |||
|                               filters.get('report_type'), txt_l) | |||
|             sheet.write('A7', 'Sale', heading) | |||
|             sheet.write('B7', 'Date Order', heading) | |||
|             sheet.write('C7', 'Customer', heading) | |||
|             sheet.write('D7', 'Sales Person', heading) | |||
|             sheet.write('E7', 'Total Qty', heading) | |||
|             sheet.write('F7', 'Amount Total', heading) | |||
|             lst = [] | |||
|             for rec in report_data_main[0]: | |||
|                 lst.append(rec) | |||
|             row = 6 | |||
|             col = 0 | |||
|             sheet.set_column(3, 0, 15) | |||
|             sheet.set_column(4, 1, 15) | |||
|             sheet.set_column(5, 2, 15) | |||
|             sheet.set_column(6, 3, 15) | |||
|             sheet.set_column(7, 4, 15) | |||
|             sheet.set_column(8, 5, 15) | |||
|             for rec_data in report_data_main: | |||
|                 row += 1 | |||
|                 sheet.write(row, col, rec_data['number'], txt_l) | |||
|                 sheet.write(row, col + 1, rec_data['date_order'], txt_l) | |||
|                 sheet.write(row, col + 2, rec_data['customer'], txt_l) | |||
|                 sheet.write(row, col + 3, rec_data['sales_man'], txt_l) | |||
|                 sheet.write(row, col + 4, rec_data['sum'], txt_l) | |||
|                 sheet.write(row, col + 5, rec_data['amount_total'], txt_l) | |||
|         if filters.get('report_type') == 'Report By Order Detail': | |||
|             sheet.merge_range('B5:D5', 'Report Type: ' + | |||
|                               filters.get('report_type'), txt_l) | |||
|             sheet.write('A7', 'Sale', heading) | |||
|             sheet.write('B7', 'Date Order', heading) | |||
|             sheet.write('C7', 'Customer', heading) | |||
|             sheet.write('D7', 'Company', heading) | |||
|             sheet.write('E7', 'Sales Person', heading) | |||
|             sheet.write('F7', 'Product Name', heading) | |||
|             sheet.write('G7', 'Product Code', heading) | |||
|             sheet.write('H7', 'Quantity', heading) | |||
|             sheet.write('I7', 'Price Subtotal', heading) | |||
|             sheet.write('J7', 'Amount Total', heading) | |||
|             lst = [] | |||
|             for rec in report_data_main[0]: | |||
|                 lst.append(rec) | |||
|             row = 6 | |||
|             col = 0 | |||
|             sheet.set_column(3, 0, 15) | |||
|             sheet.set_column(4, 1, 15) | |||
|             sheet.set_column(5, 2, 15) | |||
|             sheet.set_column(6, 3, 15) | |||
|             sheet.set_column(7, 4, 15) | |||
|             sheet.set_column(8, 5, 15) | |||
|             sheet.set_column(9, 6, 15) | |||
|             sheet.set_column(10, 7, 15) | |||
|             sheet.set_column(11, 8, 15) | |||
|             sheet.set_column(12, 9, 15) | |||
|             for rec_data in report_data_main: | |||
|                 row += 1 | |||
|                 product = [val for val in rec_data['product'].values()] | |||
|                 sheet.write(row, col, rec_data['number'], txt_l) | |||
|                 sheet.write(row, col + 1, rec_data['date_order'], txt_l) | |||
|                 sheet.write(row, col + 2, rec_data['customer'], txt_l) | |||
|                 sheet.write(row, col + 3, rec_data['company'], txt_l) | |||
|                 sheet.write(row, col + 4, rec_data['salesman'], txt_l) | |||
|                 sheet.write(row, col + 5, product[0], txt_l) | |||
|                 sheet.write(row, col + 6, rec_data['default_code'], txt_l) | |||
|                 sheet.write(row, col + 7, rec_data['product_uom_qty'], txt_l) | |||
|                 sheet.write(row, col + 8, rec_data['price_subtotal'], txt_l) | |||
|                 sheet.write(row, col + 9, rec_data['amount_total'], txt_l) | |||
|         if filters.get('report_type') == 'Report By Product': | |||
|             sheet.merge_range('B5:D5', 'Report Type: ' + | |||
|                               filters.get('report_type'), txt_l) | |||
|             sheet.write('A7', 'Product', heading) | |||
|             sheet.write('B7', 'Category', heading) | |||
|             sheet.write('C7', 'Product Code', heading) | |||
|             sheet.write('D7', 'Quantity', heading) | |||
|             sheet.write('E7', 'Amount Total', heading) | |||
|             lst = [] | |||
|             for rec in report_data_main[0]: | |||
|                 lst.append(rec) | |||
|             row = 6 | |||
|             col = 0 | |||
|             sheet.set_column(3, 0, 15) | |||
|             sheet.set_column(4, 1, 15) | |||
|             sheet.set_column(5, 2, 15) | |||
|             sheet.set_column(6, 3, 15) | |||
|             sheet.set_column(7, 4, 15) | |||
|             for rec_data in report_data_main: | |||
|                 row += 1 | |||
|                 product = [val for val in rec_data['product'].values()] | |||
|                 sheet.write(row, col, product[0], txt_l) | |||
|                 sheet.write(row, col + 1, rec_data['category'], txt_l) | |||
|                 sheet.write(row, col + 2, rec_data['default_code'], txt_l) | |||
|                 sheet.write(row, col + 3, rec_data['product_uom_qty'], txt_l) | |||
|                 sheet.write(row, col + 4, rec_data['amount_total'], txt_l) | |||
|         if filters.get('report_type') == 'Report By Categories': | |||
|             sheet.merge_range('B5:D5', 'Report Type: ' + | |||
|                               filters.get('report_type'), txt_l) | |||
|             sheet.write('B7', 'Category', heading) | |||
|             sheet.write('C7', 'Qty', heading) | |||
|             sheet.write('D7', 'Amount Total', heading) | |||
|             lst = [] | |||
|             for rec in report_data_main[0]: | |||
|                 lst.append(rec) | |||
|             row = 6 | |||
|             col = 1 | |||
|             sheet.set_column(3, 1, 15) | |||
|             sheet.set_column(4, 2, 15) | |||
|             sheet.set_column(5, 3, 15) | |||
|             for rec_data in report_data_main: | |||
|                 row += 1 | |||
|                 sheet.write(row, col, rec_data['name'], txt_l) | |||
|                 sheet.write(row, col + 1, rec_data['qty'], txt_l) | |||
|                 sheet.write(row, col + 2, rec_data['amount_total'], txt_l) | |||
|         if filters.get('report_type') == 'Report By Sales Person': | |||
|             sheet.merge_range('B5:D5', 'Report Type: ' + | |||
|                               filters.get('report_type'), txt_l) | |||
|             sheet.write('A7', 'Sales Person', heading) | |||
|             sheet.write('B7', 'Total Order', heading) | |||
|             sheet.write('C7', 'Total Qty', heading) | |||
|             sheet.write('D7', 'Total Amount', heading) | |||
|             lst = [] | |||
|             for rec in report_data_main[0]: | |||
|                 lst.append(rec) | |||
|             row = 6 | |||
|             col = 0 | |||
|             sheet.set_column(3, 0, 15) | |||
|             sheet.set_column(4, 1, 15) | |||
|             sheet.set_column(5, 2, 15) | |||
|             sheet.set_column(6, 3, 15) | |||
|             for rec_data in report_data_main: | |||
|                 row += 1 | |||
|                 sheet.write(row, col, rec_data['name'], txt_l) | |||
|                 sheet.write(row, col + 1, rec_data['order'], txt_l) | |||
|                 sheet.write(row, col + 2, rec_data['qty'], txt_l) | |||
|                 sheet.write(row, col + 3, rec_data['amount'], txt_l) | |||
|         if filters.get('report_type') == 'Report By State': | |||
|             sheet.merge_range('B5:D5', 'Report Type: ' + | |||
|                               filters.get('report_type'), txt_l) | |||
|             sheet.write('A7', 'State', heading) | |||
|             sheet.write('B7', 'Total Count', heading) | |||
|             sheet.write('C7', 'Quantity', heading) | |||
|             sheet.write('D7', 'Amount', heading) | |||
|             lst = [] | |||
|             for rec in report_data_main[0]: | |||
|                 lst.append(rec) | |||
|             row = 6 | |||
|             col = 0 | |||
|             sheet.set_column(3, 0, 15) | |||
|             sheet.set_column(4, 1, 15) | |||
|             sheet.set_column(5, 2, 15) | |||
|             sheet.set_column(6, 3, 15) | |||
|             for rec_data in report_data_main: | |||
|                 row += 1 | |||
|                 if rec_data['state'] == 'draft': | |||
|                     sheet.write(row, col, 'Quotation', txt_l) | |||
|                 elif rec_data['state'] == 'sent': | |||
|                     sheet.write(row, col, 'Quotation Sent', txt_l) | |||
|                 elif rec_data['state'] == 'sale': | |||
|                     sheet.write(row, col, 'Sale Order', txt_l) | |||
|                 sheet.write(row, col + 1, rec_data['count'], txt_l) | |||
|                 sheet.write(row, col + 2, rec_data['qty'], txt_l) | |||
|                 sheet.write(row, col + 3, rec_data['amount'], txt_l) | |||
|         workbook.close() | |||
|         output.seek(0) | |||
|         response.stream.write(output.read()) | |||
|         output.close() | |||
| @ -0,0 +1,22 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################### | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | |||
| #    Author: Swetha Anand (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 sale_order_report | |||
| @ -0,0 +1,97 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <!--    Template for Invoice Analysis Report --> | |||
|     <template id="invoice_analysis_view"> | |||
|         <t t-call="web.html_container"> | |||
|             <t t-call="web.external_layout"> | |||
|                 <t class="page"> | |||
|                     <div class="oe_structure"/> | |||
|                     <center> | |||
|                         <b> | |||
|                             <h3>Invoice Analysis Report</h3> | |||
|                         </b> | |||
|                     </center> | |||
|                     <t t-if="start_date and end_date"> | |||
|                         <center> | |||
|                             <span t-esc="start_date"/> | |||
|                             To | |||
|                             <span t-esc="end_date"/> | |||
|                         </center> | |||
|                     </t> | |||
|                     <t t-foreach="partner_id" t-as="partner"> | |||
|                         <center> | |||
|                             <b> | |||
|                                 <span t-esc="partner['name']"/> | |||
|                             </b> | |||
|                         </center> | |||
|                         <br/> | |||
|                         <t t-set="t_invoiced" t-value="0"/> | |||
|                         <t t-set="t_paid" t-value="0"/> | |||
|                         <t t-set="t_due" t-value="0"/> | |||
|                         <table class="table table-condensed"> | |||
|                             <thead> | |||
|                                 <tr> | |||
|                                     <th>Order Number</th> | |||
|                                     <th>Order Date</th> | |||
|                                     <th>Invoice Number</th> | |||
|                                     <th>Invoice Date</th> | |||
|                                     <th>Amount Invoiced</th> | |||
|                                     <th>Amount Paid</th> | |||
|                                     <th>Amount Due</th> | |||
|                                 </tr> | |||
|                             </thead> | |||
|                             <tbody> | |||
|                                 <tr t-foreach="form" t-as="order"> | |||
|                                     <t t-if="order['partner_id'] == partner['id']"> | |||
|                                         <td> | |||
|                                             <span t-esc="order['so']"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span t-esc="order['order_date']" | |||
|                                                   t-options='{"widget": "date"}'/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span t-esc="order['invoice']"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span t-esc="order['date']"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span t-esc="order['invoiced']"/> | |||
|                                             <t t-set="t_invoiced" | |||
|                                                t-value="t_invoiced + order['invoiced']"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span t-esc="order['paid']"/> | |||
|                                             <t t-set="t_paid" | |||
|                                                t-value="t_paid + order['paid']"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span t-esc="order['due']"/> | |||
|                                             <t t-set="t_due" | |||
|                                                t-value="t_due + order['due']"/> | |||
|                                         </td> | |||
|                                     </t> | |||
|                                 </tr> | |||
|                                 <tr> | |||
|                                     <td> | |||
|                                         <span>Total invoiced</span> | |||
|                                         <t t-esc="t_invoiced"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span>Total paid:</span> | |||
|                                         <t t-esc="t_paid"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span>Total due:</span> | |||
|                                         <t t-esc="t_due"/> | |||
|                                     </td> | |||
|                                 </tr> | |||
|                             </tbody> | |||
|                         </table> | |||
|                     </t> | |||
|                 </t> | |||
|             </t> | |||
|         </t> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,26 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <!--    To inherit sale.report_saleorder_document --> | |||
|     <template id="report_saleorder_inherit" | |||
|               inherit_id="sale.report_saleorder_document"> | |||
|         <xpath expr="//table[hasclass('o_main_table')]//tr/th[@name='th_quantity']" position="after"> | |||
|             <t t-if="request.env['ir.config_parameter'].sudo().get_param( | |||
|             'sale_product_image.show_product_image_in_sale_report')"> | |||
|                 <th> | |||
|                     <strong>Image</strong> | |||
|                 </th> | |||
|             </t> | |||
|         </xpath> | |||
|         <xpath expr="//t[@t-foreach='lines_to_report']//td[@name='td_quantity']" | |||
|                position="after"> | |||
|             <t t-if="request.env['ir.config_parameter'].sudo().get_param( | |||
|             'sale_product_image.show_product_image_in_sale_report')"> | |||
|                 <td style="height:20px !important;width:20px !important;"> | |||
|                     <span t-field="line.order_line_image" | |||
|                           t-options='{"widget": "image"}' | |||
|                     /> | |||
|                 </td> | |||
|             </t> | |||
|         </xpath> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,42 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2022-TODAY Cybrosys Technologies(<https://www.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, models | |||
| 
 | |||
| 
 | |||
| class SaleOrderReport(models.AbstractModel): | |||
|     """It is to add new abstract model for sale_order_report.""" | |||
|     _name = 'report.all_in_one_sales_kit.sale_order_report' | |||
|     _description = "Sale Order Report" | |||
| 
 | |||
|     @api.model | |||
|     def _get_report_values(self, docids, data=None): | |||
|         """It is to pass report values.""" | |||
|         if self.env.context.get('sale_order_report'): | |||
|             if data.get('report_data'): | |||
|                 report_lines = data.get('report_data')['report_lines'] | |||
|                 total_amount = sum( | |||
|                     line.get('amount_total', 0) for line in report_lines) | |||
|                 data.update({'report_main_line_data': report_lines, | |||
|                              'Filters': data.get('report_data')['filters'], | |||
|                              'company': self.env.company, | |||
|                              'total_amount': total_amount, | |||
|                              }) | |||
|             return data | |||
| @ -0,0 +1,397 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <!--    To Show dynamic sale order report.  --> | |||
|     <template id="sale_order_report"> | |||
|         <t t-call="web.html_container"> | |||
|             <t t-call="web.internal_layout"> | |||
|                 <t t-if="Filters.get('report_type')=='Report By Order'"> | |||
|                     <t t-call="all_in_one_sales_kit.report_order"/> | |||
|                 </t> | |||
|                 <t t-if="Filters.get('report_type')=='Report By Order Detail'"> | |||
|                     <t t-call="all_in_one_sales_kit.report_order_detail"/> | |||
|                 </t> | |||
|                 <t t-if="Filters.get('report_type')=='Report By Product'"> | |||
|                     <t t-call="all_in_one_sales_kit.report_product"/> | |||
|                 </t> | |||
|                 <t t-if="Filters.get('report_type')=='Report By Categories'"> | |||
|                     <t t-call="all_in_one_sales_kit.report_category"/> | |||
|                 </t> | |||
|                 <t t-if="Filters.get('report_type')=='Report By Sales Person'"> | |||
|                     <t t-call="all_in_one_sales_kit.report_salesman"/> | |||
|                 </t> | |||
|                 <t t-if="Filters.get('report_type')=='Report By State'"> | |||
|                     <t t-call="all_in_one_sales_kit.report_state"/> | |||
|                 </t> | |||
|             </t> | |||
|         </t> | |||
|     </template> | |||
|     <template id="report_order"> | |||
|         <div class="page"> | |||
|             <div class="oe_structure"/> | |||
|             <span t-if="Filters.get('date_from')"> | |||
|                 <strong>From:</strong> | |||
|                 <t t-esc="Filters['date_from']"/> | |||
|             </span> | |||
|             <span t-if="Filters.get('date_to')"> | |||
|                 <strong>To:</strong> | |||
|                 <t t-esc="Filters['date_to']"/> | |||
|             </span> | |||
|             <div> | |||
|                 <div style="width:100%;"> | |||
|                     <div style="text-align:centre;" class="row"> | |||
|                         <div class="col-2"> | |||
|                             <strong>Report Type:</strong> | |||
|                             <t t-esc="Filters.get('report_type')"/> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <br/> | |||
|                 <table class="table table-sm table-reports"> | |||
|                     <thead> | |||
|                         <tr> | |||
|                             <th class="text-left" colspan="6">Sale</th> | |||
|                             <th colspan="6" class="text-center">Date Order</th> | |||
|                             <th colspan="6" class="text-right">Customer</th> | |||
|                             <th colspan="6" class="text-right">Sales Person | |||
|                             </th> | |||
|                             <th colspan="6" class="text-center">Total Qty</th> | |||
|                             <th colspan="6" class="text-left">Amount Total</th> | |||
|                         </tr> | |||
|                     </thead> | |||
|                     <tbody class="text-left"> | |||
|                         <t t-foreach="report_main_line_data" t-as="main"> | |||
|                             <tr style="font-weight: bold;"> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['number']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['date_order']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['customer']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['sales_man']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['sum']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['amount_total']"/> | |||
|                                 </td> | |||
|                             </tr> | |||
|                         </t> | |||
|                         <tr style="font-weight: bold;"> | |||
|                             <td colspan="6"/> | |||
|                             <td colspan="6"/> | |||
|                             <td colspan="6"/> | |||
|                             <td colspan="6"/> | |||
|                              <td colspan="6">Grand Total</td> | |||
|                              <td colspan="6"><span t-esc="total_amount"/></td> | |||
|                         </tr> | |||
|                     </tbody> | |||
|                 </table> | |||
|             </div> | |||
|             <br/> | |||
|         </div> | |||
|     </template> | |||
|     <template id="report_order_detail"> | |||
|         <div class="page"> | |||
|             <div class="oe_structure"/> | |||
|             <span t-if="Filters.get('date_from')"> | |||
|                 <strong>From:</strong> | |||
|                 <t t-esc="Filters['date_from']"/> | |||
|             </span> | |||
|             <span t-if="Filters.get('date_to')"> | |||
|                 <strong>To:</strong> | |||
|                 <t t-esc="Filters['date_to']"/> | |||
|             </span> | |||
|             <div> | |||
|                 <div style="width:100%;"> | |||
|                     <div style="text-align:centre;" class="row"> | |||
|                         <div class="col-2"> | |||
|                             <strong>Report Type:</strong> | |||
|                             <t t-esc="Filters.get('report_type')"/> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <br/> | |||
|                 <table class="table table-sm table-reports"> | |||
|                     <thead> | |||
|                         <tr class="text-right"> | |||
|                             <th colspan="6">Sale</th> | |||
|                             <th colspan="6">Date Order</th> | |||
|                             <th colspan="6">Customer</th> | |||
|                             <th colspan="6">Company</th> | |||
|                             <th colspan="6">Sales Person</th> | |||
|                             <th colspan="6">Product Name</th> | |||
|                             <th colspan="6">Product Code</th> | |||
|                             <th colspan="6">Quantity</th> | |||
|                             <th colspan="6">Price Subtotal</th> | |||
|                             <th colspan="6">Amount Total</th> | |||
|                         </tr> | |||
|                     </thead> | |||
|                     <tbody> | |||
|                         <t t-foreach="report_main_line_data" t-as="main"> | |||
|                             <tr style="font-weight: bold;"> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['number']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['date_order']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['customer']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['company']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['salesman']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['product']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['default_code']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['product_uom_qty']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['price_subtotal']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['amount_total']"/> | |||
|                                 </td> | |||
|                             </tr> | |||
|                         </t> | |||
|                     </tbody> | |||
|                 </table> | |||
|             </div> | |||
|             <br/> | |||
|         </div> | |||
|     </template> | |||
|     <template id="report_product"> | |||
|         <div class="page"> | |||
|             <div class="oe_structure"/> | |||
|             <span t-if="Filters.get('date_from')"> | |||
|                 <strong>From:</strong> | |||
|                 <t t-esc="Filters['date_from']"/> | |||
|             </span> | |||
|             <span t-if="Filters.get('date_to')"> | |||
|                 <strong>To:</strong> | |||
|                 <t t-esc="Filters['date_to']"/> | |||
|             </span> | |||
|             <div> | |||
|                 <div style="width:100%;"> | |||
|                     <div style="text-align:centre;" class="row"> | |||
|                         <div class="col-2"> | |||
|                             <strong>Report Type:</strong> | |||
|                             <t t-esc="Filters.get('report_type')"/> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <br/> | |||
|                 <table class="table table-sm table-reports"> | |||
|                     <thead> | |||
|                         <tr> | |||
|                             <th class="text-left" colspan="6">Product</th> | |||
|                             <th colspan="6" class="text-center">Category</th> | |||
|                             <th colspan="6" class="text-center">Product Code | |||
|                             </th> | |||
|                             <th colspan="6" class="text-center">Quantity</th> | |||
|                             <th colspan="6">Amount Total</th> | |||
|                         </tr> | |||
|                     </thead> | |||
|                     <tbody> | |||
|                         <t t-foreach="report_main_line_data" t-as="main"> | |||
|                             <tr style="font-weight: bold;"> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['product']['en_US']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['category']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['default_code']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['product_uom_qty']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['amount_total']"/> | |||
|                                 </td> | |||
|                             </tr> | |||
|                         </t> | |||
|                     </tbody> | |||
|                 </table> | |||
|             </div> | |||
|             <br/> | |||
|         </div> | |||
|     </template> | |||
|     <template id="report_category"> | |||
|         <div class="page"> | |||
|             <div class="oe_structure"/> | |||
|             <span t-if="Filters.get('date_from')"> | |||
|                 <strong>From:</strong> | |||
|                 <t t-esc="Filters['date_from']"/> | |||
|             </span> | |||
|             <span t-if="Filters.get('date_to')"> | |||
|                 <strong>To:</strong> | |||
|                 <t t-esc="Filters['date_to']"/> | |||
|             </span> | |||
|             <div> | |||
|                 <div style="width:100%;"> | |||
|                     <div style="text-align:centre;" class="row"> | |||
|                         <div class="col-2"> | |||
|                             <strong>Report Type:</strong> | |||
|                             <t t-esc="Filters.get('report_type')"/> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <br/> | |||
|                 <table class="table table-sm table-reports"> | |||
|                     <thead> | |||
|                         <tr> | |||
|                             <th colspan="6">Category</th> | |||
|                             <th colspan="6">Qty</th> | |||
|                             <th colspan="6">Amount Total</th> | |||
|                         </tr> | |||
|                     </thead> | |||
|                     <tbody> | |||
|                         <t t-foreach="report_main_line_data" | |||
|                            t-as="sale_category"> | |||
|                             <tr style="font-weight: bold;"> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="sale_category['name']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="sale_category['qty']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="sale_category['amount_total']"/> | |||
|                                 </td> | |||
|                             </tr> | |||
|                         </t> | |||
|                     </tbody> | |||
|                 </table> | |||
|             </div> | |||
|             <br/> | |||
|         </div> | |||
|     </template> | |||
|     <template id="report_salesman"> | |||
|         <div class="page"> | |||
|             <div class="oe_structure"/> | |||
|             <span t-if="Filters.get('date_from')"> | |||
|                 <strong>From:</strong> | |||
|                 <t t-esc="Filters['date_from']"/> | |||
|             </span> | |||
|             <span t-if="Filters.get('date_to')"> | |||
|                 <strong>To:</strong> | |||
|                 <t t-esc="Filters['date_to']"/> | |||
|             </span> | |||
|             <div> | |||
|                 <div style="width:100%;"> | |||
|                     <div style="text-align:centre;" class="row"> | |||
|                         <div class="col-2"> | |||
|                             <strong>Report Type:</strong> | |||
|                             <t t-esc="Filters.get('report_type')"/> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <br/> | |||
|                 <table class="table table-sm table-reports"> | |||
|                     <thead> | |||
|                         <tr> | |||
|                             <th>Sales Person</th> | |||
|                             <th colspan="6">Total Order</th> | |||
|                             <th colspan="6">Total Qty</th> | |||
|                             <th colspan="6">Total Amount</th> | |||
|                         </tr> | |||
|                     </thead> | |||
|                     <tbody> | |||
|                         <t t-foreach="report_main_line_data" t-as="main"> | |||
|                             <tr style="font-weight: bold;"> | |||
|                                 <td> | |||
|                                     <span t-esc="main['name']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['order']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['qty']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6"> | |||
|                                     <span t-esc="main['amount']"/> | |||
|                                 </td> | |||
|                             </tr> | |||
|                         </t> | |||
|                     </tbody> | |||
|                 </table> | |||
|             </div> | |||
|             <br/> | |||
|         </div> | |||
|     </template> | |||
|     <template id="report_state"> | |||
|         <div class="page"> | |||
|             <div class="oe_structure"/> | |||
|             <span t-if="Filters.get('date_from')"> | |||
|                 <strong>From:</strong> | |||
|                 <t t-esc="Filters['date_from']"/> | |||
|             </span> | |||
|             <span t-if="Filters.get('date_to')"> | |||
|                 <strong>To:</strong> | |||
|                 <t t-esc="Filters['date_to']"/> | |||
|             </span> | |||
|             <div> | |||
|                 <div style="width:100%;"> | |||
|                     <div style="text-align:centre;" class="row"> | |||
|                         <div class="col-2"> | |||
|                             <strong>Report Type:</strong> | |||
|                             <t t-esc="Filters.get('report_type')"/> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <br/> | |||
|                 <table class="table table-sm table-reports"> | |||
|                     <thead> | |||
|                         <tr class="text-left"> | |||
|                             <th colspan="6">State</th> | |||
|                             <th colspan="6">Total Count</th> | |||
|                             <th colspan="6">Quantity</th> | |||
|                             <th colspan="6">Amount</th> | |||
|                         </tr> | |||
|                     </thead> | |||
|                     <tbody> | |||
|                         <t t-foreach="report_main_line_data" t-as="main"> | |||
|                             <tr style="font-weight: bold;"> | |||
|                                 <td colspan="6"> | |||
|                                     <t t-if="main['state'] == 'draft'"> | |||
|                                         <span>Quotation</span> | |||
|                                     </t> | |||
|                                     <t t-if="main['state'] == 'sent'"> | |||
|                                         <span>Quotation Sent</span> | |||
|                                     </t> | |||
|                                     <t t-if="main['state'] == 'sale'"> | |||
|                                         <span>Sale Order</span> | |||
|                                     </t> | |||
|                                 </td> | |||
|                                 <td colspan="6" class="text-left"> | |||
|                                     <span t-esc="main['count']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6" class="text-left"> | |||
|                                     <span t-esc="main['qty']"/> | |||
|                                 </td> | |||
|                                 <td colspan="6" class="text-left"> | |||
|                                     <span t-esc="main['amount']"/> | |||
|                                 </td> | |||
|                             </tr> | |||
|                         </t> | |||
|                     </tbody> | |||
|                 </table> | |||
|             </div> | |||
|             <br/> | |||
|         </div> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,353 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|      <!--    Template for Sales Profit Report --> | |||
|     <template id="sale_profit_report_view"> | |||
|         <t t-call="web.html_container"> | |||
|             <t t-call="web.external_layout"> | |||
|                 <t class="page"> | |||
|                     <div class="oe_structure"/> | |||
|                     <center> | |||
|                         <b> | |||
|                             <h3>Sales Profit Report</h3> | |||
|                         </b> | |||
|                     </center> | |||
|                     <t t-if="start_date and end_date"> | |||
|                         <center> | |||
|                             <span t-esc="start_date"/> | |||
|                             To | |||
|                             <span t-esc="end_date"/> | |||
|                         </center> | |||
|                     </t> | |||
|                     <t t-if="type=='customer'"> | |||
|                         <t t-foreach="partner_id" t-as="partner"> | |||
|                             <center> | |||
|                                 <b> | |||
|                                     <span t-esc="partner['name']"/> | |||
|                                 </b> | |||
|                             </center> | |||
|                             <t t-set="t_cost" t-value="0"/> | |||
|                             <t t-set="t_price" t-value="0"/> | |||
|                             <t t-set="t_profit" t-value="0"/> | |||
|                             <t t-set="t_margin" t-value="0"/> | |||
|                             <br/> | |||
|                             <table class="table table-condensed"> | |||
|                                 <thead> | |||
|                                     <tr> | |||
|                                         <th>Order</th> | |||
|                                         <th>Date</th> | |||
|                                         <th>Product</th> | |||
|                                         <th>Quantity</th> | |||
|                                         <th>Cost</th> | |||
|                                         <th>Sale Price</th> | |||
|                                         <th>Profit</th> | |||
|                                         <th>Margin(%)</th> | |||
|                                     </tr> | |||
|                                 </thead> | |||
|                                 <tbody> | |||
|                                     <tr t-foreach="form" t-as="order"> | |||
|                                         <t t-if="order['partner_id'] == partner['id']"> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['sequence']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['date']" | |||
|                                                       t-options='{"widget": "date"}'/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['product']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['quantity']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['cost']"/> | |||
|                                                 <t t-set="t_cost" | |||
|                                                    t-value="t_cost + order['cost']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['price']"/> | |||
|                                                 <t t-set="t_price" | |||
|                                                    t-value="t_price + order['price']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['profit']"/> | |||
|                                                 <t t-set="t_profit" | |||
|                                                    t-value="t_profit + order['profit']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['margin']"/> | |||
|                                                 <t t-set="t_margin" | |||
|                                                    t-value="t_margin + order['margin']"/> | |||
|                                             </td> | |||
|                                         </t> | |||
|                                     </tr> | |||
|                                     <tr> | |||
|                                         <td> | |||
|                                             <span>Total cost</span> | |||
|                                             <t t-esc="t_cost"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total Price:</span> | |||
|                                             <t t-esc="t_price"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total Profit:</span> | |||
|                                             <t t-esc="t_profit"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total margin:</span> | |||
|                                             <t t-esc="t_margin"/> | |||
|                                         </td> | |||
|                                     </tr> | |||
|                                 </tbody> | |||
|                             </table> | |||
|                         </t> | |||
|                     </t> | |||
|                     <t t-if="type=='product'"> | |||
|                         <t t-foreach="product_id" t-as="product"> | |||
|                             <center> | |||
|                                 <b> | |||
|                                     <span t-esc="product['name']"/> | |||
|                                 </b> | |||
|                             </center> | |||
|                             <t t-set="t_cost" t-value="0"/> | |||
|                             <t t-set="t_price" t-value="0"/> | |||
|                             <t t-set="t_profit" t-value="0"/> | |||
|                             <t t-set="t_margin" t-value="0"/> | |||
|                             <br/> | |||
|                             <table class="table table-condensed"> | |||
|                                 <thead> | |||
|                                     <tr> | |||
|                                         <th>Order</th> | |||
|                                         <th>Date</th> | |||
|                                         <th>Customer</th> | |||
|                                         <th>Quantity</th> | |||
|                                         <th>Cost</th> | |||
|                                         <th>Sale Price</th> | |||
|                                         <th>Profit</th> | |||
|                                         <th>Margin(%)</th> | |||
|                                     </tr> | |||
|                                 </thead> | |||
|                                 <tbody> | |||
|                                     <tr t-foreach="form" t-as="order"> | |||
|                                         <t t-if="order['product_id'] == product['id']"> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['sequence']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['date']" | |||
|                                                       t-options='{"widget": "date"}'/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['partner']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['quantity']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['cost']"/> | |||
|                                                 <t t-set="t_cost" | |||
|                                                    t-value="t_cost + order['cost']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['price']"/> | |||
|                                                 <t t-set="t_price" | |||
|                                                    t-value="t_price + order['price']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['profit']"/> | |||
|                                                 <t t-set="t_profit" | |||
|                                                    t-value="t_profit + order['profit']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['margin']"/> | |||
|                                                 <t t-set="t_margin" | |||
|                                                    t-value="t_margin + order['margin']"/> | |||
|                                             </td> | |||
|                                         </t> | |||
|                                     </tr> | |||
|                                     <tr> | |||
|                                         <td> | |||
|                                             <span>Total cost</span> | |||
|                                             <t t-esc="t_cost"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total Price:</span> | |||
|                                             <t t-esc="t_price"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total Profit:</span> | |||
|                                             <t t-esc="t_profit"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total margin:</span> | |||
|                                             <t t-esc="t_margin"/> | |||
|                                         </td> | |||
|                                     </tr> | |||
|                                 </tbody> | |||
|                             </table> | |||
|                         </t> | |||
|                     </t> | |||
|                     <t t-if="type=='both'"> | |||
|                         <table class="table table-condensed"> | |||
|                             <t t-set="t_cost" t-value="0"/> | |||
|                             <t t-set="t_price" t-value="0"/> | |||
|                             <t t-set="t_profit" t-value="0"/> | |||
|                             <t t-set="t_margin" t-value="0"/> | |||
|                             <thead> | |||
|                                 <tr> | |||
|                                     <th>Order</th> | |||
|                                     <th>Date</th> | |||
|                                     <th>Customer</th> | |||
|                                     <th>Product</th> | |||
|                                     <th>Quantity</th> | |||
|                                     <th>Cost</th> | |||
|                                     <th>Sale Price</th> | |||
|                                     <th>Profit</th> | |||
|                                     <th>Margin(%)</th> | |||
|                                 </tr> | |||
|                             </thead> | |||
|                             <tbody> | |||
|                                 <tr t-foreach="form" t-as="order"> | |||
|                                     <td> | |||
|                                         <span t-esc="order['sequence']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['date']" | |||
|                                               t-options='{"widget": "date"}'/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['partner']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['product']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['quantity']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['cost']"/> | |||
|                                         <t t-set="t_cost" | |||
|                                            t-value="t_cost + order['cost']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['price']"/> | |||
|                                         <t t-set="t_price" | |||
|                                            t-value="t_price + order['price']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['profit']"/> | |||
|                                         <t t-set="t_profit" | |||
|                                            t-value="t_profit + order['profit']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['margin']"/> | |||
|                                         <t t-set="t_margin" | |||
|                                            t-value="t_margin + order['margin']"/> | |||
|                                     </td> | |||
|                                 </tr> | |||
|                                 <tr> | |||
|                                     <td> | |||
|                                         <span>Total cost</span> | |||
|                                         <t t-esc="t_cost"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span>Total Price:</span> | |||
|                                         <t t-esc="t_price"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span>Total Profit:</span> | |||
|                                         <t t-esc="t_profit"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span>Total margin:</span> | |||
|                                         <t t-esc="t_margin"/> | |||
|                                     </td> | |||
|                                 </tr> | |||
|                             </tbody> | |||
|                         </table> | |||
|                     </t> | |||
|                     <t t-if="no_value == True"> | |||
|                         <table class="table table-condensed"> | |||
|                             <t t-set="t_cost" t-value="0"/> | |||
|                             <t t-set="t_price" t-value="0"/> | |||
|                             <t t-set="t_profit" t-value="0"/> | |||
|                             <t t-set="t_margin" t-value="0"/> | |||
|                             <thead> | |||
|                                 <tr> | |||
|                                     <th>Order</th> | |||
|                                     <th>Date</th> | |||
|                                     <th>Customer</th> | |||
|                                     <th>Product</th> | |||
|                                     <th>Quantity</th> | |||
|                                     <th>Cost</th> | |||
|                                     <th>Sale Price</th> | |||
|                                     <th>Profit</th> | |||
|                                     <th>Margin(%)</th> | |||
|                                 </tr> | |||
|                             </thead> | |||
|                             <tbody> | |||
|                                 <tr t-foreach="form" t-as="order"> | |||
|                                     <td> | |||
|                                         <span t-esc="order['sequence']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['date']" | |||
|                                               t-options='{"widget": "date"}'/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['partner']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['product']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['quantity']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['cost']"/> | |||
|                                         <t t-set="t_cost" | |||
|                                            t-value="t_cost + order['cost']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['price']"/> | |||
|                                         <t t-set="t_price" | |||
|                                            t-value="t_price + order['price']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['profit']"/> | |||
|                                         <t t-set="t_profit" | |||
|                                            t-value="t_profit + order['profit']"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span t-esc="order['margin']"/> | |||
|                                         <t t-set="t_margin" | |||
|                                            t-value="t_margin + order['margin']"/> | |||
|                                     </td> | |||
|                                 </tr> | |||
|                                 <tr> | |||
|                                     <td> | |||
|                                         <span>Total cost</span> | |||
|                                         <t t-esc="t_cost"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span>Total Price:</span> | |||
|                                         <t t-esc="t_price"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span>Total Profit:</span> | |||
|                                         <t t-esc="t_profit"/> | |||
|                                     </td> | |||
|                                     <td> | |||
|                                         <span>Total margin:</span> | |||
|                                         <t t-esc="t_margin"/> | |||
|                                     </td> | |||
|                                 </tr> | |||
|                             </tbody> | |||
|                         </table> | |||
|                     </t> | |||
|                 </t> | |||
|             </t> | |||
|         </t> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,59 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <!-- It is to print Sale report --> | |||
|     <record id="sale_report_action" model="ir.actions.report"> | |||
|         <field name="name">Sales</field> | |||
|         <field name="model">sale.report.advance</field> | |||
|         <field name="report_type">qweb-pdf</field> | |||
|         <field name="report_name">all_in_one_sales_kit.sale_profit_report_view</field> | |||
|         <field name="report_file">all_in_one_sales_kit.sale_profit_report_view</field> | |||
|     </record> | |||
|     <!-- It is to print Invoice Analysis report --> | |||
|     <record id="invoice_analysis_action" model="ir.actions.report"> | |||
|         <field name="name">Invoice Analysis</field> | |||
|         <field name="model">sale.report.invoice</field> | |||
|         <field name="report_type">qweb-pdf</field> | |||
|         <field name="report_name">all_in_one_sales_kit.invoice_analysis_view</field> | |||
|         <field name="report_file">all_in_one_sales_kit.invoice_analysis_view</field> | |||
|     </record> | |||
|     <!-- It is to print Sales Category report --> | |||
|     <record id="sale_category_action" model="ir.actions.report"> | |||
|         <field name="name">Sales Category</field> | |||
|         <field name="model">sale.report.category</field> | |||
|         <field name="report_type">qweb-pdf</field> | |||
|         <field name="report_name">all_in_one_sales_kit.sales_category_view</field> | |||
|         <field name="report_file">all_in_one_sales_kit.sales_category_view</field> | |||
|     </record> | |||
|     <!-- It is to print Product Sales Indent report --> | |||
|     <record id="sale_indent_action" model="ir.actions.report"> | |||
|         <field name="name">Product Sales Indent</field> | |||
|         <field name="model">sale.report.indent</field> | |||
|         <field name="report_type">qweb-pdf</field> | |||
|         <field name="report_name">all_in_one_sales_kit.sales_indent_view</field> | |||
|         <field name="report_file">all_in_one_sales_kit.sales_indent_view</field> | |||
|     </record> | |||
|     <!-- It is to print Sales Analysis Report--> | |||
|     <record id="sales_analysis_action" model="ir.actions.report"> | |||
|         <field name="name">Sales Analysis Report</field> | |||
|         <field name="model">sale.report.analysis</field> | |||
|         <field name="report_type">qweb-pdf</field> | |||
|         <field name="report_name">all_in_one_sales_kit.sales_analysis_view</field> | |||
|         <field name="report_file">all_in_one_sales_kit.sales_analysis_view</field> | |||
|     </record> | |||
|     <!-- It is to print Hourly Sales Report --> | |||
|     <record id="sales_weekly_action" model="ir.actions.report"> | |||
|         <field name="name">Hourly Sales Report</field> | |||
|         <field name="model">sale.report.weekly</field> | |||
|         <field name="report_type">qweb-pdf</field> | |||
|         <field name="report_name">all_in_one_sales_kit.sales_hourly_view</field> | |||
|         <field name="report_file">all_in_one_sales_kit.sales_hourly_view</field> | |||
|     </record> | |||
|     <!-- It is to print Sales All In One Report --> | |||
|     <record id="report_sale_all_in_one_action" model="ir.actions.report"> | |||
|         <field name="name">Sales All In One Report</field> | |||
|         <field name="model">sales.report</field> | |||
|         <field name="report_type">qweb-pdf</field> | |||
|         <field name="report_name">all_in_one_sales_kit.sale_order_report</field> | |||
|         <field name="report_file">all_in_one_sales_kit.sale_order_report</field> | |||
|     </record> | |||
| </odoo> | |||
| @ -0,0 +1,173 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|      <!--    Template for Sales Analysis Report --> | |||
|     <template id="sales_analysis_view"> | |||
|         <t t-call="web.html_container"> | |||
|             <t t-call="web.external_layout"> | |||
|                 <style> | |||
|                 </style> | |||
|                 <t class="page"> | |||
|                     <div class="oe_structure"/> | |||
|                     <center> | |||
|                         <b> | |||
|                             <h3>Sales Analysis Report</h3> | |||
|                         </b> | |||
|                     </center> | |||
|                     <t t-if="start_date and end_date"> | |||
|                         <center> | |||
|                             <span t-esc="start_date"/> | |||
|                             To | |||
|                             <span t-esc="end_date"/> | |||
|                         </center> | |||
|                     </t> | |||
|                     <t t-foreach="partner_id" t-as="partner"> | |||
|                         <center> | |||
|                             <b> | |||
|                                 <span t-esc="partner['name']" | |||
|                                       style="font-size:22px;"/> | |||
|                             </b> | |||
|                         </center> | |||
|                         <t t-if="type =='sale'"> | |||
|                             <t t-set="t_amt" t-value="0"/> | |||
|                             <t t-set="t_paid" t-value="0"/> | |||
|                             <t t-set="t_balance" t-value="0"/> | |||
|                             <table class="table table-condensed"> | |||
|                                 <thead> | |||
|                                     <tr> | |||
|                                         <th>Order Number</th> | |||
|                                         <th>Order Date</th> | |||
|                                         <th>Sales Person</th> | |||
|                                         <th>Sales Amount</th> | |||
|                                         <th>Amount Paid</th> | |||
|                                         <th>Balance</th> | |||
|                                     </tr> | |||
|                                 </thead> | |||
|                                 <tbody> | |||
|                                     <tr t-foreach="form" t-as="order"> | |||
|                                         <t t-if="order['partner_id'] == partner['id']"> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['so']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['date']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['sales_person']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['s_amt']"/> | |||
|                                                 <t t-set="t_amt" | |||
|                                                    t-value="t_amt + order['s_amt']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['p_amt']"/> | |||
|                                                 <t t-set="t_paid" | |||
|                                                    t-value="t_paid + order['p_amt']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['balance']"/> | |||
|                                                 <t t-set="t_balance" | |||
|                                                    t-value="t_balance + order['balance']"/> | |||
|                                             </td> | |||
|                                         </t> | |||
|                                     </tr> | |||
|                                     <tr> | |||
|                                         <td colsapn="3"> | |||
|                                             <span>Total Amount</span> | |||
|                                             <t t-esc="t_amt"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total Paid:</span> | |||
|                                             <t t-esc="t_paid"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total Balance:</span> | |||
|                                             <t t-esc="t_balance"/> | |||
|                                         </td> | |||
|                                     </tr> | |||
|                                 </tbody> | |||
|                             </table> | |||
|                         </t> | |||
|                         <t t-else=""> | |||
|                             <t t-set="t_total" t-value="0"/> | |||
|                             <t t-set="t_price" t-value="0"/> | |||
|                             <t t-set="t_disc" t-value="0"/> | |||
|                             <t t-set="t_qty" t-value="0"/> | |||
|                             <table class="table table-condensed"> | |||
|                                 <thead> | |||
|                                     <tr> | |||
|                                         <th>Order</th> | |||
|                                         <th>Date</th> | |||
|                                         <th>Product</th> | |||
|                                         <th>Quantity</th> | |||
|                                         <th>price</th> | |||
|                                         <th>Discount(%)</th> | |||
|                                         <th>Tax(%)</th> | |||
|                                         <th>Subtotal</th> | |||
|                                     </tr> | |||
|                                 </thead> | |||
|                                 <tbody> | |||
|                                     <tr t-foreach="form" t-as="order"> | |||
|                                         <t t-if="order['partner_id'] == partner['id']"> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['so']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['date']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['product_id']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['quantity']"/> | |||
|                                                 <t t-set="t_qty" | |||
|                                                    t-value="t_qty + order['quantity']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['price']"/> | |||
|                                                 <t t-set="t_price" | |||
|                                                    t-value="t_price + order['price']"/> | |||
| 
 | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['discount']"/> | |||
|                                                 <t t-set="t_disc" | |||
|                                                    t-value="t_disc + order['discount']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['tax']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['total']"/> | |||
|                                                 <t t-set="t_total" | |||
|                                                    t-value="t_total + order['total']"/> | |||
|                                             </td> | |||
|                                         </t> | |||
|                                     </tr> | |||
|                                     <tr> | |||
|                                         <td colsapn="3"> | |||
|                                             <span>Total Quantity</span> | |||
|                                             <t t-esc="t_qty"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total Price:</span> | |||
|                                             <t t-esc="t_price"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total Discount:</span> | |||
|                                             <t t-esc="t_disc"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Subtotal</span> | |||
|                                             <t t-esc="t_total"/> | |||
|                                         </td> | |||
|                                     </tr> | |||
|                                 </tbody> | |||
|                             </table> | |||
|                         </t> | |||
|                     </t> | |||
|                 </t> | |||
|             </t> | |||
|         </t> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,114 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|      <!--    Template for Sales category Report --> | |||
|     <template id="sales_category_view"> | |||
|         <t t-call="web.html_container"> | |||
|             <t t-call="web.external_layout"> | |||
|                 <t class="page"> | |||
|                     <div class="oe_structure"/> | |||
|                     <center> | |||
|                         <b> | |||
|                             <h3>Sales category Report</h3> | |||
|                         </b> | |||
|                     </center> | |||
|                     <t t-if="start_date and end_date"> | |||
|                         <center> | |||
|                             <span t-esc="start_date"/> | |||
|                             To | |||
|                             <span t-esc="end_date"/> | |||
|                         </center> | |||
|                     </t> | |||
|                     <t t-if="categ_id"> | |||
|                         <t t-foreach="categ_id" t-as="categ"> | |||
|                             <center> | |||
|                                 <b> | |||
|                                     <span t-esc="categ['name']"/> | |||
|                                 </b> | |||
|                             </center> | |||
|                             <br/> | |||
|                             <t t-set="t_qty" t-value="0"/> | |||
|                             <t t-set="t_price" t-value="0"/> | |||
|                             <t t-set="t_total" t-value="0"/> | |||
|                             <t t-set="t_subtotal" t-value="0"/> | |||
|                             <table class="table table-condensed"> | |||
|                                 <thead> | |||
|                                     <tr> | |||
|                                         <th>Order</th> | |||
|                                         <th>Date</th> | |||
|                                         <th>Product</th> | |||
|                                         <th>Quantity</th> | |||
|                                         <th>UOM</th> | |||
|                                         <th>Price</th> | |||
|                                         <th>Tax(%)</th> | |||
|                                         <th>Subtotal</th> | |||
|                                         <th>Total</th> | |||
|                                     </tr> | |||
|                                 </thead> | |||
|                                 <tbody> | |||
|                                     <tr t-foreach="form" t-as="order"> | |||
|                                         <t t-if="order['category_id'] == categ['id']"> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['so']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['date']" | |||
|                                                       t-options='{"widget": "date"}'/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['product_id']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['quantity']"/> | |||
|                                                 <t t-set="t_qty" | |||
|                                                    t-value="t_qty + order['quantity']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['uom']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['price']"/> | |||
|                                                 <t t-set="t_price" | |||
|                                                    t-value="t_price + order['price']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['tax']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['subtotal']"/> | |||
|                                                 <t t-set="t_subtotal" | |||
|                                                    t-value="t_subtotal + order['subtotal']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['total']"/> | |||
|                                                 <t t-set="t_total" | |||
|                                                    t-value="t_total + order['total']"/> | |||
|                                             </td> | |||
|                                         </t> | |||
|                                     </tr> | |||
|                                     <tr> | |||
|                                         <td colsapn="3"> | |||
|                                             <span>Total Quantity</span> | |||
|                                             <t t-esc="t_qty"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total Price:</span> | |||
|                                             <t t-esc="t_price"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total Subtotal:</span> | |||
|                                             <t t-esc="t_subtotal"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span>Total Total:</span> | |||
|                                             <t t-esc="t_total"/> | |||
|                                         </td> | |||
|                                     </tr> | |||
|                                 </tbody> | |||
|                             </table> | |||
|                         </t> | |||
|                     </t> | |||
|                 </t> | |||
|             </t> | |||
|         </t> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,61 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|      <!--    Template for Product Sales Indent Report --> | |||
|     <template id="sales_indent_view"> | |||
|         <t t-call="web.html_container"> | |||
|             <t t-call="web.external_layout"> | |||
|                 <t class="page"> | |||
|                     <div class="oe_structure"/> | |||
|                     <center> | |||
|                         <b> | |||
|                             <h3>Product Sales Indent Report</h3> | |||
|                         </b> | |||
|                     </center> | |||
|                     <t t-if="start_date and end_date"> | |||
|                         <center> | |||
|                             <span t-esc="start_date"/> | |||
|                             To | |||
|                             <span t-esc="end_date"/> | |||
|                         </center> | |||
|                     </t> | |||
|                     <t t-foreach="partner_id" t-as="partner"> | |||
|                         <center> | |||
|                             <b> | |||
|                                 <span t-esc="partner['name']" | |||
|                                       style="font-size:22px;"/> | |||
|                             </b> | |||
|                         </center> | |||
|                         <t t-foreach="categ_id" t-as="categ"> | |||
|                             <center> | |||
|                                 <b> | |||
|                                     <span t-esc="categ['name']" | |||
|                                           style="font-size:17px;"/> | |||
|                                 </b> | |||
|                             </center> | |||
|                             <table class="table table-condensed"> | |||
|                                 <thead> | |||
|                                     <tr> | |||
|                                         <th>Product</th> | |||
|                                         <th>Quantity</th> | |||
|                                     </tr> | |||
|                                 </thead> | |||
|                                 <tbody> | |||
|                                     <tr t-foreach="form" t-as="order"> | |||
|                                         <t t-if="order['category_id'] == categ['id'] and order['partner_id'] == partner['id']"> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['product_id']"/> | |||
|                                             </td> | |||
|                                             <td> | |||
|                                                 <span t-esc="order['quantity']"/> | |||
|                                             </td> | |||
|                                         </t> | |||
|                                     </tr> | |||
|                                 </tbody> | |||
|                             </table> | |||
|                         </t> | |||
|                     </t> | |||
|                 </t> | |||
|             </t> | |||
|         </t> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,68 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|      <!--    Template for Hourly Analysis Report --> | |||
|     <template id="sales_hourly_view"> | |||
|         <t t-call="web.html_container"> | |||
|             <t t-call="web.external_layout"> | |||
|                 <style> | |||
|                 </style> | |||
|                 <t class="page"> | |||
|                     <div class="oe_structure"/> | |||
|                     <center> | |||
|                         <b> | |||
|                             <h3>Hourly Sales Report</h3> | |||
|                         </b> | |||
|                     </center> | |||
|                     <t t-foreach="times" t-as="t"> | |||
|                         <center> | |||
|                             <b> | |||
|                                 <span t-esc="t['name']" | |||
|                                       style="font-size:21px;"/> | |||
|                             </b> | |||
|                         </center> | |||
|                         <t t-set="t_amt" t-value="0"/> | |||
|                         <table class="table table-condensed"> | |||
|                             <thead> | |||
|                                 <tr> | |||
|                                     <th>Order Number</th> | |||
|                                     <th>Order Date</th> | |||
|                                     <t t-if="type=='untax'"> | |||
|                                         <th>Untaxed Total</th> | |||
|                                     </t> | |||
|                                     <t t-else=""> | |||
|                                         <th>Total</th> | |||
|                                     </t> | |||
|                                 </tr> | |||
|                             </thead> | |||
|                             <tbody> | |||
|                                 <tr t-foreach="form" t-as="order"> | |||
|                                     <t t-if="order['time'] == t['id']"> | |||
|                                         <td> | |||
|                                             <span t-esc="order['order']"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span t-esc="order['date']"/> | |||
|                                         </td> | |||
|                                         <td> | |||
|                                             <span t-esc="order['amount']"/> | |||
|                                             <t t-set="t_amt" | |||
|                                                t-value="t_amt + order['amount']"/> | |||
|                                         </td> | |||
|                                     </t> | |||
|                                 </tr> | |||
|                                 <tr> | |||
|                                     <td colsapn="3"> | |||
|                                         <b> | |||
|                                             <span>Total Amount</span> | |||
|                                         </b> | |||
|                                         <t t-esc="t_amt"/> | |||
|                                     </td> | |||
|                                 </tr> | |||
|                             </tbody> | |||
|                         </table> | |||
|                     </t> | |||
|                 </t> | |||
|             </t> | |||
|         </t> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,18 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <data noupdate="0"> | |||
|         <!-- It is to set access for res.groups  --> | |||
|         <record id="module_sale_order_discount_approval"  model="ir.module.category"> | |||
|             <field name="name">Sale Order Discount Approval</field> | |||
|             <field name="description">Category for Discount Approval</field> | |||
|         </record> | |||
|         <record id="group_approval_manager" model="res.groups"> | |||
|             <field name="name">Discount Approval Manager</field> | |||
|             <field name="category_id" | |||
|                    ref="module_sale_order_discount_approval"/> | |||
|         </record> | |||
|         <record id="group_add_sale_custom_fields" model="res.groups"> | |||
|             <field name="name">Create Custom Fields in Sale</field> | |||
|         </record> | |||
|     </data> | |||
| </odoo> | |||
| 
 | 
| After Width: | Height: | Size: 3.6 KiB | 
| After Width: | Height: | Size: 310 B | 
| After Width: | Height: | Size: 1.3 KiB | 
| After Width: | Height: | Size: 1.4 KiB | 
| After Width: | Height: | Size: 576 B | 
| After Width: | Height: | Size: 733 B | 
| After Width: | Height: | Size: 911 B | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 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: 82 KiB | 
| After Width: | Height: | Size: 88 KiB | 
| After Width: | Height: | Size: 15 KiB | 
| After Width: | Height: | Size: 84 KiB | 
| After Width: | Height: | Size: 88 KiB | 
| After Width: | Height: | Size: 87 KiB | 
| After Width: | Height: | Size: 327 KiB | 
| After Width: | Height: | Size: 106 KiB | 
| After Width: | Height: | Size: 98 KiB | 
| After Width: | Height: | Size: 44 KiB | 
| After Width: | Height: | Size: 301 KiB | 
| After Width: | Height: | Size: 161 KiB | 
| After Width: | Height: | Size: 36 KiB | 
| After Width: | Height: | Size: 54 KiB | 
| After Width: | Height: | Size: 162 KiB | 
| After Width: | Height: | Size: 170 KiB | 
| After Width: | Height: | Size: 152 KiB | 
| After Width: | Height: | Size: 153 KiB | 
| After Width: | Height: | Size: 167 KiB | 
| After Width: | Height: | Size: 105 KiB | 
| After Width: | Height: | Size: 114 KiB | 
| After Width: | Height: | Size: 39 KiB | 
| After Width: | Height: | Size: 89 KiB | 
| After Width: | Height: | Size: 306 KiB | 
| After Width: | Height: | Size: 90 KiB | 
| After Width: | Height: | Size: 83 KiB | 
| After Width: | Height: | Size: 75 KiB | 
| After Width: | Height: | Size: 82 KiB | 
| After Width: | Height: | Size: 80 KiB | 
| After Width: | Height: | Size: 84 KiB | 
| After Width: | Height: | Size: 84 KiB | 
| After Width: | Height: | Size: 92 KiB | 
| After Width: | Height: | Size: 85 KiB | 
| After Width: | Height: | Size: 67 KiB |