diff --git a/all_in_one_purchase_kit/README.rst b/all_in_one_purchase_kit/README.rst new file mode 100644 index 000000000..7afd4c95f --- /dev/null +++ b/all_in_one_purchase_kit/README.rst @@ -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 Purchase Kit +======================= +This module combines a verity of Purchase features. By Installing this module a user can get features like Product brand, Merge sale order, Purchase Order Line View, Amount in company currency, Amount in words, Employee Purchase requisition, Product recommendation etc.. + +Configuration +============= +- No additional configuration is required + +Company +------- +* `Cybrosys Techno Solutions `__ + +License +------- +GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (AGPL v3) +(https://www.gnu.org/licenses/agpl-3.0-standalone.html) + +Credits +------- +Developer: (V16)Mohamed Muzammil VP, 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 `__ + +Further information +=================== +HTML Description: ``__ diff --git a/all_in_one_purchase_kit/__init__.py b/all_in_one_purchase_kit/__init__.py new file mode 100644 index 000000000..432a35200 --- /dev/null +++ b/all_in_one_purchase_kit/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from . import controllers +from . import models +from . import report +from . import wizard diff --git a/all_in_one_purchase_kit/__manifest__.py b/all_in_one_purchase_kit/__manifest__.py new file mode 100644 index 000000000..d4dc13cae --- /dev/null +++ b/all_in_one_purchase_kit/__manifest__.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +{ + 'name': 'All In One Purchase Kit', + 'version': '16.0.1.0.0', + 'category': 'Purchases', + 'summary': 'An integrated module offering streamlined purchase management', + 'description': 'Product Brand for products, Purchase Order Line View,' + 'Company Currency Total in Purchase,' + 'Employee Purchase Requisition,' + 'Purchase All In One Report Generator,' + 'Previous Purchase Product Rates,' + 'Barcode scanning support for Purchase,' + 'Amount in Words in Invoice for Purchase Order,' + 'Multiple Purchase Order Confirm And Cancel,' + 'Merge Same Product Line, Product image in order-line,' + 'Purchase discount from Purchase order line,' + 'Product Recommendation', + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': 'https://www.cybrosys.com', + 'depends': ['base', 'hr', 'stock', 'purchase'], + 'data': [ + 'security/all_in_one_purchase_kit_groups.xml', + 'security/all_in_one_purchase_kit_security.xml', + 'security/ir.model.access.csv', + 'data/ir_sequence_data.xml', + 'data/mail_template_data.xml', + 'views/employee_purchase_requisition_views.xml', + 'views/hr_employee_views.xml', + 'views/hr_department_views.xml', + 'views/purchase_order_views.xml', + 'views/stock_picking_views.xml', + 'views/employee_purchase_requisition_action.xml', + 'views/product_brand_views.xml', + 'views/product_template_views.xml', + 'views/purchase_report_views.xml', + 'views/purchase_order_line_views.xml', + 'views/rfq_line_views.xml', + 'views/purchase_report.xml', + 'views/account_move_views.xml', + 'views/product_product_views.xml', + 'views/res_config_settings_views.xml', + 'views/product_supplier_views.xml', + 'views/res_partner_views.xml', + 'views/purchase_dashboard.xml', + 'report/purchase_order_report_templates.xml', + 'report/all_in_one_purchase_kit_report_views.xml', + 'report/purchase_requisition_templates.xml', + 'report/purchase_order_templates.xml', + 'report/dynamic_purchase_report_action.xml', + 'wizard/product_recommendation_views.xml', + 'views/all_in_one_purchase_kit_menus.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'all_in_one_purchase_kit/static/src/js/purchase_report.js', + 'all_in_one_purchase_kit/static/src/js/PurchaseDashboard.js', + 'all_in_one_purchase_kit/static/src/css/purchase_report.css', + 'all_in_one_purchase_kit/static/src/scss/purchase_dashboard.scss', + 'all_in_one_purchase_kit/static/src/xml/purchase_report_views.xml', + 'all_in_one_purchase_kit/static/src/xml/dasboard_templates.xml', + 'https://cdn.jsdelivr.net/npm/chart.js', + ], + }, + 'images': ['static/description/banner.jpg'], + 'license': 'AGPL-3', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/all_in_one_purchase_kit/controllers/__init__.py b/all_in_one_purchase_kit/controllers/__init__.py new file mode 100644 index 000000000..aa2ebb011 --- /dev/null +++ b/all_in_one_purchase_kit/controllers/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from . import all_in_one_purchase_kit diff --git a/all_in_one_purchase_kit/controllers/all_in_one_purchase_kit.py b/all_in_one_purchase_kit/controllers/all_in_one_purchase_kit.py new file mode 100644 index 000000000..91f903617 --- /dev/null +++ b/all_in_one_purchase_kit/controllers/all_in_one_purchase_kit.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +import json +from odoo import http +from odoo.http import content_disposition, request +from odoo.tools import html_escape + + +class PurchaseReportController(http.Controller): + """Controller to generate excel report""" + @http.route('/purchase_dynamic_xlsx_reports', type='http', auth='user', + methods=['POST'], csrf=False) + def get_report_xlsx(self, model, options, output_format, report_data, + report_name, dfr_data): + """ Method to generate and return an Excel 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].with_user( + request.session.uid).get_purchase_xlsx_report( + options, response, report_data, dfr_data) + response.set_cookie('fileToken', token) + return response + except Exception: + error = { + 'code': 200, + 'message': 'Odoo Server Error', + 'data': 0, + } + return request.make_response(html_escape(json.dumps(error))) diff --git a/all_in_one_purchase_kit/data/ir_sequence_data.xml b/all_in_one_purchase_kit/data/ir_sequence_data.xml new file mode 100644 index 000000000..0e62f56d1 --- /dev/null +++ b/all_in_one_purchase_kit/data/ir_sequence_data.xml @@ -0,0 +1,14 @@ + + + + + Employee Purchase Requisition + employee.purchase.requisition + EPR + 5 + + + + + + diff --git a/all_in_one_purchase_kit/data/mail_template_data.xml b/all_in_one_purchase_kit/data/mail_template_data.xml new file mode 100644 index 000000000..661dfcf8e --- /dev/null +++ b/all_in_one_purchase_kit/data/mail_template_data.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + +
+

+ Dear + Brandon Freeman + + ( + Azure Interior) + +
+
+ Here is in attachment a purchase order + P00015 + + with reference: + REF_XXX + + amounting in + + $ 10.00 + + + + + from + YourCompany. +
+
+ + The receipt is expected for + 05/05/2021. +
+
+ Could you please acknowledge the receipt of this order? +
+

+
+
+
+ + + + + + + +
+
diff --git a/all_in_one_purchase_kit/doc/RELEASE_NOTES.md b/all_in_one_purchase_kit/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..6992eb0dc --- /dev/null +++ b/all_in_one_purchase_kit/doc/RELEASE_NOTES.md @@ -0,0 +1,7 @@ +## Module + +#### 06.01.2024 +#### Version 16.0.1.0.0 +#### ADD + +- Initial Commit for All In One Purchase Kit diff --git a/all_in_one_purchase_kit/models/__init__.py b/all_in_one_purchase_kit/models/__init__.py new file mode 100644 index 000000000..f50e22e7d --- /dev/null +++ b/all_in_one_purchase_kit/models/__init__.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from . import account_move +from . import dynamic_purchase_report +from . import employee_purchase_requisition +from . import hr_department +from . import hr_employee +from . import product_brand +from . import product_product +from . import product_supplierinfo +from . import product_template +from . import purchase_order +from . import purchase_order_line +from . import purchase_report +from . import requisition_order +from . import res_config_settings +from . import res_partner +from . import stock_picking diff --git a/all_in_one_purchase_kit/models/account_move.py b/all_in_one_purchase_kit/models/account_move.py new file mode 100644 index 000000000..36d7a4eda --- /dev/null +++ b/all_in_one_purchase_kit/models/account_move.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import fields, models + + +class AccountMove(models.Model): + """Inherit account.move to add fields and methods""" + _inherit = 'account.move' + + amount_total_company_signed = fields.Float( + string='Company Currency Total', + compute='_compute_amount_total_company_signed', + help="Total amount in company currency") + number_to_words = fields.Char( + string="Amount in Words (Total) : ", + compute='_compute_number_to_words', help="Amount in words") + + def _compute_amount_total_company_signed(self): + """Compute the total amount in company currency for each record.""" + for amount in self: + amount.amount_total_company_signed = self.env[ + 'res.currency']._compute( + amount.currency_id, amount.company_id.currency_id, + amount.amount_total) + + def _compute_number_to_words(self): + """Compute the amount to words in Invoice for each record.""" + for rec in self: + rec.number_to_words = rec.currency_id.amount_to_text( + rec.amount_total) + + def action_post(self): + """Override the default post action to merge order lines with the same + product and price.""" + for line in self.invoice_line_ids: + if line.id in self.invoice_line_ids.ids: + line_ids = self.invoice_line_ids.filtered( + lambda m: m.product_id.id == line.product_id.id and m. + price_unit == line.price_unit) + quantity = line_ids.mapped('quantity') + line_ids.write({'quantity': sum(quantity), + 'price_unit': line.price_unit}) + line_ids[1:].unlink() + res = super(AccountMove, self).action_post() + return res diff --git a/all_in_one_purchase_kit/models/dynamic_purchase_report.py b/all_in_one_purchase_kit/models/dynamic_purchase_report.py new file mode 100644 index 000000000..c3b31a2cc --- /dev/null +++ b/all_in_one_purchase_kit/models/dynamic_purchase_report.py @@ -0,0 +1,485 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +import io +import json +from odoo import api, fields, models +from odoo.exceptions import ValidationError +try: + from odoo.tools.misc import xlsxwriter +except ImportError: + import xlsxwriter + + +class DynamicPurchaseReport(models.Model): + """Model for generating dynamic purchase reports""" + _name = "dynamic.purchase.report" + _description = 'Dynamic Purchase Report' + + purchase_report = fields.Char( + string="Purchase Report", help="Purchase Report" + ) + date_from = fields.Datetime( + string="Date From", help="From which date report needed" + ) + date_to = fields.Datetime( + string="Date to", help="Till which date report needs to print" + ) + 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_purchase_representative', + 'Report By Purchase Representative'), + ('report_by_state', 'Report By State')], default='report_by_order', + string="Report Type", + help="Choose the report type need to be printed" + ) + + @api.model + def purchase_report(self, option): + """ + Generate a dynamic purchase report. + """ + report_values = self.env['dynamic.purchase.report'].browse(option) + 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('PURCHASE') + return { + 'name': "Purchase Orders", + 'type': 'ir.actions.client', + 'tag': 's_r', + 'orders': data, + 'filters': filters, + 'report_lines': lines, + } + + def get_filter(self, option): + """Get the selected filter type for the report.""" + 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_purchase_representative': + filters['report_type'] = 'Report By Purchase Representative' + 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): + """Get filter data for the specified report configuration.""" + return { + 'report_type': self.env[ + 'dynamic.purchase.report'].browse(option).report_type + } + + @api.model + def create(self, vals): + """Override the default create method to create a new dynamic purchase + report record.""" + return super(DynamicPurchaseReport, self).create(vals) + + def write(self, vals): + """Override the default write method to update the field values of the + dynamic purchase report record.""" + return super(DynamicPurchaseReport, self).write(vals) + + def _get_report_sub_lines(self, data, report, date_from, date_to): + """Getting data for report lines""" + report_sub_lines = [] + if data.get('report_type') == 'report_by_order': + query = ''' + select l.name,l.date_order,l.partner_id,l.amount_total, + l.notes,l.user_id,res_partner.name as partner, + res_users.partner_id as user_partner, + sum(purchase_order_line.product_qty),l.id as id, + (SELECT res_partner.name as salesman FROM + res_partner WHERE res_partner.id = res_users.partner_id) + from purchase_order as l + left join res_partner on l.partner_id = res_partner.id + left join res_users on l.user_id = res_users.id + left join purchase_order_line on l.id = + purchase_order_line.order_id + ''' + term = 'Where ' + if data.get('date_from') and data.get('date_to') and \ + data.get('date_from') > data.get('date_to'): + raise ValidationError('Start Date cannot be greater than ' + 'End Date') + if data.get('date_from'): + query += "Where l.date_order >= '%s' " % data.get('date_from') + term = 'AND ' + if data.get('date_to'): + query += term + "l.date_order <= '%s' " % data.get('date_to') + query += "group by l.user_id,res_users.partner_id," \ + "res_partner.name,l.partner_id,l.date_order,l.name," \ + "l.amount_total,l.notes,l.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 l.name,l.date_order,l.partner_id,l.amount_total, + l.notes,l.user_id,res_partner.name as partner, + res_users.partner_id as user_partner, + sum(purchase_order_line.product_qty), + purchase_order_line.name as product, + purchase_order_line.price_unit,purchase_order_line.price_subtotal, + l.amount_total,purchase_order_line.product_id, + product_product.default_code, + (SELECT res_partner.name as salesman FROM res_partner + WHERE res_partner.id = res_users.partner_id) + from purchase_order as l + left join res_partner on l.partner_id = res_partner.id + left join res_users on l.user_id = res_users.id + left join purchase_order_line on l.id = + purchase_order_line.order_id + left join product_product on purchase_order_line.product_id = + product_product.id + ''' + term = 'Where ' + if data.get('date_from'): + query += "Where l.date_order >= '%s' " % data.get('date_from') + term = 'AND ' + if data.get('date_to'): + query += term + "l.date_order <= '%s' " % data.get('date_to') + query += "group by l.user_id,res_users.partner_id," \ + "res_partner.name,l.partner_id,l.date_order," \ + "l.name,l.amount_total,l.notes," \ + "purchase_order_line.name," \ + "purchase_order_line.price_unit," \ + "purchase_order_line.price_subtotal,l.amount_total," \ + "purchase_order_line.product_id," \ + "product_product.default_code" + 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 l.amount_total,sum(purchase_order_line.product_qty) as qty, + purchase_order_line.name as product, + purchase_order_line.price_unit,product_product.default_code, + product_category.name + from purchase_order as l + left join purchase_order_line on l.id = + purchase_order_line.order_id + left join product_product on purchase_order_line.product_id = + product_product.id + left join product_template on purchase_order_line.product_id = + product_template.id + left join product_category on product_category.id = + product_template.categ_id + ''' + term = 'Where ' + if data.get('date_from'): + query += "Where l.date_order >= '%s' " % data.get('date_from') + term = 'AND ' + if data.get('date_to'): + query += term + "l.date_order <= '%s' " % data.get('date_to') + query += "group by l.amount_total,purchase_order_line.name," \ + "purchase_order_line.price_unit," \ + "purchase_order_line.product_id," \ + "product_product.default_code," \ + "product_template.categ_id,product_category.name" + 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(l.product_qty) as qty, + sum(l.price_subtotal) as amount_total + from purchase_order_line as l + left join product_template on l.product_id = product_template.id + left join product_category on product_category.id = + product_template.categ_id + left join purchase_order on l.order_id = purchase_order.id + ''' + term = 'Where ' + if data.get('date_from'): + query += "Where pos_order.date_order >= '%s' " % data.get( + 'date_from') + term = 'AND ' + if data.get('date_to'): + query += term + "pos_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_purchase_representative': + query = ''' + select res_partner.name,sum(purchase_order_line.product_qty) as + qty,sum(purchase_order_line.price_subtotal) as amount,count(l.id) + as order from purchase_order as l + left join res_users on l.user_id = res_users.id + left join res_partner on res_users.partner_id = res_partner.id + left join purchase_order_line on l.id = + purchase_order_line.order_id + ''' + term = 'Where ' + if data.get('date_from'): + query += "Where l.date_order >= '%s' " % data.get('date_from') + term = 'AND ' + if data.get('date_to'): + query += term + "l.date_order <= '%s' " % data.get('date_to') + query += "group by res_partner.name" + self._cr.execute(query) + report_by_purchase_representative = self._cr.dictfetchall() + report_sub_lines.append(report_by_purchase_representative) + elif data.get('report_type') == 'report_by_state': + query = ''' + select l.state,sum(purchase_order_line.product_qty) as + qty,sum(purchase_order_line.price_subtotal) as amount,count(l.id) + as order from purchase_order as l + left join res_users on l.user_id = res_users.id + left join res_partner on res_users.partner_id = res_partner.id + left join purchase_order_line on l.id = + purchase_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 l.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_values(self, data): + """Get data for the specified type of report lines.""" + docs = data['model'] + date_from = data.get('date_from') + date_to = data.get('date_to') + 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_purchase_representative': + report = ['Report By Purchase Representative'] + elif data['report_type'] == 'report_by_state': + report = ['Report By State'] + else: + report = ['Report By Order'] + if data.get('report_type'): + report_res = \ + self._get_report_sub_lines(data, report, date_from, date_to)[0] + else: + report_res = self._get_report_sub_lines(data, report, date_from, + date_to) + return { + 'doc_ids': self.ids, + 'docs': docs, + 'PURCHASE': report_res, + } + + def get_purchase_xlsx_report(self, data, response, report_data, dfr_data): + """Generate an XLSX report with purchase data based on provided + filters.""" + report_data_main = json.loads(report_data) + output = io.BytesIO() + filters = json.loads(data) + 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', 'Purchase 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', 'Order', heading) + sheet.write('B7', 'Date Order', heading) + sheet.write('C7', 'Customer', heading) + sheet.write('D7', 'Purchase Representative', heading) + sheet.write('E7', 'Total Qty', heading) + sheet.write('F7', 'Amount Total', heading) + if report_data_main: + 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['name'], txt_l) + sheet.write(row, col + 1, rec_data['date_order'], txt_l) + sheet.write(row, col + 2, rec_data['partner'], txt_l) + sheet.write(row, col + 3, rec_data['salesman'], 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', 'Order', heading) + sheet.write('B7', 'Date Order', heading) + sheet.write('C7', 'Customer', heading) + sheet.write('D7', 'Purchase Representative', heading) + sheet.write('E7', 'Product Code', heading) + sheet.write('F7', 'Product Name', heading) + sheet.write('G7', 'Price unit', heading) + sheet.write('H7', 'Qty', heading) + sheet.write('I7', 'Price Total', heading) + if report_data_main: + 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 + sheet.write(row, col, rec_data['name'], txt_l) + sheet.write(row, col + 1, rec_data['date_order'], txt_l) + sheet.write(row, col + 2, rec_data['partner'], txt_l) + sheet.write(row, col + 3, rec_data['salesman'], txt_l) + sheet.write(row, col + 4, rec_data['default_code'], txt_l) + sheet.write(row, col + 5, rec_data['product'], txt_l) + sheet.write(row, col + 6, rec_data['price_unit'], txt_l) + sheet.write(row, col + 7, rec_data['sum'], txt_l) + sheet.write(row, col + 8, 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', 'Category', heading) + sheet.write('B7', 'Product Code', heading) + sheet.write('C7', 'Product Name', heading) + sheet.write('D7', 'Qty', heading) + sheet.write('E7', 'Amount Total', heading) + if report_data_main: + 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 + sheet.write(row, col, rec_data['name'], txt_l) + sheet.write(row, col + 1, rec_data['default_code'], txt_l) + sheet.write(row, col + 2, rec_data['product'], txt_l) + sheet.write(row, col + 3, rec_data['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) + if report_data_main: + 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_purchase_representative': + sheet.merge_range('B5:D5', 'Report Type: ' + + filters.get('report_type'), txt_l) + sheet.write('A7', 'Purchase Representative', heading) + sheet.write('B7', 'Total Order', heading) + sheet.write('C7', 'Total Qty', heading) + sheet.write('D7', 'Total Amount', heading) + if report_data_main: + 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) + if report_data_main: + 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'] == 'purchase': + sheet.write(row, col, 'Purchase Order', 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) + workbook.close() + output.seek(0) + response.stream.write(output.read()) + output.close() diff --git a/all_in_one_purchase_kit/models/employee_purchase_requisition.py b/all_in_one_purchase_kit/models/employee_purchase_requisition.py new file mode 100644 index 000000000..b7d9cbb18 --- /dev/null +++ b/all_in_one_purchase_kit/models/employee_purchase_requisition.py @@ -0,0 +1,260 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import api, fields, models + + +class EmployeePurchaseRequisition(models.Model): + """ Model for storing purchase requisition """ + _name = 'employee.purchase.requisition' + _description = 'Purchase Requisition' + _inherit = "mail.thread", "mail.activity.mixin" + + name = fields.Char( + string="Reference No", help="Reference Number", readonly=True + ) + employee_id = fields.Many2one( + 'hr.employee', string='Employee', required=True, + help='Choose the employee' + ) + dept_id = fields.Many2one( + 'hr.department', related='employee_id.department_id', store=True, + help='Choose Department', string='Department' + ) + user_id = fields.Many2one( + 'res.users', string='Requisition Responsible', required=True, + help='Requisition responsible user' + ) + requisition_date = fields.Date( + string="Requisition Date", default=lambda self: fields.Date.today(), + help='Date of Requisition' + ) + receive_date = fields.Date( + string="Received Date", readonly=True, help='Receive Date' + ) + requisition_deadline = fields.Date( + string="Requisition Deadline", help="End date of Purchase requisition" + ) + company_id = fields.Many2one( + 'res.company', string='Company', default=lambda self: self.env.company, + help='Select the company' + ) + requisition_order_ids = fields.One2many( + 'requisition.order', 'requisition_product_id', required=True, + string="Requisition Order", help="Requisition order") + confirm_id = fields.Many2one( + 'res.users', string='Confirmed By', default=lambda self: self.env.uid, + readonly=True, help='User who Confirmed the requisition.' + ) + manager_id = fields.Many2one( + 'res.users', string='Department Manager', readonly=True, + help='Department Manager' + ) + requisition_head_id = fields.Many2one( + 'res.users', string='Approved By', readonly=True, + help='User who approved the requisition.' + ) + rejected_user_id = fields.Many2one( + 'res.users', string='Rejected By', readonly=True, + help='user who rejected the requisition' + ) + confirmed_date = fields.Date( + string='Confirmed Date', readonly=True, + help='Date of Requisition Confirmation' + ) + department_approval_date = fields.Date( + string='Department Approval Date', readonly=True, + help='Department Approval Date' + ) + approval_date = fields.Date( + string='Approved Date', readonly=True, help='Requisition Approval Date' + ) + reject_date = fields.Date( + string='Rejection Date', readonly=True, + help='Requisition Rejected Date' + ) + source_location_id = fields.Many2one( + 'stock.location', string='Source Location', + help='Source location of requisition.' + ) + destination_location_id = fields.Many2one( + 'stock.location', string="Destination Location", + help='Destination location of requisition.' + ) + delivery_type_id = fields.Many2one( + 'stock.picking.type', string='Delivery To', help='Type of Delivery.' + ) + internal_picking_id = fields.Many2one( + 'stock.picking.type', string="Internal Picking", + help="Choose picking type" + ) + requisition_description = fields.Text( + string="Reason For Requisition", help="Write description" + ) + purchase_count = fields.Integer( + string='Purchase Count', help="Count of purchase order" + ) + internal_transfer_count = fields.Integer( + string='Internal Transfer count', help="Internal transfer count" + ) + state = fields.Selection( + [('new', 'New'), + ('waiting_department_approval', 'Waiting Department Approval'), + ('waiting_head_approval', 'Waiting Head Approval'), + ('approved', 'Approved'), + ('purchase_order_created', 'Purchase Order Created'), + ('received', 'Received'), + ('cancelled', 'Cancelled')], string="State", default='new', + copy=False, tracking=True, help="State of the record" + ) + has_internal = fields.Boolean(string='Has Internal Transfer', + help="Will become true if this purchase " + "requisition has internal transfer", + compute="_compute_has_internal") + + @api.model + def create(self, vals): + """Generate purchase requisition sequence""" + if vals.get('name', 'New') == 'New': + vals['name'] = self.env['ir.sequence'].next_by_code( + 'employee.purchase.requisition') or 'New' + return super(EmployeePurchaseRequisition, self).create(vals) + + @api.depends('requisition_order_ids') + def _compute_has_internal(self): + """Method to compute whether there is any internal transfer in the + purchase requisition""" + for rec in self: + has_internal_transfer = False + for order in rec.requisition_order_ids: + if order.requisition_type == 'internal_transfer': + has_internal_transfer = True + break + if has_internal_transfer: + rec.has_internal = True + else: + rec.has_internal = False + + def action_confirm_requisition(self): + """Confirm purchase requisition""" + self.source_location_id = self.employee_id.department_id.department_location_id.id + self.destination_location_id = self.employee_id.employee_location_id.id + self.delivery_type_id = self.source_location_id.warehouse_id.in_type_id.id + self.internal_picking_id = self.source_location_id.warehouse_id.int_type_id.id + self.write({'state': 'waiting_department_approval'}) + self.confirm_id = self.env.uid + self.confirmed_date = fields.Date.today() + + def action_department_approval(self): + """Approval from the department""" + self.write({'state': 'waiting_head_approval'}) + self.manager_id = self.env.uid + self.department_approval_date = fields.Date.today() + + def action_department_cancel(self): + """Cancellation from department """ + self.write({'state': 'cancelled'}) + self.rejected_user_id = self.env.uid + self.reject_date = fields.Date.today() + + def action_head_approval(self): + """Approval from department head""" + self.write({'state': 'approved'}) + self.requisition_head_id = self.env.uid + self.approval_date = fields.Date.today() + + def action_head_cancel(self): + """Cancellation from department head""" + self.write({'state': 'cancelled'}) + self.rejected_user_id = self.env.uid + self.reject_date = fields.Date.today() + + def action_create_purchase_order(self): + """Create purchase order and internal transfer""" + for rec in self.requisition_order_ids: + if rec.requisition_type == 'internal_transfer': + self.env['stock.picking'].create({ + 'location_id': self.source_location_id.id, + 'location_dest_id': self.destination_location_id.id, + 'picking_type_id': self.internal_picking_id.id, + 'requisition_order': self.name, + 'move_ids_without_package': [(0, 0, { + 'name': rec.product_id.name, + 'product_id': rec.product_id.id, + 'product_uom': rec.product_id.uom_id, + 'product_uom_qty': rec.quantity, + 'location_id': self.source_location_id.id, + 'location_dest_id': self.destination_location_id.id, + })] + }) + else: + self.env['purchase.order'].create({ + 'partner_id': self.employee_id.work_contact_id.id, + 'requisition_order': self.name, + "order_line": [(0, 0, { + 'product_id': rec.product_id.id, + 'product_qty': rec.quantity, + })]}) + self.write({'state': 'purchase_order_created'}) + self.purchase_count = self.env['purchase.order'].search_count([ + ('requisition_order', '=', self.name)]) + self.internal_transfer_count = self.env['stock.picking'].search_count([ + ('requisition_order', '=', self.name)]) + + def action_receive(self): + """Receive purchase requisition""" + self.write({'state': 'received'}) + self.receive_date = fields.Date.today() + + def get_purchase_order(self): + """Purchase order smart button, when click on the smart button it + gives the purchase order of the user""" + self.ensure_one() + return { + 'type': 'ir.actions.act_window', + 'name': 'Purchase Order', + 'view_mode': 'tree,form', + 'res_model': 'purchase.order', + 'domain': [('requisition_order', '=', self.name)], + } + + def get_internal_transfer(self): + """Internal transfer smart button, when click on the smart button it + gives the internal transfer of the user""" + self.ensure_one() + return { + 'type': 'ir.actions.act_window', + 'name': 'Internal Transfers', + 'view_mode': 'tree,form', + 'res_model': 'stock.picking', + 'domain': [('requisition_order', '=', self.name)], + } + + def action_print_report(self): + """Print purchase requisition report""" + data = { + 'employee': self.employee_id.name, + 'records': self.read(), + 'order_ids': self.requisition_order_ids.read(), + } + return self.env.ref( + 'all_in_one_purchase_kit.report_purchase_requisition_action' + ).report_action(self, data=data) diff --git a/all_in_one_purchase_kit/models/hr_department.py b/all_in_one_purchase_kit/models/hr_department.py new file mode 100644 index 000000000..f58849f1a --- /dev/null +++ b/all_in_one_purchase_kit/models/hr_department.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import fields, models + + +class HrDepartment(models.Model): + """ Inherit the hr.department model add department location field""" + _inherit = 'hr.department' + + department_location_id = fields.Many2one( + 'stock.location', string='Destination Location', + help='Department location' + ) diff --git a/all_in_one_purchase_kit/models/hr_employee.py b/all_in_one_purchase_kit/models/hr_employee.py new file mode 100644 index 000000000..dedb77432 --- /dev/null +++ b/all_in_one_purchase_kit/models/hr_employee.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import fields, models + + +class HrEmployee(models.Model): + """ inherit hr.employee model add employee location field""" + + _inherit = 'hr.employee' + + employee_location_id = fields.Many2one( + 'stock.location', string="Destination Location", + help='Employee location' + ) diff --git a/all_in_one_purchase_kit/models/product_brand.py b/all_in_one_purchase_kit/models/product_brand.py new file mode 100644 index 000000000..1b1403edf --- /dev/null +++ b/all_in_one_purchase_kit/models/product_brand.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import api, fields, models + + +class ProductBrand(models.Model): + """Model to add brand for products""" + _name = 'product.brand' + _description = 'Product Brand' + + name = fields.Char(String="Name", help="Brand name") + brand_image = fields.Binary(String="Brand Logo", help="Brand Logo") + product_ids = fields.One2many( + 'product.template', 'brand_id', string="Product", help="Add product" + ) + product_count = fields.Char( + String='Product Count', compute='_compute_count_products', store=True, + help="Count of Products" + ) + + @api.depends('product_ids') + def _compute_count_products(self): + """Methode to get the count of products in brand""" + for rec in self: + rec.product_count = len(rec.product_ids) diff --git a/all_in_one_purchase_kit/models/product_product.py b/all_in_one_purchase_kit/models/product_product.py new file mode 100644 index 000000000..802d79113 --- /dev/null +++ b/all_in_one_purchase_kit/models/product_product.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import api, fields, models +from odoo.exceptions import UserError + + +class ProductProduct(models.Model): + """Inherit model and add fields and methods""" + _inherit = "product.product" + + order_partner_id = fields.Many2one( + 'res.partner', string="Partner", help="Choose partner" + ) + + def action_purchase_product_prices(self): + """Display the purchase history of a product.""" + rel_view_id = self.env.ref( + 'all_in_one_purchase_kit.last_product_purchase_prices_view') + if self.order_partner_id.id: + purchase_lines = self.env['purchase.order.line'].search( + [('product_id', '=', self.id), + ('partner_id', '=', self.order_partner_id.id)], + order='create_date DESC').mapped('id') + else: + purchase_lines = self.env['purchase.order.line'].search( + [('product_id', '=', self.id)], + order='create_date DESC').mapped('id') + if not purchase_lines: + raise UserError("No purchase history found.!") + return { + 'domain': [('id', 'in', purchase_lines)], + 'views': [(rel_view_id.id, 'tree')], + 'name': 'Purchase History', + 'res_model': 'purchase.order.line', + 'view_id': False, + 'type': 'ir.actions.act_window', + } + + @api.model + def most_purchased_product(self): + """Method returns most purchased products""" + purchased_qty = self.search_read([], ['name', 'purchased_product_qty']) + product_qty = {count['name']: count['purchased_product_qty'] for count + in purchased_qty if count['purchased_product_qty'] > 0} + sorted_qty = {key: val for key, val in sorted( + product_qty.items(), key=lambda ele: ele[1], reverse=True) + } + return {'purchased_qty': sorted_qty} + + def add_to_rfq(self): + """When click on add to RFQ button product added to RFQ""" + order_id = self.env.context.get('order_id') + sale_order_id = self.env['purchase.order.line'].search( + [('order_id', '=', order_id)]) + lst = [rec.product_id for rec in sale_order_id] + if self in lst: + order_line_id = self.env['purchase.order.line'].search( + [('order_id', '=', order_id), ('product_id', '=', self.id)]) + order_line_id.product_uom_qty += 1 + else: + self.env['purchase.order.line'].create({ + 'product_id': self.id, + 'order_id': order_id, + }) diff --git a/all_in_one_purchase_kit/models/product_supplierinfo.py b/all_in_one_purchase_kit/models/product_supplierinfo.py new file mode 100644 index 000000000..3242ae0e3 --- /dev/null +++ b/all_in_one_purchase_kit/models/product_supplierinfo.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import api, fields, models + + +class ProductSupplierInfo(models.Model): + """Inherit the model to add fields and methods""" + _inherit = "product.supplierinfo" + + discount = fields.Float(string="Discount (%)", help="Discount in %") + _sql_constraints = [ + ( + "maximum_discount", + "CHECK (discount <= 100.0)", + "Discount must be lower than 100%.", + ) + ] + + @api.onchange("partner_id") + def _onchange_discount(self): + """Add default discount to order line""" + for supplier in self.filtered("partner_id"): + supplier.write({'discount': supplier.partner_id.default_discount}) diff --git a/all_in_one_purchase_kit/models/product_template.py b/all_in_one_purchase_kit/models/product_template.py new file mode 100644 index 000000000..04c8c8fe6 --- /dev/null +++ b/all_in_one_purchase_kit/models/product_template.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import fields, models + + +class ProductTemplate(models.Model): + """Add brand field in product.template""" + _inherit = 'product.template' + + brand_id = fields.Many2one( + 'product.brand', string='Brand', help="Choose brand" + ) diff --git a/all_in_one_purchase_kit/models/purchase_order.py b/all_in_one_purchase_kit/models/purchase_order.py new file mode 100644 index 000000000..288d44c2e --- /dev/null +++ b/all_in_one_purchase_kit/models/purchase_order.py @@ -0,0 +1,262 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +import datetime +import calendar +from odoo import api, fields, models + + +class PurchaseOrder(models.Model): + """ Inherit purchase.order model and add fields and methods """ + _inherit = 'purchase.order' + + requisition_order = fields.Char( + string='Requisition Order', help='Requisition Order' + ) + company_currency_amount = fields.Float( + string='Company Currency Total', compute='_compute_amount', + help="Total amount in company currency" + ) + number_to_words = fields.Char( + string="Amount in Words (Total) : ", + compute='_compute_number_to_words', help="Total amount in words" + ) + + def _compute_amount(self): + """Total amount in company currency""" + for amount in self: + amount.company_currency_amount = self.env['res.currency']._compute( + amount.currency_id, amount.company_id.currency_id, + amount.amount_total) + + def _compute_number_to_words(self): + """Compute the amount to words in Purchase Order""" + for rec in self: + rec.number_to_words = rec.currency_id.amount_to_text( + rec.amount_total) + + def action_multi_confirm(self): + """Confirm multiple order by a single click""" + for order in self.env['purchase.order'].browse( + self.env.context.get('active_ids')).filtered( + lambda o: o.state in ['draft', 'sent']): + order.button_confirm() + + def action_multi_cancel(self): + """Cancel multiple order by a single click""" + for order in self.env['purchase.order'].browse( + self.env.context.get('active_ids')): + order.button_cancel() + + def button_confirm(self): + """The same order line merges when the confirmation button is + clicked""" + line_groups = {} + for line in self.order_line: + key = (line.product_id.id, line.price_unit) + line_groups.setdefault(key, []).append(line) + for lines in line_groups.values(): + if len(lines) > 1: + lines[0].product_qty = sum(line.product_qty for line in lines) + lines[0]._compute_amount() + for line in lines[1:]: + line.unlink() + res = super(PurchaseOrder, self).button_confirm() + return res + + @api.onchange('partner_id') + def _recompute_discount(self): + """Calculate the discount""" + self.order_line.calculate_discount_percentage() + + @api.model + def get_data(self): + """Get various counts and total amounts related to different states + of purchase-related records.""" + return{ + 'rfq': self.search_count([('state', '=', 'draft')]), + 'rfq_sent': self.search_count([('state', '=', 'sent')]), + 'rfq_to_approve': self.search_count([('state', '=', 'to approve')]), + 'purchase_order': self.search_count([('state', '=', 'purchase')]), + 'cancelled_order': self.search_count([('state', '=', 'cancel')]), + 'amount_total': sum(self.search([ + ('state', '=', 'purchase')]).mapped('amount_total')), + 'amount_rfq': sum(self.search([ + ('state', '=', 'draft')]).mapped('amount_total')), + } + + @api.model + def get_value(self, start_date, end_date): + """It is to pass values according to start and end date to the + dashboard.""" + if start_date and end_date: + rfq = self.search_count( + [('state', '=', 'draft'), ('date_order', '>=', start_date), + ('date_order', '<=', end_date)]) + rfq_sent = self.search_count( + [('state', '=', 'sent'), ('date_order', '>=', start_date), + ('date_order', '<=', end_date)]) + rfq_to_approve = self.search_count( + [('state', '=', 'to approve'), + ('date_order', '>=', start_date), + ('date_order', '<=', end_date)]) + purchase_order = self.search_count( + [('state', '=', 'purchase'), ('date_order', '>=', start_date), + ('date_order', '<=', end_date)]) + cancelled_order = self.search_count( + [('state', '=', 'cancel'), ('date_order', '>=', start_date), + ('date_order', '<=', end_date)]) + amount_total = sum(self.search([ + ('state', '=', 'purchase'), ('date_order', '>=', start_date), + ('date_order', '<=', end_date)]).mapped('amount_total')) + amount_rfq = sum(self.search([ + ('state', '=', 'draft'), ('date_order', '>=', start_date), + ('date_order', '<=', end_date)]).mapped('amount_total')) + elif start_date: + rfq = self.search_count([('state', '=', 'draft'), + ('date_order', '>=', start_date)]) + rfq_sent = self.search_count([('state', '=', 'sent'), + ('date_order', '>=', start_date)]) + rfq_to_approve = self.search_count( + [('state', '=', 'to approve'), + ('date_order', '>=', start_date), + ]) + purchase_order = self.search_count( + [('state', '=', 'purchase'), ('date_order', '>=', start_date)]) + cancelled_order = self.search_count( + [('state', '=', 'cancel'), ('date_order', '>=', start_date)]) + amount_total = sum(self.search([ + ('state', '=', 'purchase'), ('date_order', '>=', start_date) + ]).mapped('amount_total')) + amount_rfq = sum(self.search([ + ('state', '=', 'draft'), ('date_order', '>=', start_date) + ]).mapped('amount_total')) + elif end_date: + rfq = self.search_count( + [('state', '=', 'draft'), ('date_order', '<=', end_date)]) + rfq_sent = self.search_count( + [('state', '=', 'sent'), + ('date_order', '<=', end_date)]) + rfq_to_approve = self.search_count( + [('state', '=', 'to approve'), + ('date_order', '<=', end_date), + ]) + purchase_order = self.search_count( + [('state', '=', 'purchase'), ('date_order', '<=', end_date)]) + cancelled_order = self.search_count( + [('state', '=', 'cancel'), ('date_order', '<=', end_date)]) + amount_total = sum(self.search([ + ('state', '=', 'purchase'), ('date_order', '<=', end_date) + ]).mapped('amount_total')) + amount_rfq = sum(self.search([ + ('state', '=', 'draft'), ('date_order', '>=', start_date) + ]).mapped('amount_total')) + return { + 'rfq': rfq, + 'rfq_sent': rfq_sent, + 'rfq_to_approve': rfq_to_approve, + 'purchase_order': purchase_order, + 'cancelled_order': cancelled_order, + 'amount_total': amount_total, + 'amount_rfq': amount_rfq, + } + + @api.model + def get_current_month_purchase(self): + """Returns current month purchase""" + date = fields.Datetime.today() + start_date = datetime.datetime(date.year, date.month, 1) + purchase_order = self.search_count( + [('create_date', '<', date), ('create_date', '>', start_date), + ('state', '=', 'purchase')] + ) + current_month_count = { + calendar.month_name[date.month]: purchase_order + } + return{ + 'current_month_count': current_month_count + } + + @api.model + def get_monthly_purchase_order(self): + """Returns monthly purchase count data to the graph of dashboard""" + monthly_purchase = {} + purchase_order = self.search([('state', '=', 'purchase')]) + lst = [rec.create_date.month for rec in purchase_order] + for i in range(1, 13): + count = lst.count(i) + monthly_purchase.update({ + calendar.month_name[i]: count + }) + return { + 'monthly_purchase_count': monthly_purchase, + } + + @api.model + def get_monthly_order(self): + """Returns complete monthly data includes rfq, purchase order, + canceled order,to approve order etc. of to the graph of dashboard""" + monthly_count = {} + purchase_order = self.search([]) + lst = [rec.create_date.month for rec in purchase_order] + for i in range(1, 13): + count = lst.count(i) + monthly_count.update({ + calendar.month_name[i]: count + }) + return { + 'monthly_count': monthly_count, + } + + @api.model + def total_amount_spend(self): + """Returns total amount spend for purchase""" + total_amount = sum(self.search([ + ('state', '=', 'purchase')]).mapped('amount_total')) + return { + 'amount_total': total_amount + } + + def recommendation_wizard(self): + """Add data to wizard""" + orders = self.search([('partner_id', '=', self.partner_id.id)]) + pro_id = [] + for order in orders: + for product in order.order_line.product_id: + val = (0, 0, { + 'product_id': product.id, + 'available_qty': product.qty_available, + 'list_price': product.list_price, + 'qty_need': 0, + 'is_modified': False, + }) + if val not in pro_id: + pro_id.append(val) + res = { + 'type': 'ir.actions.act_window', + 'view_mode': 'form', + 'res_model': 'product.recommendation', + 'target': 'new', + 'context': { + 'default_line_ids': pro_id, + } + } + return res diff --git a/all_in_one_purchase_kit/models/purchase_order_line.py b/all_in_one_purchase_kit/models/purchase_order_line.py new file mode 100644 index 000000000..57c388490 --- /dev/null +++ b/all_in_one_purchase_kit/models/purchase_order_line.py @@ -0,0 +1,144 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import api, fields, models, _ +from odoo.exceptions import UserError + + +class PurchaseOrderLine(models.Model): + """Inherit purchase.order.line to add fields and methods""" + _inherit = 'purchase.order.line' + + product_image = fields.Binary( + related="product_id.image_1920", + string="Product Image", + help='For getting product image to purchase order line') + purchase_date = fields.Datetime( + comodel_name='purchase.order', related='order_id.date_order', store=True, + string='Purchase Date', help="Purchase Date" + ) + barcode_scan = fields.Char( + string='Product Barcode', + help="Here you can provide the barcode for the product") + discount = fields.Float( + string="Discount (%)", editable=True, help="Total Discount" + ) + _sql_constraints = [ + ( + "maximum_discount", + "CHECK (discount <= 100.0)", + "Discount must be lower than 100%.", + ) + ] + + @api.onchange('order_id') + def _onchange_order_id(self): + """ Restrict creating purchase order line for purchase order + in locked, cancel and purchase order states""" + if self.order_id.state in ['cancel', 'done', 'purchase']: + raise UserError(_("You cannot select purchase order in " + "cancel or locked or purchase order state")) + + def get_product_form(self): + """Get the product form""" + 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 + } + + @api.onchange('barcode_scan') + def _onchange_barcode_scan(self): + """Search the product with the barcode entered""" + if self.barcode_scan: + product = self.env['product.product'].search([ + ('barcode', '=', self.barcode_scan)]) + self.product_id = product.id + + @api.depends("discount") + def _compute_amount(self): + """Add discount""" + return super()._compute_amount() + + def _convert_to_tax_base_line_dict(self): + """Update price unit""" + vals = super()._convert_to_tax_base_line_dict() + vals.update({"price_unit": self._get_discounted_price()}) + return vals + + @api.onchange('product_id') + def calculate_discount_percentage(self): + """Calculate the discount percentage""" + vendor = self.order_id.partner_id + sellers = self.product_id.product_tmpl_id.seller_ids + for rec in sellers: + if rec.partner_id.id == vendor.id: + if rec.discount: + self.write({'discount': rec.discount}) + self.update({'price_unit': rec.price}) + break + elif rec.partner_id.id != vendor.id: + self.update({'discount': vendor.default_discount}) + break + else: + self.write({'discount': None}) + + @api.depends('discount') + def _get_discounted_price(self): + """Returns discounted price""" + self.ensure_one() + if self.discount: + return self.price_unit * (1 - self.discount / 100) + return self.price_unit + + def _prepare_account_move_line(self, move=False): + """Discount in account.move.line""" + sup = super(PurchaseOrderLine, self)._prepare_account_move_line(move) + sup.update({'discount': self.discount}) + return sup + + def add_catalog_control(self): + """Method to call product.product model when click on catalog + button in purchase order line""" + 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', + } + + def action_purchase_order(self): + """Method action_purchase_order to return the form view of the + model purchase.order""" + return { + 'type': 'ir.actions.act_window', + 'name': _('Purchase Order'), + 'res_id': self.order_id.id, + 'res_model': 'purchase.order', + 'view_mode': 'form', + 'target': 'current', + } diff --git a/all_in_one_purchase_kit/models/purchase_report.py b/all_in_one_purchase_kit/models/purchase_report.py new file mode 100644 index 000000000..2d17dedf1 --- /dev/null +++ b/all_in_one_purchase_kit/models/purchase_report.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import fields, models + + +class PurchaseReport(models.Model): + """Inherit model to add fields and methods""" + _inherit = 'purchase.report' + + brand_id = fields.Many2one( + 'product.brand', string='Brand', help='Select brand of the product' + ) + + def _select(self): + """Add filter in pivot view""" + res = super(PurchaseReport, self)._select() + query = res.split('t.categ_id as category_id,', 1) + res = query[0] + 't.categ_id as category_id,t.brand_id' \ + ' as brand_id,' + query[1] + return res + + def _group_by(self): + """Add the group by in pivot view""" + res = super(PurchaseReport, self)._group_by() + query = res.split('t.categ_id,', 1) + res = query[0] + 't.categ_id,t.brand_id,' + query[1] + return res diff --git a/all_in_one_purchase_kit/models/requisition_order.py b/all_in_one_purchase_kit/models/requisition_order.py new file mode 100644 index 000000000..903ac5cad --- /dev/null +++ b/all_in_one_purchase_kit/models/requisition_order.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import api, fields, models + + +class RequisitionOrder(models.Model): + """Model for requisition order""" + _name = 'requisition.order' + _description = 'Requisition order' + + requisition_product_id = fields.Many2one( + 'employee.purchase.requisition', string="Requisition Product", + help='Requisition product.') + state = fields.Selection( + string='State', related='requisition_product_id.state', + help="Requisition State") + requisition_type = fields.Selection( + string='Requisition Type', + selection=[ + ('purchase_order', 'Purchase Order'), + ('internal_transfer', 'Internal Transfer')], + help='Type of requisition') + product_id = fields.Many2one( + 'product.product', required=True, string="Product", + help='Select Product') + description = fields.Text( + string="Description", + compute='_compute_product_id', + store=True, readonly=False, + precompute=True, help='Product Description') + quantity = fields.Integer(string='Quantity', help='Quantity') + uom = fields.Char( + related='product_id.uom_id.name', string='Unit of Measure', + help='Product Uom') + partner_ids = fields.Many2many('res.partner', + compute='_compute_requisition_type') + partner_id = fields.Many2one( + 'res.partner', string='Vendor', + help='Vendor for the requisition', readonly=False, ) + + @api.depends('product_id') + def _compute_product_id(self): + """Compute product description '[("id", "in", [13, 66, 65, 51] )]'""" + for option in self: + if not option.product_id: + continue + product_lang = option.product_id.with_context( + lang=self.requisition_product_id.employee_id.lang) + option.description = product_lang.get_product_multiline_description_sale() + + @api.depends('requisition_type', 'product_id') + def _compute_requisition_type(self): + """Fetching product vendors""" + self.partner_ids = [data.partner_id.id for data in + self.product_id.seller_ids] diff --git a/all_in_one_purchase_kit/models/res_config_settings.py b/all_in_one_purchase_kit/models/res_config_settings.py new file mode 100644 index 000000000..f1f39e907 --- /dev/null +++ b/all_in_one_purchase_kit/models/res_config_settings.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import api, fields, models + + +class ResConfigSettings(models.TransientModel): + """Add field in res.config.settings""" + _inherit = 'res.config.settings' + + show_product_image_in_report_purchase = fields.Boolean( + string="Show Product Image", + config_parameter='all_in_one_purchase_kit.show_product_image_in_report_purchase', + help="Enable this field to Print image in report") diff --git a/all_in_one_purchase_kit/models/res_partner.py b/all_in_one_purchase_kit/models/res_partner.py new file mode 100644 index 000000000..d8fc49c0c --- /dev/null +++ b/all_in_one_purchase_kit/models/res_partner.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import api, fields, models + + +class ResPartner(models.Model): + """Inheriting res partner to add fields and methods""" + _inherit = 'res.partner' + + default_discount = fields.Float(string='Discount(%)', + help="Enter discount amount in %") + _sql_constraints = [ + ( + "maximum_discount", + "CHECK (discount <= 100.0)", + "Discount must be lower than 100%.", + ) + ] + + @api.model + def get_vendor_po(self): + """Get purchase order of vendors""" + count_dict = { + count['name']: count['purchase_order_count'] + for count in self.search_read( + [], ['name', 'purchase_order_count'], + order='purchase_order_count') + if count['purchase_order_count'] > 0 + } + return {'purchase_order_count': {key: val for key, val in sorted( + count_dict.items(), key=lambda ele: ele[1], reverse=True)}} diff --git a/all_in_one_purchase_kit/models/stock_picking.py b/all_in_one_purchase_kit/models/stock_picking.py new file mode 100644 index 000000000..1b5404bcb --- /dev/null +++ b/all_in_one_purchase_kit/models/stock_picking.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import fields, models + + +class StockPicking(models.Model): + """ + Inherit stock.picking model and add field requisition order in + stock picking + """ + _inherit = 'stock.picking' + + requisition_order = fields.Char( + string='Requisition Order', help='Requisition Order' + ) diff --git a/all_in_one_purchase_kit/report/__init__.py b/all_in_one_purchase_kit/report/__init__.py new file mode 100644 index 000000000..6431e3ea7 --- /dev/null +++ b/all_in_one_purchase_kit/report/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from . import purchase_order_report diff --git a/all_in_one_purchase_kit/report/all_in_one_purchase_kit_report_views.xml b/all_in_one_purchase_kit/report/all_in_one_purchase_kit_report_views.xml new file mode 100644 index 000000000..baed7f46d --- /dev/null +++ b/all_in_one_purchase_kit/report/all_in_one_purchase_kit_report_views.xml @@ -0,0 +1,11 @@ + + + + + Material Purchase Requisition Report + employee.purchase.requisition + qweb-pdf + all_in_one_purchase_kit.report_purchase_requisition + all_in_one_purchase_kit.report_purchase_requisition + + diff --git a/all_in_one_purchase_kit/report/dynamic_purchase_report_action.xml b/all_in_one_purchase_kit/report/dynamic_purchase_report_action.xml new file mode 100644 index 000000000..dc911b789 --- /dev/null +++ b/all_in_one_purchase_kit/report/dynamic_purchase_report_action.xml @@ -0,0 +1,11 @@ + + + + + Purchase All In One Report + dynamic.purchase.report + qweb-pdf + all_in_one_purchase_kit.purchase_order_report + all_in_one_purchase_kit.purchase_order_report + + diff --git a/all_in_one_purchase_kit/report/purchase_order_report.py b/all_in_one_purchase_kit/report/purchase_order_report.py new file mode 100644 index 000000000..5452c1fbe --- /dev/null +++ b/all_in_one_purchase_kit/report/purchase_order_report.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Mohamed Muzammil VP (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 . +# +############################################################################### +from odoo import api, models + + +class PurchaseOrderReport(models.AbstractModel): + """Model to get value for the report""" + _name = 'report.all_in_one_purchase_kit.purchase_order_report' + + @api.model + def _get_report_values(self, docids, data=None): + """Get values for the report""" + if self.env.context.get('purchase_order_report') and\ + data.get('report_data'): + data.update( + { + 'report_main_line_data': + data.get('report_data')['report_lines'], + 'Filters': data.get('report_data')['filters'], + 'company': self.env.company + } + ) + return data diff --git a/all_in_one_purchase_kit/report/purchase_order_report_templates.xml b/all_in_one_purchase_kit/report/purchase_order_report_templates.xml new file mode 100644 index 000000000..1d317ddcd --- /dev/null +++ b/all_in_one_purchase_kit/report/purchase_order_report_templates.xml @@ -0,0 +1,427 @@ + + + + + + + + + + + + + + + + + + + diff --git a/all_in_one_purchase_kit/report/purchase_order_templates.xml b/all_in_one_purchase_kit/report/purchase_order_templates.xml new file mode 100644 index 000000000..37031a357 --- /dev/null +++ b/all_in_one_purchase_kit/report/purchase_order_templates.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/all_in_one_purchase_kit/report/purchase_requisition_templates.xml b/all_in_one_purchase_kit/report/purchase_requisition_templates.xml new file mode 100644 index 000000000..9c78b6669 --- /dev/null +++ b/all_in_one_purchase_kit/report/purchase_requisition_templates.xml @@ -0,0 +1,206 @@ + + + + + diff --git a/all_in_one_purchase_kit/security/all_in_one_purchase_kit_groups.xml b/all_in_one_purchase_kit/security/all_in_one_purchase_kit_groups.xml new file mode 100644 index 000000000..dd310253a --- /dev/null +++ b/all_in_one_purchase_kit/security/all_in_one_purchase_kit_groups.xml @@ -0,0 +1,30 @@ + + + + Employee Purchase Requisition + User access level for Material Request + module + + 20 + + + + + Requisition Users + + + + + Department Head + + + + + + Requisition Manager + + + + diff --git a/all_in_one_purchase_kit/security/all_in_one_purchase_kit_security.xml b/all_in_one_purchase_kit/security/all_in_one_purchase_kit_security.xml new file mode 100644 index 000000000..81d832aba --- /dev/null +++ b/all_in_one_purchase_kit/security/all_in_one_purchase_kit_security.xml @@ -0,0 +1,34 @@ + + + + + + Requisition User Rule + + [('confirm_id', '=', user.id)] + + + + + Department Head Rule + + [('user_id','=',user.id)] + + + + + Requisition Manager Rule + + [(1,'=',1)] + + + + + Purchase Requisition Company Rule + + [('company_id', '=', company_id)] + + diff --git a/all_in_one_purchase_kit/security/ir.model.access.csv b/all_in_one_purchase_kit/security/ir.model.access.csv new file mode 100644 index 000000000..7d4431178 --- /dev/null +++ b/all_in_one_purchase_kit/security/ir.model.access.csv @@ -0,0 +1,9 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_product_brand_user,access.product.brand.user,model_product_brand,base.group_user,1,1,1,1 +access_employee_purchase_requisition_manager,access.employee.purchase.requisition.manager,model_employee_purchase_requisition,all_in_one_purchase_kit.employee_requisition_manager,1,1,1,1 +access_employee_purchase_requisition_head,access.employee.purchase.requisition.head,model_employee_purchase_requisition,all_in_one_purchase_kit.employee_requisition_head,1,1,1,1 +access_employee_purchase_requisition_user,access.employee.purchase.requisition.user,model_employee_purchase_requisition,all_in_one_purchase_kit.employee_requisition_user,1,1,1,1 +access_requisition_order_user,access.requisition.order.user,model_requisition_order,base.group_user,1,1,1,1 +access_dynamic_purchase_report_user,access.dynamic.purchase.report.user,model_dynamic_purchase_report,base.group_user,1,1,1,1 +access_product_recommendation_user,access.product.recommendation.user,model_product_recommendation,base.group_user,1,1,1,1 +access_product_recommendation_line_user,access.product.recommendation.line.user,model_product_recommendation_line,base.group_user,1,1,1,1 diff --git a/all_in_one_purchase_kit/static/description/assets/icons/check.png b/all_in_one_purchase_kit/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/check.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/chevron.png b/all_in_one_purchase_kit/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/chevron.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/cogs.png b/all_in_one_purchase_kit/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/cogs.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/consultation.png b/all_in_one_purchase_kit/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/consultation.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/ecom-black.png b/all_in_one_purchase_kit/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/ecom-black.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/education-black.png b/all_in_one_purchase_kit/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/education-black.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/hotel-black.png b/all_in_one_purchase_kit/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/hotel-black.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/license.png b/all_in_one_purchase_kit/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/license.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/lifebuoy.png b/all_in_one_purchase_kit/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/lifebuoy.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/manufacturing-black.png b/all_in_one_purchase_kit/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/manufacturing-black.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/pos-black.png b/all_in_one_purchase_kit/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/pos-black.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/puzzle.png b/all_in_one_purchase_kit/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/puzzle.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/restaurant-black.png b/all_in_one_purchase_kit/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/restaurant-black.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/service-black.png b/all_in_one_purchase_kit/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/service-black.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/trading-black.png b/all_in_one_purchase_kit/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/trading-black.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/training.png b/all_in_one_purchase_kit/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/training.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/update.png b/all_in_one_purchase_kit/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/update.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/user.png b/all_in_one_purchase_kit/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/user.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/icons/wrench.png b/all_in_one_purchase_kit/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/icons/wrench.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/categories.png b/all_in_one_purchase_kit/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/categories.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/check-box.png b/all_in_one_purchase_kit/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/check-box.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/compass.png b/all_in_one_purchase_kit/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/compass.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/corporate.png b/all_in_one_purchase_kit/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/corporate.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/customer-support.png b/all_in_one_purchase_kit/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/customer-support.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/cybrosys-logo.png b/all_in_one_purchase_kit/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/cybrosys-logo.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/features.png b/all_in_one_purchase_kit/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/features.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/logo.png b/all_in_one_purchase_kit/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/logo.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/pictures.png b/all_in_one_purchase_kit/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/pictures.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/pie-chart.png b/all_in_one_purchase_kit/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/pie-chart.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/right-arrow.png b/all_in_one_purchase_kit/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/right-arrow.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/star.png b/all_in_one_purchase_kit/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/star.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/support.png b/all_in_one_purchase_kit/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/support.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/misc/whatsapp.png b/all_in_one_purchase_kit/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/misc/whatsapp.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/modules/1.png b/all_in_one_purchase_kit/static/description/assets/modules/1.png new file mode 100644 index 000000000..3de38979f Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/modules/1.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/modules/2.png b/all_in_one_purchase_kit/static/description/assets/modules/2.png new file mode 100644 index 000000000..19de058d1 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/modules/2.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/modules/3.png b/all_in_one_purchase_kit/static/description/assets/modules/3.png new file mode 100644 index 000000000..0cc9efd4a Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/modules/3.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/modules/4.png b/all_in_one_purchase_kit/static/description/assets/modules/4.png new file mode 100644 index 000000000..4f9e87f6e Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/modules/4.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/modules/5.png b/all_in_one_purchase_kit/static/description/assets/modules/5.png new file mode 100644 index 000000000..b80a7a99b Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/modules/5.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/modules/6.png b/all_in_one_purchase_kit/static/description/assets/modules/6.png new file mode 100644 index 000000000..d7e97170c Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/modules/6.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/1.png b/all_in_one_purchase_kit/static/description/assets/screenshots/1.png new file mode 100644 index 000000000..02c30da58 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/1.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/10.png b/all_in_one_purchase_kit/static/description/assets/screenshots/10.png new file mode 100644 index 000000000..5d3ce1908 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/10.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/11.png b/all_in_one_purchase_kit/static/description/assets/screenshots/11.png new file mode 100644 index 000000000..58e28d002 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/11.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/12.png b/all_in_one_purchase_kit/static/description/assets/screenshots/12.png new file mode 100644 index 000000000..c4e879e5c Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/12.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/13.png b/all_in_one_purchase_kit/static/description/assets/screenshots/13.png new file mode 100644 index 000000000..348cbae7a Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/13.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/14.png b/all_in_one_purchase_kit/static/description/assets/screenshots/14.png new file mode 100644 index 000000000..aed29c078 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/14.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/15.png b/all_in_one_purchase_kit/static/description/assets/screenshots/15.png new file mode 100644 index 000000000..9af7c0e2d Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/15.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/16.png b/all_in_one_purchase_kit/static/description/assets/screenshots/16.png new file mode 100644 index 000000000..00c862105 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/16.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/17.png b/all_in_one_purchase_kit/static/description/assets/screenshots/17.png new file mode 100644 index 000000000..dcdf5bf87 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/17.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/18.png b/all_in_one_purchase_kit/static/description/assets/screenshots/18.png new file mode 100644 index 000000000..a8ac26fb1 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/18.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/19.png b/all_in_one_purchase_kit/static/description/assets/screenshots/19.png new file mode 100644 index 000000000..710f0784f Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/19.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/2.png b/all_in_one_purchase_kit/static/description/assets/screenshots/2.png new file mode 100644 index 000000000..52c4fe2f3 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/2.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/20.png b/all_in_one_purchase_kit/static/description/assets/screenshots/20.png new file mode 100644 index 000000000..f3d8521ec Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/20.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/21.png b/all_in_one_purchase_kit/static/description/assets/screenshots/21.png new file mode 100644 index 000000000..63d23e921 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/21.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/22.png b/all_in_one_purchase_kit/static/description/assets/screenshots/22.png new file mode 100644 index 000000000..c703427ab Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/22.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/23.png b/all_in_one_purchase_kit/static/description/assets/screenshots/23.png new file mode 100644 index 000000000..58155e2e5 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/23.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/24.png b/all_in_one_purchase_kit/static/description/assets/screenshots/24.png new file mode 100644 index 000000000..e136ec911 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/24.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/25.png b/all_in_one_purchase_kit/static/description/assets/screenshots/25.png new file mode 100644 index 000000000..949a2c2d8 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/25.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/26.png b/all_in_one_purchase_kit/static/description/assets/screenshots/26.png new file mode 100644 index 000000000..4a40c8add Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/26.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/27.png b/all_in_one_purchase_kit/static/description/assets/screenshots/27.png new file mode 100644 index 000000000..39ae8804d Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/27.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/28.png b/all_in_one_purchase_kit/static/description/assets/screenshots/28.png new file mode 100644 index 000000000..d93d9e447 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/28.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/29.png b/all_in_one_purchase_kit/static/description/assets/screenshots/29.png new file mode 100644 index 000000000..bcb6176a6 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/29.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/3.png b/all_in_one_purchase_kit/static/description/assets/screenshots/3.png new file mode 100644 index 000000000..daf0b2a42 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/3.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/30.png b/all_in_one_purchase_kit/static/description/assets/screenshots/30.png new file mode 100644 index 000000000..9e148b562 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/30.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/31.png b/all_in_one_purchase_kit/static/description/assets/screenshots/31.png new file mode 100644 index 000000000..4d20c400a Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/31.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/32.png b/all_in_one_purchase_kit/static/description/assets/screenshots/32.png new file mode 100644 index 000000000..af9e6db65 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/32.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/33.png b/all_in_one_purchase_kit/static/description/assets/screenshots/33.png new file mode 100644 index 000000000..cd71726c9 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/33.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/34.png b/all_in_one_purchase_kit/static/description/assets/screenshots/34.png new file mode 100644 index 000000000..d8a592026 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/34.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/35.png b/all_in_one_purchase_kit/static/description/assets/screenshots/35.png new file mode 100644 index 000000000..dbe5f1cb8 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/35.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/36.png b/all_in_one_purchase_kit/static/description/assets/screenshots/36.png new file mode 100644 index 000000000..1f7198ac8 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/36.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/37.png b/all_in_one_purchase_kit/static/description/assets/screenshots/37.png new file mode 100644 index 000000000..e6c1ad54e Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/37.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/4.png b/all_in_one_purchase_kit/static/description/assets/screenshots/4.png new file mode 100644 index 000000000..9af7acd6f Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/4.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/5.png b/all_in_one_purchase_kit/static/description/assets/screenshots/5.png new file mode 100644 index 000000000..6a6fe7a13 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/5.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/6.png b/all_in_one_purchase_kit/static/description/assets/screenshots/6.png new file mode 100644 index 000000000..bf259175c Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/6.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/7.png b/all_in_one_purchase_kit/static/description/assets/screenshots/7.png new file mode 100644 index 000000000..5185030d0 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/7.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/8.png b/all_in_one_purchase_kit/static/description/assets/screenshots/8.png new file mode 100644 index 000000000..3c4a8e3fd Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/8.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/9.png b/all_in_one_purchase_kit/static/description/assets/screenshots/9.png new file mode 100644 index 000000000..e0506a635 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/9.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/excel1.png b/all_in_one_purchase_kit/static/description/assets/screenshots/excel1.png new file mode 100644 index 000000000..db71857cf Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/excel1.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/hero.gif b/all_in_one_purchase_kit/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..d3da68868 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/hero.gif differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/pdf1.png b/all_in_one_purchase_kit/static/description/assets/screenshots/pdf1.png new file mode 100644 index 000000000..fcf6bd2af Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/pdf1.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/rq1.png b/all_in_one_purchase_kit/static/description/assets/screenshots/rq1.png new file mode 100644 index 000000000..bbb1de3c4 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/rq1.png differ diff --git a/all_in_one_purchase_kit/static/description/assets/screenshots/rq2.png b/all_in_one_purchase_kit/static/description/assets/screenshots/rq2.png new file mode 100644 index 000000000..4ba848450 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/assets/screenshots/rq2.png differ diff --git a/all_in_one_purchase_kit/static/description/banner.jpg b/all_in_one_purchase_kit/static/description/banner.jpg new file mode 100644 index 000000000..56fbe5ac7 Binary files /dev/null and b/all_in_one_purchase_kit/static/description/banner.jpg differ diff --git a/all_in_one_purchase_kit/static/description/icon.png b/all_in_one_purchase_kit/static/description/icon.png new file mode 100644 index 000000000..44fd84b3f Binary files /dev/null and b/all_in_one_purchase_kit/static/description/icon.png differ diff --git a/all_in_one_purchase_kit/static/description/index.html b/all_in_one_purchase_kit/static/description/index.html new file mode 100644 index 000000000..5a935df00 --- /dev/null +++ b/all_in_one_purchase_kit/static/description/index.html @@ -0,0 +1,1261 @@ +
+ +
+ +
+
+ Community +
+
+ Enterprise +
+
+ Odoo.sh +
+
+
+ +
+
+
+ +

+ ALL IN ONE PURCHASE KIT +

+

+ Get the Complete Features for Purchase. +

+ + +
+
+
+
+ +
+
+ +
+

+ Explore This + Module +

+
+ + + +
+
+ +
+

+ Overview +

+
+
+
+ This module combines a verity of Purchase features like, Product Brand for products,Purchase Order Line View,Company Currency Total in Purchase, + Employee Purchase Requisition,Purchase All In One Report Generator,Previous Purchase Product Rates,Barcode scanning support for Purchase, + Amount in Words in Invoice for Purchase Order,Multiple Purchase Order Confirm And Cancel,Merge Same Product Line,Product image in order-line, + Purchase discount from Purchase order line,Product Recommendation etc... +
+
+ + +
+
+ +
+

+ Features +

+
+
+
+
+ + Community & + Enterprise Support. +
+
+ + Feature Packed Purchase Kit +
+
+ + Amount in Company Currency. +
+
+ + Employee + purchase requisition. +
+
+
+
+ + Amount in Words. +
+
+ + Scan Barcode to add Products in Order Line. +
+
+ + Confirm or Cancel Multiple Orders. +
+
+ + Product Brand. +
+
+ + Purchase Line View. +
+
+ + Merge Duplicate Order Line. +
+
+ + Image in Order Line and Report. +
+
+ + Purchase Report. +
+
+ + See the Purchase History. +
+
+ + Vendor Purchase Discount. +
+
+ + Product Recommendation in Purchase Order. +
+
+
+ + +
+
+ +
+

+ Screenshots +

+
+
+
+
+

+ Dashboard +

+

+ You may view some information about Purchase Orders here. +

+ + + +
+
+
+
+
+
+

+ Purchase Order Line and RFQ Line +

+

+ Select the Purchase Order Line to see all the Order Lines in + Purchase Order State +

+

+ Select the RFQ Line to see all the Order Lines in RFQ State +

+ + + +
+
+
+
+
+
+

+ Brand +

+

+ Can Create Brands for Products from here and also can see all + Brands created. +

+

+ Add Brand Name add Corresponding Brand Products. +

+

+ Users can add Product Brand from product's form view. +

+ + + +
+
+
+
+
+
+

+ Report +

+

+ Reporting-->Purchase Report +

+

+ Users can filter the Report and can Print Report in PDF or + Excel format. +

+ + + +
+
+
+
+
+
+

+ Purchase Requisition +

+

+ Give access to the Purchase Requisition. +

+

+ Users can create Purchase Requisition. +

+

+ Fill the data for Requisition and Confirm it. +

+

+ The Department can Approve or Reject the Requisition. +

+

+ After that wait for the Head Approval, Head can Approve or + Reject the Requisition +

+

+ After Approval, User can Create Purchase Order +

+

+ Go to Employees --> Select Purchase Requisition Settings, + Select the destination location + where the Product needs to + deliver for the employee +

+ + + +
+
+
+
+
+
+

+ Purchase History +

+

+ Click on the Button marked. +

+

+ Click the Previous Purchase Rates button. +

+

+ Users can see the Previous Price History. +

+ + + +
+
+
+
+
+
+

+ Barcode +

+

+ Add Barcode for Product +

+

+ Scan Barcode in Purchase Order Product Line. +

+ + + +
+
+
+
+
+
+

+ Add from Catalog +

+

+ Add Multiple Products easily to Order Line +

+ + + +
+
+
+
+
+
+

+ Show Product Image +

+

+ Enable the field to view Product Image in the Report +

+ + + +
+
+
+
+
+
+

+ Recommended Products +

+

+ Click On RECOMMENDED PRODUCTS +

+

+ Wizard Shows the Recommended Products +

+

+ Click On the Add Button to add Product to the Order Line +

+

+ Zero quantity product is not added to the Order Line +

+ + + +
+
+
+
+
+
+

+ Features +

+

+ Discount in Product line/default discount in Vendor, Confirm or + Cancel Multiple RFQ or Purchase Order, + Merge Duplicate Order Lines, Total in company currency, +

+ + + +
+
+
+ + +
+
+ +
+

+ Suggested + Products +

+
+
+
+ +
+
+ + +
+
+ +
+

+ Our Services +

+
+
+
+
+
+ +
+
+ Odoo + Customization +
+
+
+
+ +
+
+ Odoo + Implementation +
+
+
+
+ +
+
+ Odoo + Support +
+
+
+
+ +
+
+ Hire + Odoo + Developer +
+
+
+
+ +
+
+ Odoo + Integration +
+
+
+
+ +
+
+ Odoo + Migration +
+
+
+
+ +
+
+ Odoo + Consultancy +
+
+
+
+ +
+
+ Odoo + Implementation +
+
+
+
+ +
+
+ Odoo + Licensing Consultancy +
+
+
+
+ + +
+
+ +
+

+ Our + Industries +

+
+
+
+
+
+ +
+ Trading +
+

+ Easily procure + and + sell your products +

+
+
+
+
+ +
+ POS +
+

+ Easy + configuration + and convivial experience +

+
+
+
+
+ +
+ Education +
+

+ A platform for + educational management +

+
+
+
+
+ +
+ Manufacturing +
+

+ Plan, track and + schedule your operations +

+
+
+
+
+ +
+ E-commerce & Website +
+

+ Mobile + friendly, + awe-inspiring product pages +

+
+
+
+
+ +
+ Service Management +
+

+ Keep track of + services and invoice +

+
+
+
+
+ +
+ Restaurant +
+

+ Run your bar or + restaurant methodically +

+
+
+
+
+ +
+ Hotel Management +
+

+ An + all-inclusive + hotel management application +

+
+
+
+
+ + +
+
+ +
+

+ Support +

+
+
+
+
+
+
+ +
+
+

Need Help?

+

Got questions or need help? + Get in touch. +

+ +

+ odoo@cybrosys.com +

+
+
+
+
+
+
+
+ +
+
+

WhatsApp

+

Say hi to us on WhatsApp!

+ +

+ +91 86068 + 27707 +

+
+
+
+
+
+
+
+ +
+
+
+ \ No newline at end of file diff --git a/all_in_one_purchase_kit/static/src/css/purchase_report.css b/all_in_one_purchase_kit/static/src/css/purchase_report.css new file mode 100644 index 000000000..091a2ecdd --- /dev/null +++ b/all_in_one_purchase_kit/static/src/css/purchase_report.css @@ -0,0 +1,136 @@ +.time_range_pr { + width: 125px; + border: 2px solid #ccc; + border-radius: 5px; + padding: 10px; + +} +.apply_sale { + margin-right: 5px; + padding: 4px; +} +#apply_filter { + margin-right: 25px; +} +#pdf, #xlsx, #apply_filter { + color: white; + background-color: #7c7bad; + border-color: #7c7bad; +} +a.dropdown-toggle.report-type { + margin: 10px; +} +.search-Result-Selection { + border: 2px solid #ccc; + max-width: 360px; + min-width: 250px; + margin-right: 10px; + margin-left: 10px; + border-radius: 5px; + min-height: 40px; +} +.search-Result-Selection:hover{ + border:2px solid #eaeaea; +} +.dropdown-togglereport-type{ + min-height: 40px; + padding-top: 10px; +} +.low_case, #report_res { + text-transform: capitalize; + text-align: center; +} +#report_res{ + padding-right: 3px; +} +.print-btns { + margin-bottom: 30px; +} +.table_pr_head { + background-color: #7c7bad; + color: #fff; + padding: 20px; + margin: 20px; + height: 57px; + width: 100%; + border: 1px solid #000; +} +tr.pr-line { + height: 48px; +} +tr.table_pr_head th { + font-size: 18px; + text-align: center; +} +.table_view_pr { + overflow-y: scroll; + position: relative; + height: 500px; + max-width: 100%; +} +.my_custom_dropdown{ + min-width:200px; + height:150px; + padding: 20px; +} +.my_custom_dropdown input{ + height:25px; +} +.report_type{ + min-height: 100px; + min-width: 150px; + padding: 30px 10px 10px; +} +.sub_container_right, .print-btns { + display: flex; + justify-content: space-around; + align-items: center; +} +@media screen and (max-width: 768px) { + .sub_container_right, .print-btns { + flex-flow: column; + align-items: center; + } + .sub_container_left { + order: 2; + margin: 0; + } + .sub_container_right { + flex-flow: row; + margin-bottom: 10px; + flex-wrap: wrap !important; + width: 100%; + } +} +@media screen and (max-width: 576px) { + .apply_filter { + width: 100%; + position: relative; + } + #apply_filter { + position: absolute; + margin: 30px 0 0; + top: 50%; + left: 50%; + -ms-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + } + #date_chose { + margin-bottom: 15px; + } + .search-Result-Selection { + text-align: center; + } + .sub_container_left { + order: 2; + display: flex; + margin-top: 50px; + width: 100%; + justify-content: center; + align-items: center; + flex-wrap: wrap !important; + } + .sub_container_right { + flex-direction: column; + } +} diff --git a/all_in_one_purchase_kit/static/src/img/cancelled_order.png b/all_in_one_purchase_kit/static/src/img/cancelled_order.png new file mode 100644 index 000000000..d1eb2a230 Binary files /dev/null and b/all_in_one_purchase_kit/static/src/img/cancelled_order.png differ diff --git a/all_in_one_purchase_kit/static/src/img/purchase_order.png b/all_in_one_purchase_kit/static/src/img/purchase_order.png new file mode 100644 index 000000000..339b6cd61 Binary files /dev/null and b/all_in_one_purchase_kit/static/src/img/purchase_order.png differ diff --git a/all_in_one_purchase_kit/static/src/img/rfq.png b/all_in_one_purchase_kit/static/src/img/rfq.png new file mode 100644 index 000000000..c4829585c Binary files /dev/null and b/all_in_one_purchase_kit/static/src/img/rfq.png differ diff --git a/all_in_one_purchase_kit/static/src/img/rfq_sent.png b/all_in_one_purchase_kit/static/src/img/rfq_sent.png new file mode 100644 index 000000000..da473517b Binary files /dev/null and b/all_in_one_purchase_kit/static/src/img/rfq_sent.png differ diff --git a/all_in_one_purchase_kit/static/src/img/rfq_to_approve.png b/all_in_one_purchase_kit/static/src/img/rfq_to_approve.png new file mode 100644 index 000000000..8d082132d Binary files /dev/null and b/all_in_one_purchase_kit/static/src/img/rfq_to_approve.png differ diff --git a/all_in_one_purchase_kit/static/src/js/PurchaseDashboard.js b/all_in_one_purchase_kit/static/src/js/PurchaseDashboard.js new file mode 100644 index 000000000..33f5e1dbd --- /dev/null +++ b/all_in_one_purchase_kit/static/src/js/PurchaseDashboard.js @@ -0,0 +1,403 @@ +/** @odoo-module **/ +var AbstractAction = require('web.AbstractAction'); +var core = require('web.core'); +var QWeb = core.qweb; +var session = require('web.session'); +var rpc = require('web.rpc'); +const Dialog = require('web.Dialog'); +var self = this; +var DashBoard = AbstractAction.extend({ + /*The template name used to render the dashboard content.*/ + contentTemplate: 'DashboardDashboard', + events: { + 'click .rfq': 'on_dashboard_rfq_action', + 'click .rfq_sent': 'on_dashboard_rfq_sent_action', + 'click .rfq_to_approve': 'on_dashboard_to_rfq_approve_action', + 'click .purchase_order': 'on_dashboard_my_purchase_order_action', + 'click .cancelled_order': 'on_dashboard_rfq_cancel_action', + 'change #start_date': function (e) { + /*This function works on change of start date.*/ + e.stopPropagation(); + var $target = $(e.target); + var values = $target.val(); + this.onClick_this_values($target.val()); + }, + 'change #end_date': function (e) { + /*This function works on change of end date.*/ + e.stopPropagation(); + var $target = $(e.target); + var values = $target.val(); + this.onClick_this_values($target.val()); + }, + }, + /** + * Initializes the DashBoard widget. + */ + init: function (parent, context) { + this._super(parent, context); + this.dashboards_templates = ['MainSection']; + }, + /*Rendering each graph at the start*/ + start: function () { + self = this; + self.set("title", 'Dashboard'); + return self._super().then(function () { + self.render_dashboards(); + self.render_vendor_product_graph(); + self.render_product_purchase_graph(); + self.render_current_month_purchase_graph(); + self.render_monthly_purchase_count_graph(); + self.render_monthly_count_graph(); + }); + }, + /*WillStart function - executed before the widget starts*/ + willStart: function () { + return this._super() + }, + /** + * Renders the dashboards by fetching data and appending templates to the DOM. + */ + render_dashboards: function () { + self = this; + self.fetch_data() + var templates = [] + var templates = ['MainSection']; + _.each(templates, function (template) { + self.$('.o_hr_dashboard').append(QWeb.render(template, { widget: self })) + }); + }, + /*Fetch data from model purchase order*/ + fetch_data: function () { + self = this + var def1 = self._rpc({ + model: 'purchase.order', + method: "get_data", + }).then(function (result) { + self.$('#rfq').append('' + result.rfq + ''); + self.$('#rfq_sent').append('' + result.rfq_sent + ''); + self.$('#rfq_to_approve').append('' + result.rfq_to_approve + ''); + self.$('#purchase_order').append('' + result.purchase_order + ''); + self.$('#cancelled_order').append('' + result.cancelled_order + ''); + self.$('#total_spend').append('' + result.amount_total + ''); + self.$('#amount_rfq').append('' + result.amount_rfq + ''); + }); + }, + /*This is to get rfq data according to the filters.*/ + on_dashboard_rfq_action: function (ev) { + var start_date = $('#start_date').val() + var end_date = $('#end_date').val() + if (start_date && end_date) { + var domain = [['user_id', '=', session.uid], ['state', '=', 'draft'], ['date_order', '>=', start_date], ['date_order', '<=', end_date]] + } + else if (start_date) { + var domain = [['user_id', '=', session.uid], ['state', '=', 'draft'], ['date_order', '>=', start_date]] + } + else if (end_date) { + var domain = [['user_id', '=', session.uid], ['state', '=', 'draft'], ['date_order', '<=', end_date]] + } + else { + var domain = [['user_id', '=', session.uid], ['state', '=', 'draft']] + } + this.do_action({ + type: 'ir.actions.act_window', + name: 'RFQ', + res_model: 'purchase.order', + views: [[false, 'tree'], [false, 'form']], + domain: domain, + target: 'current', + }); + }, + /*This is to get purchase order data according to the filters.*/ + on_dashboard_my_purchase_order_action: function (ev) { + ev.preventDefault(); + var $action = $(ev.currentTarget); + var start_date = this.$('#start_date').val() + var end_date = this.$('#end_date').val() + if (start_date && end_date) { + var domain = [['user_id', '=', session.uid], ['state', '=', 'purchase'], ['date_order', '>=', start_date], ['date_order', '<=', end_date]] + } + else if (start_date) { + var domain = [['user_id', '=', session.uid], ['state', '=', 'purchase'], ['date_order', '>=', start_date]] + } + else if (end_date) { + var domain = [['user_id', '=', session.uid], ['state', '=', 'purchase'], ['date_order', '<=', end_date]] + } + else { + var domain = [['user_id', '=', session.uid], ['state', '=', 'purchase']] + } + this.do_action({ + type: 'ir.actions.act_window', + name: 'Purchase Orders', + res_model: 'purchase.order', + views: [[false, 'tree'], [false, 'form']], + domain: domain, + target: 'current', + }); + }, + /*This is to get rfq sent data according to the filters.*/ + on_dashboard_rfq_sent_action: function (ev) { + ev.preventDefault(); + var $action = $(ev.currentTarget); + var start_date = this.$('#start_date').val() + var end_date = this.$('#end_date').val() + if (start_date && end_date) { + var domain = [['user_id', '=', session.uid], ['state', '=', 'sent'], ['date_order', '>=', start_date], ['date_order', '<=', end_date]] + } + else if (start_date) { + var domain = [['user_id', '=', session.uid], ['state', '=', 'sent'], ['date_order', '>=', start_date]] + } + else if (end_date) { + var domain = [['user_id', '=', session.uid], ['state', '=', 'sent'], ['date_order', '<=', end_date]] + } + else { + var domain = [['user_id', '=', session.uid], ['state', '=', 'sent']] + } + this.do_action({ + type: 'ir.actions.act_window', + name: 'RFQ Sent', + res_model: 'purchase.order', + views: [[false, 'tree'], [false, 'form']], + domain: domain, + target: 'current', + }); + }, + /*This is to get rfq cancel data according to the filters.*/ + on_dashboard_rfq_cancel_action: function (ev) { + ev.preventDefault(); + var $action = $(ev.currentTarget); + this.do_action({ + type: 'ir.actions.act_window', + name: 'RFQ Cancel', + res_model: 'purchase.order', + views: [[false, 'tree'], [false, 'form']], + domain: [['user_id', '=', session.uid], ['state', '=', 'cancel']], + target: 'current', + }); + }, + /*This is to get rfq to be approved data according to the filters.*/ + on_dashboard_to_rfq_approve_action: function (ev) { + ev.preventDefault(); + var $action = $(ev.currentTarget); + var start_date = this.$('#start_date').val() + var end_date = this.$('#end_date').val() + if (start_date && end_date) { + var domain = [['user_id', '=', session.uid], ['state', '=', 'to approve'], ['date_order', '>=', start_date], ['date_order', '<=', end_date]] + } + else if (start_date) { + var domain = [['user_id', '=', session.uid], ['state', '=', 'to approve'], ['date_order', '>=', start_date]] + } + else if (end_date) { + var domain = [['user_id', '=', session.uid], ['state', '=', 'to approve'], ['date_order', '<=', end_date]] + } + else { + var domain = [['user_id', '=', session.uid], ['state', '=', 'to approve']] + } + this.do_action({ + type: 'ir.actions.act_window', + name: 'To Approve', + res_model: 'purchase.order', + views: [[false, 'tree'], [false, 'form']], + domain: domain, + target: 'current', + }); + }, + /** + *Handles the onClick event for the date inputs and fetches data based on the selected date range. + *It empties certain elements on the dashboard and then queries the backend to get purchase order data. + *If the selected start date is greater than the end date, it displays a warning dialog. + */ + onClick_this_values() { + self = this + self.$('#rfq').empty(); + self.$('#rfq_sent').empty(); + self.$('#rfq_to_approve').empty(); + self.$('#purchase_order').empty(); + self.$('#cancelled_order').empty(); + var start_date = self.$('#start_date').val() + var end_date = self.$('#end_date').val() + if (start_date && end_date && start_date > end_date){ + var dialog = new Dialog(null, { + title: "Warning", + size: 'medium', + $content: $('
', { + html: 'End date is Less than Start date' + }), + buttons: [{ + text: "Close", + close: true + }] + }); + dialog.open(); + } + rpc.query({ + model: 'purchase.order', + method: 'get_value', + args: [start_date, end_date], + }).then(function (data) { + self.$('#rfq').append('' + data.rfq + ''); + self.$('#rfq_sent').append('' + data.rfq_sent + ''); + self.$('#rfq_to_approve').append('' + data.rfq_to_approve + ''); + self.$('#purchase_order').append('' + data.purchase_order + ''); + self.$('#cancelled_order').append('' + data.cancelled_order + ''); + }) + }, + render_vendor_product_graph: function () { + /*Graph shows count of products for vendors.*/ + var ctx = this.$("#lead_vendor"); + rpc.query({ + model: 'res.partner', + method: 'get_vendor_po', + args: [], + }).then(function (results) { + var po_count = results.purchase_order_count; + var chart = new Chart(ctx, { + type: "doughnut", + data: { + labels: Object.keys(po_count), + datasets: [{ + backgroundColor: [ + 'rgb(150,20,147)', + 'rgb(186,90,211)', + 'rgb(10,20,255)', + 'rgb(30,91,25)', + 'rgb(10,206,209)', + 'rgb(32,18,170)', + 'rgb(173,255,47)', + 'rgb(205,92,92)', + 'rgb(178,34,34)', + 'rgb(0,128,128)', + ], + data: Object.values(po_count), + }] + }, + }); + }); + }, + render_product_purchase_graph: function () { + /*This is to show a product lead graph.*/ + var ctx = this.$("#lead_product"); + rpc.query({ + model: 'product.product', + method: 'most_purchased_product', + args: [], + }).then(function (results) { + var purchased_qty = results.purchased_qty; + var chart = new Chart(ctx, { + type: "pie", + data: { + labels: Object.keys(purchased_qty), + datasets: [{ + backgroundColor: [ + 'rgb(255, 99, 132)', + 'rgb(255, 159, 64)', + 'rgb(75, 192, 192)', + 'rgb(54, 162, 235)', + 'rgb(255, 209, 219)', + 'rgb(255, 205, 86)', + 'rgb(99, 255, 222)', + 'rgb(132, 255, 99)', + 'rgb(139, 139, 184)', + 'rgb(40, 255, 40)', + ], + data: Object.values(purchased_qty), + }] + }, + }); + }); + }, + render_current_month_purchase_graph: function () { + /*It is to show monthly purchase count graph.*/ + var ctx = this.$("#current_month_purchase"); + rpc.query({ + model: 'purchase.order', + method: 'get_current_month_purchase', + args: [], + }).then(function (results) { + var current_month_count = results.current_month_count; + var chart = new Chart(ctx, { + type: "bar", + data: { + labels: Object.keys(current_month_count), + datasets: [{ + label: 'Purchase Order Count', + backgroundColor: [ + 'rgb(25,25,112)', + ], + data: Object.values(current_month_count), + }] + }, + }); + }); + }, + render_monthly_purchase_count_graph: function () { + /*This is to show lead quotations graph.*/ + var ctx = this.$("#monthly_purchase"); + rpc.query({ + model: 'purchase.order', + method: 'get_monthly_purchase_order', + args: [], + }).then(function (results) { + var monthly_purchase_count = results.monthly_purchase_count; + var chart = new Chart(ctx, { + type: "bar", + data: { + labels: Object.keys(monthly_purchase_count), + datasets: [{ + label: 'Purchase Order', + backgroundColor: [ + 'rgb(255, 99, 132)', + 'rgb(255, 159, 64)', + 'rgb(75, 192, 192)', + 'rgb(54, 162, 235)', + 'rgb(255, 209, 219)', + 'rgb(255, 205, 86)', + 'rgb(99, 255, 222)', + 'rgb(132, 255, 99)', + 'rgb(139, 139, 184)', + 'rgb(40, 255, 40)', + 'rgb(40, 0, 40)', + 'rgb(40, 255, 0)', + ], + data: Object.values(monthly_purchase_count), + }] + }, + }); + }); + }, + render_monthly_count_graph: function () { + /*This is to monthly count graph.*/ + var ctx = this.$("#monthly_count"); + rpc.query({ + model: 'purchase.order', + method: 'get_monthly_order', + args: [], + }).then(function (results) { + var monthly_count = results.monthly_count; + var chart = new Chart(ctx, { + type: "line", + data: { + labels: Object.keys(monthly_count), + datasets: [{ + label: 'Monthly Order', + backgroundColor: [ + 'rgb(25,25,112)', + 'rgb(135,206,235)', + 'rgb(75, 192, 192)', + 'rgb(54, 162, 235)', + 'rgb(255, 209, 219)', + 'rgb(255, 205, 86)', + 'rgb(99, 255, 222)', + 'rgb(132, 255, 99)', + 'rgb(139, 139, 184)', + 'rgb(40, 255, 40)', + ], + data: Object.values(monthly_count), + }] + }, + }); + }); + }, +}); +/*Add the DashBoard class to the action registry*/ +core.action_registry.add('purchase_dashboard', DashBoard); +return DashBoard; diff --git a/all_in_one_purchase_kit/static/src/js/purchase_report.js b/all_in_one_purchase_kit/static/src/js/purchase_report.js new file mode 100644 index 000000000..c1b394a78 --- /dev/null +++ b/all_in_one_purchase_kit/static/src/js/purchase_report.js @@ -0,0 +1,215 @@ +/** @odoo-module **/ +var AbstractAction = require("web.AbstractAction"); +var core = require("web.core"); +var rpc = require('web.rpc'); +var _t = core._t; +var QWeb = core.qweb; +var time = require('web.time'); +var framework = require('web.framework'); +var session = require('web.session'); +var self = this +/*Extending AbstractAction*/ +var PurchaseReport = AbstractAction.extend({ + template: 'PurchaseReport', + events: { + 'click #apply_filter': 'apply_filter', + 'click #pdf': 'print_pdf', + 'click #xlsx': 'print_xlsx', + 'click .view_purchase_order': 'button_view_order', + 'mousedown div.input-group.date[data-target-input="nearest"]': '_onCalendarIconClick', + }, + /*Initializing the function*/ + init: function(parent, action) { + this._super(parent, action); + this.report_lines = action.report_lines; + this.wizard_id = action.context.wizard | null; + }, + /*Take data from dynamic.purchase.report model*/ + start: function() { + self = this; + self.initial_render = true; + rpc.query({ + model: 'dynamic.purchase.report', + method: 'create', + args: [{ + }] + }).then(function(res) { + self.wizard_id = res; + self.load_data(self.initial_render); + }) + }, + /** + * Handles the click event when the calendar icon is clicked. + * Initializes the datetime picker with specified options. + */ + _onCalendarIconClick: function(ev) { + var $calendarInputGroup = $(ev.currentTarget); + var calendarOptions = { + minDate: moment({ + y: 1000 + }), + maxDate: moment().add(200, 'y'), + calendarWeeks: true, + defaultDate: moment().format(), + sideBySide: true, + buttons: { + showClear: true, + showClose: true, + showToday: true, + }, + icons: { + date: 'fa fa-calendar', + }, + locale: moment.locale(), + format: time.getLangDateFormat(), + widgetParent: 'body', + allowInputToggle: true, + }; + $calendarInputGroup.datetimepicker(calendarOptions); + }, + /*Load data*/ + load_data: function(initial_render = true) { + self = this; + self._rpc({ + model: 'dynamic.purchase.report', + method: 'purchase_report', + args: [ + [this.wizard_id] + ], + }).then(function(datas) { + if (initial_render) { + self.$('.filter_view_pr').html(QWeb.render('PurchaseFilterView', { + filter_data: datas['filters'], + + })); + self.$el.find('.report_type').select2({ + placeholder: ' Report Type...', + }); + } + if (datas['orders']) + self.$('.table_view_pr').html(QWeb.render('PurchaseOrderTable', { + filter: datas['filters'], + order: datas['orders'], + report_lines: datas['report_lines'], + main_lines: datas['report_main_line'] + })); + }) + }, + /*Function to print pdf*/ + print_pdf: function(e) { + e.preventDefault(); + self = this; + var action_title = self._title; + self._rpc({ + model: 'dynamic.purchase.report', + method: 'purchase_report', + args: [ + [self.wizard_id] + ], + }).then(function(data) { + var action = { + 'type': 'ir.actions.report', + 'report_type': 'qweb-pdf', + 'report_name': 'all_in_one_purchase_kit.purchase_order_report', + 'report_file': 'all_in_one_purchase_kit.purchase_order_report', + 'data': { + 'report_data': data + }, + 'context': { + 'active_model': 'purchase.report', + 'landscape': 1, + 'purchase_order_report': true + + }, + 'display_name': 'Purchase Order', + }; + return self.do_action(action); + }); + }, + /*Print excel report*/ + print_xlsx: function() { + self = this; + self._rpc({ + model: 'dynamic.purchase.report', + method: 'purchase_report', + args: [ + [self.wizard_id] + ], + }).then(function(data) { + var action = { + 'data': { + 'model': 'dynamic.purchase.report', + 'options': JSON.stringify(data['orders']), + 'output_format': 'xlsx', + 'report_data': JSON.stringify(data['report_lines']), + 'report_name': 'Purchase Report', + 'dfr_data': JSON.stringify(data), + }, + }; + self.downloadXlsx(action); + }); + }, + /*Link to controller*/ + downloadXlsx: function (action){ + framework.blockUI(); + session.get_file({ + url: '/purchase_dynamic_xlsx_reports', + data: action.data, + complete: framework.unblockUI, + error: (error) => this.call('crash_manager', 'rpc_error', error), + }); + }, + /*View Purchase Order*/ + button_view_order: function(event) { + event.preventDefault(); + var context = {}; + this.do_action({ + name: _t("Purchase Order"), + type: 'ir.actions.act_window', + res_model: 'purchase.order', + view_type: 'form', + domain: [ + ['id', '=', $(event.target).closest('.view_purchase_order').attr('id')] + ], + views: [ + [false, 'list'], + [false, 'form'] + ], + target: 'current' + }); + }, + /*Filter by date*/ + apply_filter: function() { + self = this; + self.initial_render = false; + var filter_data_selected = {}; + if (this.$el.find('.datetimepicker-input[name="date_from"]').val()) { + filter_data_selected.date_from = moment(this.$el.find('.datetimepicker-input[name="date_from"]').val(), time.getLangDateFormat()).locale('en').format('YYYY-MM-DD'); + } + if (this.$el.find('.datetimepicker-input[name="date_to"]').val()) { + filter_data_selected.date_to = moment(this.$el.find('.datetimepicker-input[name="date_to"]').val(), time.getLangDateFormat()).locale('en').format('YYYY-MM-DD'); + } + if ($(".report_type").length) { + var report_res = document.getElementById("report_res") + filter_data_selected.report_type = $(".report_type")[1].value + report_res.value = $(".report_type")[1].value + report_res.innerHTML = report_res.value.replaceAll('_', ' '); + if ($(".report_type")[1].value == "") { + report_res.innerHTML = "report_by_order"; + } + } + rpc.query({ + model: 'dynamic.purchase.report', + method: 'write', + args: [ + self.wizard_id, filter_data_selected + ], + }).then(function(res) { + self.initial_render = false; + self.load_data(self.initial_render); + }); + }, +}); +/*Adding purchase_report to registry*/ +core.action_registry.add("purchase_report", PurchaseReport); +return PurchaseReport; diff --git a/all_in_one_purchase_kit/static/src/scss/purchase_dashboard.scss b/all_in_one_purchase_kit/static/src/scss/purchase_dashboard.scss new file mode 100644 index 000000000..78f145395 --- /dev/null +++ b/all_in_one_purchase_kit/static/src/scss/purchase_dashboard.scss @@ -0,0 +1,133 @@ +p, span, a, li, button { + font-size: inherit; + font-weight: inherit; + line-height: inherit; +} +strong { + font-weight: 600; +} +h1, h2, h3, h4, h5, h6 { + line-height: 1.5em; + font-weight: 500; +} +strong { + font-weight: 400; +} +div span { + font-weight: 400; +} +:root { + /* Primary */ + --mauve: #7D7EAF; + + /* Light */ + --mauve-light: #e5e5ef; + --mauve-taupe: #B0FFDF; +} +.bg-mauve-light { + background-color: var(--mauve-taupe); +} +.text-mauve { + color: var(--mauve); +} +.dashboard-card { + display: flex; + justify-content: left; + padding: 1.1rem 1.5rem 1.5rem 1.5rem; + margin: 1rem auto; + height: 110px; + width: 15%; +} +.dashboard-card__icon-container { + height: 50px; + width: 50px; + border-radius: 15px; +} +.dashboard-card__icon-container i { + font-size: 20px; +} +.dashboard-card__details h3 { + font-weight: 700; + font-size: 1.2rem; + text-indent: 20px; +} +.dashboard-card__details h4 { + font-weight: 700; + font-size: 1.0rem; + margin-top: -3px; + text-indent: 20px; +} +h2.section-header { + font-weight: 500; + font-size: 1.5rem; +} +.card-shadow { + box-shadow: 1px 3px 5px 0px rgba(222, 222, 222, 1); +} +.lead_vendor{ + background-color: #f2f2f2; + height:500px; + width:48%; + float:left; +} +.lead_product{ + background-color: #f2f2f2; + height:500px; + width:48%; + float:right; +} +.monthly_purchase{ + background-color: #f2f2f2; + height:500px; + width:100%; +} +.bar{ + margin-top:40px; +} +.graph{ + margin-top:40px; +} +.current_month_purchase{ + background-color: #f2f2f2; + height:500px; + width:48%; + float:left; +} +.monthly_count{ + background-color: #f2f2f2; + height:500px; + width:48%; + float:right; +} +.total-amount-tile{ + width: 100%; + height: 150px; + padding: 1.7rem 1.5rem 1.5rem 1.5rem; + background: #848487; +} +.dashboard-card__icon-amount{ + font-weight: 700; + height:50px; + font-size: 1.2rem; + text-indent: 2px; + background: beige; +} +.form-group{ + float:right; + width: 20%; + height: 150px; +} +.dashboard-card:hover{ + background:#edebeb; +} +.date-filter{ + display: flex; + margin: 1rem auto; + height: 110px; + padding:10px +} +.card-shadow-date{ + box-shadow: 1px 3px 5px 0px rgba(222, 222, 222, 1); + width:500px; + display: flex; +} \ No newline at end of file diff --git a/all_in_one_purchase_kit/static/src/xml/dasboard_templates.xml b/all_in_one_purchase_kit/static/src/xml/dasboard_templates.xml new file mode 100644 index 000000000..a365598b9 --- /dev/null +++ b/all_in_one_purchase_kit/static/src/xml/dasboard_templates.xml @@ -0,0 +1,176 @@ + + + + +
+
+
+ + +
+
+
+
+
+
+

Total Purchase Amount:

+

+ +
+ +

+
+
+
+
+
+
+

Total RFQ Amount:

+

+ +
+ +

+
+
+
+
+
+

Start Date: + +

+
+
+

End Date: + +

+
+
+
+
+
+
+
+
+
+ +
+
+

+ +
+ +

+

RFQ

+
+
+
+
+ +
+
+

+ +
+ +

+

RFQ Sent

+
+
+
+
+ +
+
+

+ +
+ +

+

RFQ To Approve

+
+
+
+
+ +
+
+

+ +
+ +

+

Purchase Order

+
+
+
+
+ +
+
+

+ +
+ +

+

Cancelled

+
+
+
+
+
+
+
+

Top Purchase Orders

+
+ +
+
+
+
+
+

Top Purchased Products

+
+ +
+
+
+
+
+
+
+

Current Month Purchase

+
+ +
+
+
+
+
+

Order Created In Each Month

+
+ +
+
+
+
+
+
+
+

Monthly Purchases

+
+ +
+
+
+
+
+
+
+ \ No newline at end of file diff --git a/all_in_one_purchase_kit/static/src/xml/purchase_report_views.xml b/all_in_one_purchase_kit/static/src/xml/purchase_report_views.xml new file mode 100644 index 000000000..56c19a837 --- /dev/null +++ b/all_in_one_purchase_kit/static/src/xml/purchase_report_views.xml @@ -0,0 +1,489 @@ + + + + +
+
+
+

Purchase Report

+
+
+
+
+
+
+
+
+
+ + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
OrderDate OrderCustomerPurchase RepresentativeTotal QtyAmount TotalNote
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OrderDa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te OrderCustomerPurchase RepresentativeProduct CodeProduct NamePrice unitQtyPrice Subtotal
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
CategoryProduct CodeProduct NameQtyAmount Total
+ + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + +
CategoryQtyAmount Total
+ + + + + + + + + + + + +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + +
Purchase RepresentativeTotal OrderTotal QtyTotal Amount
+ + + + + + + + + + + + + + + + +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + +
StateTotal CountQuantityAmount
+ + + + + + + + + + + + + + + + +
+
+
+
+ diff --git a/all_in_one_purchase_kit/views/account_move_views.xml b/all_in_one_purchase_kit/views/account_move_views.xml new file mode 100644 index 000000000..8cfe34700 --- /dev/null +++ b/all_in_one_purchase_kit/views/account_move_views.xml @@ -0,0 +1,34 @@ + + + + + account.move.inherit.view.tree.all.in.one.purchase.kit + account.move + + + + + + + + + + account.move.inherit.view.form.all.in.one.purchase.kit + account.move + + + + +
+ + + +
+
+
+
+
+
diff --git a/all_in_one_purchase_kit/views/all_in_one_purchase_kit_menus.xml b/all_in_one_purchase_kit/views/all_in_one_purchase_kit_menus.xml new file mode 100644 index 000000000..e991bc8bc --- /dev/null +++ b/all_in_one_purchase_kit/views/all_in_one_purchase_kit_menus.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + diff --git a/all_in_one_purchase_kit/views/employee_purchase_requisition_action.xml b/all_in_one_purchase_kit/views/employee_purchase_requisition_action.xml new file mode 100644 index 000000000..c20c28aa7 --- /dev/null +++ b/all_in_one_purchase_kit/views/employee_purchase_requisition_action.xml @@ -0,0 +1,12 @@ + + + + + Print Requisition Order + + + form + code + action = records.action_print_report() + + diff --git a/all_in_one_purchase_kit/views/employee_purchase_requisition_views.xml b/all_in_one_purchase_kit/views/employee_purchase_requisition_views.xml new file mode 100644 index 000000000..b482fdf2a --- /dev/null +++ b/all_in_one_purchase_kit/views/employee_purchase_requisition_views.xml @@ -0,0 +1,273 @@ + + + + + Purchase Requisition + ir.actions.act_window + employee.purchase.requisition + tree,form,kanban + +

+ Create a new record! +

+
+
+ + + employee.purchase.requisition.view.form + employee.purchase.requisition + +
+
+ + +
+ +
+ + +
+
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
+
+
+ + + employee.purchase.requisition.view.tree + employee.purchase.requisition + + + + + + + + + + + + + + employee.purchase.requisition.view.kanban + employee.purchase.requisition + + + + +
+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+
+
+
+
+
+ + + employee.purchase.requisition.view.search + employee.purchase.requisition + + + + + + + + + + + + requisition.order.view.tree + requisition.order + + + + + + + + + + + + + +
diff --git a/all_in_one_purchase_kit/views/hr_department_views.xml b/all_in_one_purchase_kit/views/hr_department_views.xml new file mode 100644 index 000000000..d8feb7477 --- /dev/null +++ b/all_in_one_purchase_kit/views/hr_department_views.xml @@ -0,0 +1,14 @@ + + + + + hr.department.inherit.view.form.all.in.one.purchase.kit + hr.department + + + + + + + + diff --git a/all_in_one_purchase_kit/views/hr_employee_views.xml b/all_in_one_purchase_kit/views/hr_employee_views.xml new file mode 100644 index 000000000..cd8c40a9a --- /dev/null +++ b/all_in_one_purchase_kit/views/hr_employee_views.xml @@ -0,0 +1,22 @@ + + + + + hr.employee.inherit.view.form.all.in.one.purchase.kit + hr.employee + + + + + + + + + + + + + + diff --git a/all_in_one_purchase_kit/views/product_brand_views.xml b/all_in_one_purchase_kit/views/product_brand_views.xml new file mode 100644 index 000000000..00d663be5 --- /dev/null +++ b/all_in_one_purchase_kit/views/product_brand_views.xml @@ -0,0 +1,62 @@ + + + + + Product Brand + product.brand + tree,form + + + + Product.brand.view.form + product.brand + +
+ + +
+