Browse Source

Jan 06: [ADD] Initial Commit 'all_in_one_purchase_kit'

pull/299/head
Shijin V 1 year ago
parent
commit
6dd4b9bfb3
  1. 46
      all_in_one_purchase_kit/README.rst
  2. 25
      all_in_one_purchase_kit/__init__.py
  3. 91
      all_in_one_purchase_kit/__manifest__.py
  4. 22
      all_in_one_purchase_kit/controllers/__init__.py
  5. 57
      all_in_one_purchase_kit/controllers/all_in_one_purchase_kit.py
  6. 14
      all_in_one_purchase_kit/data/ir_sequence_data.xml
  7. 62
      all_in_one_purchase_kit/data/mail_template_data.xml
  8. 7
      all_in_one_purchase_kit/doc/RELEASE_NOTES.md
  9. 37
      all_in_one_purchase_kit/models/__init__.py
  10. 64
      all_in_one_purchase_kit/models/account_move.py
  11. 485
      all_in_one_purchase_kit/models/dynamic_purchase_report.py
  12. 260
      all_in_one_purchase_kit/models/employee_purchase_requisition.py
  13. 32
      all_in_one_purchase_kit/models/hr_department.py
  14. 33
      all_in_one_purchase_kit/models/hr_employee.py
  15. 44
      all_in_one_purchase_kit/models/product_brand.py
  16. 83
      all_in_one_purchase_kit/models/product_product.py
  17. 42
      all_in_one_purchase_kit/models/product_supplierinfo.py
  18. 31
      all_in_one_purchase_kit/models/product_template.py
  19. 262
      all_in_one_purchase_kit/models/purchase_order.py
  20. 144
      all_in_one_purchase_kit/models/purchase_order_line.py
  21. 46
      all_in_one_purchase_kit/models/purchase_report.py
  22. 74
      all_in_one_purchase_kit/models/requisition_order.py
  23. 32
      all_in_one_purchase_kit/models/res_config_settings.py
  24. 50
      all_in_one_purchase_kit/models/res_partner.py
  25. 34
      all_in_one_purchase_kit/models/stock_picking.py
  26. 22
      all_in_one_purchase_kit/report/__init__.py
  27. 11
      all_in_one_purchase_kit/report/all_in_one_purchase_kit_report_views.xml
  28. 11
      all_in_one_purchase_kit/report/dynamic_purchase_report_action.xml
  29. 42
      all_in_one_purchase_kit/report/purchase_order_report.py
  30. 427
      all_in_one_purchase_kit/report/purchase_order_report_templates.xml
  31. 15
      all_in_one_purchase_kit/report/purchase_order_templates.xml
  32. 206
      all_in_one_purchase_kit/report/purchase_requisition_templates.xml
  33. 30
      all_in_one_purchase_kit/security/all_in_one_purchase_kit_groups.xml
  34. 34
      all_in_one_purchase_kit/security/all_in_one_purchase_kit_security.xml
  35. 9
      all_in_one_purchase_kit/security/ir.model.access.csv
  36. BIN
      all_in_one_purchase_kit/static/description/assets/icons/check.png
  37. BIN
      all_in_one_purchase_kit/static/description/assets/icons/chevron.png
  38. BIN
      all_in_one_purchase_kit/static/description/assets/icons/cogs.png
  39. BIN
      all_in_one_purchase_kit/static/description/assets/icons/consultation.png
  40. BIN
      all_in_one_purchase_kit/static/description/assets/icons/ecom-black.png
  41. BIN
      all_in_one_purchase_kit/static/description/assets/icons/education-black.png
  42. BIN
      all_in_one_purchase_kit/static/description/assets/icons/hotel-black.png
  43. BIN
      all_in_one_purchase_kit/static/description/assets/icons/license.png
  44. BIN
      all_in_one_purchase_kit/static/description/assets/icons/lifebuoy.png
  45. BIN
      all_in_one_purchase_kit/static/description/assets/icons/manufacturing-black.png
  46. BIN
      all_in_one_purchase_kit/static/description/assets/icons/pos-black.png
  47. BIN
      all_in_one_purchase_kit/static/description/assets/icons/puzzle.png
  48. BIN
      all_in_one_purchase_kit/static/description/assets/icons/restaurant-black.png
  49. BIN
      all_in_one_purchase_kit/static/description/assets/icons/service-black.png
  50. BIN
      all_in_one_purchase_kit/static/description/assets/icons/trading-black.png
  51. BIN
      all_in_one_purchase_kit/static/description/assets/icons/training.png
  52. BIN
      all_in_one_purchase_kit/static/description/assets/icons/update.png
  53. BIN
      all_in_one_purchase_kit/static/description/assets/icons/user.png
  54. BIN
      all_in_one_purchase_kit/static/description/assets/icons/wrench.png
  55. BIN
      all_in_one_purchase_kit/static/description/assets/misc/categories.png
  56. BIN
      all_in_one_purchase_kit/static/description/assets/misc/check-box.png
  57. BIN
      all_in_one_purchase_kit/static/description/assets/misc/compass.png
  58. BIN
      all_in_one_purchase_kit/static/description/assets/misc/corporate.png
  59. BIN
      all_in_one_purchase_kit/static/description/assets/misc/customer-support.png
  60. BIN
      all_in_one_purchase_kit/static/description/assets/misc/cybrosys-logo.png
  61. BIN
      all_in_one_purchase_kit/static/description/assets/misc/features.png
  62. BIN
      all_in_one_purchase_kit/static/description/assets/misc/logo.png
  63. BIN
      all_in_one_purchase_kit/static/description/assets/misc/pictures.png
  64. BIN
      all_in_one_purchase_kit/static/description/assets/misc/pie-chart.png
  65. BIN
      all_in_one_purchase_kit/static/description/assets/misc/right-arrow.png
  66. BIN
      all_in_one_purchase_kit/static/description/assets/misc/star.png
  67. BIN
      all_in_one_purchase_kit/static/description/assets/misc/support.png
  68. BIN
      all_in_one_purchase_kit/static/description/assets/misc/whatsapp.png
  69. BIN
      all_in_one_purchase_kit/static/description/assets/modules/1.png
  70. BIN
      all_in_one_purchase_kit/static/description/assets/modules/2.png
  71. BIN
      all_in_one_purchase_kit/static/description/assets/modules/3.png
  72. BIN
      all_in_one_purchase_kit/static/description/assets/modules/4.png
  73. BIN
      all_in_one_purchase_kit/static/description/assets/modules/5.png
  74. BIN
      all_in_one_purchase_kit/static/description/assets/modules/6.png
  75. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/1.png
  76. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/10.png
  77. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/11.png
  78. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/12.png
  79. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/13.png
  80. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/14.png
  81. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/15.png
  82. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/16.png
  83. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/17.png
  84. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/18.png
  85. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/19.png
  86. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/2.png
  87. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/20.png
  88. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/21.png
  89. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/22.png
  90. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/23.png
  91. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/24.png
  92. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/25.png
  93. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/26.png
  94. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/27.png
  95. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/28.png
  96. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/29.png
  97. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/3.png
  98. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/30.png
  99. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/31.png
  100. BIN
      all_in_one_purchase_kit/static/description/assets/screenshots/32.png

46
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 <https://cybrosys.com/>`__
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 <https://cybrosys.com/>`__
Further information
===================
HTML Description: `<static/description/index.html>`__

25
all_in_one_purchase_kit/__init__.py

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
from . import controllers
from . import models
from . import report
from . import wizard

91
all_in_one_purchase_kit/__manifest__.py

@ -0,0 +1,91 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
{
'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,
}

22
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
from . import all_in_one_purchase_kit

57
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
import json
from odoo import http
from odoo.http import content_disposition, request
from odoo.tools import html_escape
class 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)))

14
all_in_one_purchase_kit/data/ir_sequence_data.xml

@ -0,0 +1,14 @@
<odoo>
<!-- Sequence for employee purchase requisition -->
<data noupdate="1">
<record id="sequence_purchase_requisition" model="ir.sequence">
<field name="name">Employee Purchase Requisition</field>
<field name="code">employee.purchase.requisition</field>
<field name="prefix">EPR</field>
<field name="padding">5</field>
<field eval="1" name="number_next"/>
<field eval="1" name="number_increment"/>
<field eval="False" name="company_id"/>
</record>
</data>
</odoo>

62
all_in_one_purchase_kit/data/mail_template_data.xml

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data noupdate="1">
<!--Function to set noupdate to False-->
<function name="write" model="ir.model.data">
<function name="search" model="ir.model.data">
<value eval="[('name', '=', 'email_template_edi_purchase_done'), ('module', '=', 'purchase')]"/>
</function>
<value eval="{'noupdate': False}"/>
</function>
<!--Confirmed po send mail data-->
<record id="purchase.email_template_edi_purchase_done"
model="mail.template">
<field name="body_html" type="html">
<div style="margin: 0px; padding: 0px;">
<p style="margin: 0px; padding: 0px; font-size: 13px;">
Dear
<t t-out="object.partner_id.name or ''">Brandon Freeman</t>
<t t-if="object.partner_id.parent_id">
(<t t-out="object.partner_id.parent_id.name or ''">
Azure Interior</t>)
</t>
<br/>
<br/>
Here is in attachment a purchase order
<strong t-out="object.name or ''">P00015</strong>
<t t-if="object.partner_ref">
with reference:
<t t-out="object.partner_ref or ''">REF_XXX</t>
</t>
amounting in
<strong t-out="format_amount(object.amount_total, object.currency_id) or ''">
$ 10.00
</strong>
<span>
<strong t-out="object.number_to_words"/>
</span>
from <t t-out="object.company_id.name or ''">
YourCompany</t>.
<br/>
<br/>
<t t-if="object.date_planned">
The receipt is expected for <strong
t-out="format_date(object.date_planned) or ''">
05/05/2021</strong>.
<br/>
<br/>
Could you please acknowledge the receipt of this order?
</t>
</p>
</div>
</field>
</record>
<!-- Function to set noupdate to True-->
<function name="write" model="ir.model.data">
<function name="search" model="ir.model.data">
<value eval="[('name', '=', 'email_template_edi_purchase_done'), ('module', '=', 'purchase')]"/>
</function>
<value eval="{'noupdate': True}"/>
</function>
</data>
</odoo>

7
all_in_one_purchase_kit/doc/RELEASE_NOTES.md

@ -0,0 +1,7 @@
## Module <all_in_one_purchase_kit>
#### 06.01.2024
#### Version 16.0.1.0.0
#### ADD
- Initial Commit for All In One Purchase Kit

37
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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

64
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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

485
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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()

260
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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)

32
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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'
)

33
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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'
)

44
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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)

83
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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,
})

42
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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})

31
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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"
)

262
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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

144
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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',
}

46
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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

74
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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]

32
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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")

50
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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)}}

34
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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'
)

22
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
from . import purchase_order_report

11
all_in_one_purchase_kit/report/all_in_one_purchase_kit_report_views.xml

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!--Purchase requisition report-->
<record id="report_purchase_requisition_action" model="ir.actions.report">
<field name="name">Material Purchase Requisition Report</field>
<field name="model">employee.purchase.requisition</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">all_in_one_purchase_kit.report_purchase_requisition</field>
<field name="report_file">all_in_one_purchase_kit.report_purchase_requisition</field>
</record>
</odoo>

11
all_in_one_purchase_kit/report/dynamic_purchase_report_action.xml

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!--Print pdf report-->
<record id="purchase_all_in_one_purchase_kit_action" model="ir.actions.report">
<field name="name">Purchase All In One Report</field>
<field name="model">dynamic.purchase.report</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">all_in_one_purchase_kit.purchase_order_report</field>
<field name="report_file">all_in_one_purchase_kit.purchase_order_report</field>
</record>
</odoo>

42
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(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
###############################################################################
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

427
all_in_one_purchase_kit/report/purchase_order_report_templates.xml

@ -0,0 +1,427 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!--Template to show purchase report respect to the filter selected-->
<template id="purchase_order_report">
<t t-call="web.html_container">
<t t-call="web.internal_layout">
<t t-if="Filters.get('report_type')=='Report By Order'">
<t t-call="all_in_one_purchase_kit.report_order"/>
</t>
<t t-if="Filters.get('report_type')=='Report By Order Detail'">
<t t-call="all_in_one_purchase_kit.report_order_detail"/>
</t>
<t t-if="Filters.get('report_type')=='Report By Product'">
<t t-call="all_in_one_purchase_kit.report_product"/>
</t>
<t t-if="Filters.get('report_type')=='Report By Categories'">
<t t-call="all_in_one_purchase_kit.report_category"/>
</t>
<t t-if="Filters.get('report_type')=='Report By Purchase Representative'">
<t t-call="all_in_one_purchase_kit.report_purchase_representative"/>
</t>
<t t-if="Filters.get('report_type')=='Report By State'">
<t t-call="all_in_one_purchase_kit.report_state"/>
</t>
</t>
</t>
</template>
<!--Report template when 'Report By Order' filter applied-->
<template id="report_order">
<div class="page">
<div class="oe_structure"/>
<span t-if="Filters.get('date_from')">
<strong>From:</strong>
<t t-esc="Filters['date_from']"/>
</span>
<span t-if="Filters.get('date_to')">
<strong>To:</strong>
<t t-esc="Filters['date_to']"/>
</span>
<div>
<div style="width:100%;">
<div style="text-align:centre;" class="row">
<div class="col-2">
<strong>Report Type:</strong>
<t t-esc="Filters.get('report_type')"/>
</div>
</div>
</div>
<br/>
<table class="table table-sm table-reports">
<thead>
<tr>
<th class="text-left">Order</th>
<th colspan="6" class="text-center">Date Order</th>
<th colspan="6" class="text-right">Customer</th>
<th colspan="6" class="text-right">Purchase
Representative
</th>
<th colspan="6" class="text-center">Total Qty</th>
<th colspan="6" class="text-left">Amount Total</th>
</tr>
</thead>
<tbody class="text-left">
<t t-foreach="report_main_line_data" t-as="main">
<tr style="font-weight: bold;">
<td colspan="6">
<span t-esc="main['name']"/>
</td>
<td colspan="6">
<span t-esc="main['date_order']"/>
</td>
<td colspan="6">
<span t-esc="main['partner']"/>
</td>
<td colspan="6">
<span t-esc="main['salesman']"/>
</td>
<td colspan="6">
<span t-esc="main['sum']"/>
</td>
<td colspan="6">
<span t-esc="main['amount_total']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
<br/>
</div>
</template>
<!--Report template when 'Report By Order Detail' filter applied-->
<template id="report_order_detail">
<div class="page">
<div class="oe_structure"/>
<span t-if="Filters.get('date_from')">
<strong>From:</strong>
<t t-esc="Filters['date_from']"/>
</span>
<span t-if="Filters.get('date_to')">
<strong>To:</strong>
<t t-esc="Filters['date_to']"/>
</span>
<div>
<div style="width:100%;">
<div style="text-align:centre;" class="row">
<div class="col-2">
<strong>Report Type:</strong>
<t t-esc="Filters.get('report_type')"/>
</div>
</div>
</div>
<br/>
<table class="table table-sm table-reports">
<thead>
<tr class="text-right">
<th>Order</th>
<th colspan="6">Date Order</th>
<th colspan="6">Customer</th>
<th colspan="6">Purchase Representative</th>
<th colspan="6">Product Code</th>
<th colspan="6">Product Name</th>
<th colspan="6">Price unit</th>
<th colspan="6">Qty</th>
<th colspan="6">Price Total</th>
</tr>
</thead>
<tbody>
<t t-foreach="report_main_line_data" t-as="main">
<tr style="font-weight: bold;">
<td colspan="6">
<span t-esc="main['name']"/>
</td>
<td colspan="6">
<span t-esc="main['date_order']"/>
</td>
<td colspan="6">
<span t-esc="main['partner']"/>
</td>
<td colspan="6">
<span t-esc="main['salesman']"/>
</td>
<td colspan="6">
<span t-esc="main['default_code']"/>
</td>
<td colspan="6">
<span t-esc="main['product']"/>
</td>
<td colspan="6">
<span t-esc="main['price_unit']"/>
</td>
<td colspan="6">
<span t-esc="main['sum']"/>
</td>
<td colspan="6">
<span t-esc="main['amount_total']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
<br/>
</div>
</template>
<!--Report template when 'Report By Product' filter applied-->
<template id="report_product">
<div class="page">
<div class="oe_structure"/>
<span t-if="Filters.get('date_from')">
<strong>From:</strong>
<t t-esc="Filters['date_from']"/>
</span>
<span t-if="Filters.get('date_to')">
<strong>To:</strong>
<t t-esc="Filters['date_to']"/>
</span>
<div>
<div style="width:100%;">
<div style="text-align:centre;" class="row">
<div class="col-2">
<strong>Report Type:</strong>
<t t-esc="Filters.get('report_type')"/>
</div>
</div>
</div>
<br/>
<table class="table table-sm table-reports">
<thead>
<tr>
<th class="text-left">Category</th>
<th colspan="6" class="text-center">Product Code
</th>
<th colspan="6" class="text-center">Product Name
</th>
<th colspan="6" class="text-center">Qty</th>
<th colspan="6">Amount Total</th>
</tr>
</thead>
<tbody>
<t t-foreach="report_main_line_data" t-as="main">
<tr style="font-weight: bold;">
<td colspan="6">
<span t-esc="main['name']"/>
</td>
<td colspan="6">
<span t-esc="main['default_code']"/>
</td>
<td colspan="6">
<span t-esc="main['product']"/>
</td>
<td colspan="6">
<span t-esc="main['qty']"/>
</td>
<td colspan="6">
<span t-esc="main['amount_total']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
<br/>
</div>
</template>
<!--Report template when 'Report By Category' filter applied-->
<template id="report_category">
<div class="page">
<div class="oe_structure"/>
<span t-if="Filters.get('date_from')">
<strong>From:</strong>
<t t-esc="Filters['date_from']"/>
</span>
<span t-if="Filters.get('date_to')">
<strong>To:</strong>
<t t-esc="Filters['date_to']"/>
</span>
<div>
<div style="width:100%;">
<div style="text-align:centre;" class="row">
<div class="col-2">
<strong>Report Type:</strong>
<t t-esc="Filters.get('report_type')"/>
</div>
</div>
</div>
<br/>
<table class="table table-sm table-reports">
<thead>
<tr>
<th colspan="6">Category</th>
<th colspan="6">Qty</th>
<th colspan="6">Amount Total</th>
</tr>
</thead>
<tbody>
<t t-foreach="report_main_line_data"
t-as="purchase_category">
<tr style="font-weight: bold;">
<td colspan="6">
<span t-esc="purchase_category['name']"/>
</td>
<td colspan="6">
<span t-esc="purchase_category['qty']"/>
</td>
<td colspan="6">
<span t-esc="purchase_category['amount_total']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
<br/>
</div>
</template>
<!--Report template when 'Report By Purchase Representative'
filter applied-->
<template id="report_purchase_representative">
<div class="page">
<div class="oe_structure"/>
<span t-if="Filters.get('date_from')">
<strong>From:</strong>
<t t-esc="Filters['date_from']"/>
</span>
<span t-if="Filters.get('date_to')">
<strong>To:</strong>
<t t-esc="Filters['date_to']"/>
</span>
<div>
<div style="width:100%;">
<div style="text-align:centre;" class="row">
<div class="col-2">
<strong>Report Type:</strong>
<t t-esc="Filters.get('report_type')"/>
</div>
</div>
</div>
<br/>
<table class="table table-sm table-reports">
<thead>
<tr>
<th>Purchase Representative</th>
<th colspan="6">Total Order</th>
<th colspan="6">Total Qty</th>
<th colspan="6">Total Amount</th>
</tr>
</thead>
<tbody>
<t t-foreach="report_main_line_data" t-as="main">
<tr style="font-weight: bold;">
<td>
<span t-esc="main['name']"/>
</td>
<td colspan="6">
<span t-esc="main['order']"/>
</td>
<td colspan="6">
<span t-esc="main['qty']"/>
</td>
<td colspan="6">
<span t-esc="main['amount']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
<br/>
</div>
</template>
<!--Report template when 'Report By State' filter applied-->
<template id="report_state">
<div class="page">
<div class="oe_structure"/>
<span t-if="Filters.get('date_from')">
<strong>From:</strong>
<t t-esc="Filters['date_from']"/>
</span>
<span t-if="Filters.get('date_to')">
<strong>To:</strong>
<t t-esc="Filters['date_to']"/>
</span>
<div>
<div style="width:100%;">
<div style="text-align:centre;" class="row">
<div class="col-2">
<strong>Report Type:</strong>
<t t-esc="Filters.get('report_type')"/>
</div>
</div>
</div>
<br/>
<table class="table table-sm table-reports">
<thead>
<tr class="text-left">
<th>State</th>
<th colspan="6">Total Count</th>
<th colspan="6">Quantity</th>
<th colspan="6">Amount</th>
</tr>
</thead>
<tbody>
<t t-foreach="report_main_line_data" t-as="main">
<tr style="font-weight: bold;">
<td colspan="6">
<t t-if="main['state'] == 'draft'">
<span>Quotation</span>
</t>
<t t-if="main['state'] == 'sent'">
<span>Quotation Sent</span>
</t>
<t t-if="main['state'] == 'purchase'">
<span>Purchase Order</span>
</t>
</td>
<td colspan="6" class="text-left">
<span t-esc="main['order']"/>
</td>
<td colspan="6" class="text-left">
<span t-esc="main['qty']"/>
</td>
<td colspan="6" class="text-left">
<span t-esc="main['amount']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
<br/>
</div>
</template>
<!--Inherit template report_purchaseorder_document-->
<template id="report_purchaseorder_inherit"
inherit_id="purchase.report_purchaseorder_document">
<xpath expr="//table//tr/th[1]" position="after">
<t t-if="request.env['ir.config_parameter'].sudo().get_param('purchase_orderline_image.show_product_image_in_report_purchase')">
<th>
<strong>Image</strong>
</th>
</t>
</xpath>
<!--Add product image in the report-->
<xpath expr="//t[@t-foreach='o.order_line']/tr/t[@t-if='not line.display_type']/td[1]"
position="after">
<t t-if="request.env['ir.config_parameter'].sudo().get_param('purchase_orderline_image.show_product_image_in_report_purchase')">
<td style="height:20px !important;width:20px !important;">
<span t-field="line.product_image"
t-options='{"widget": "image"}'/>
</td>
</t>
</xpath>
<xpath expr="//th[@name='th_price_unit']" position="after">
<th name="th_discount" class="text-right">
<strong>Discount(%)</strong>
</th>
</xpath>
<!--Add discount to report-->
<xpath expr="//td[span[@t-field='line.price_subtotal']]" position="before">
<td class="text-right">
<span t-field="line.discount"/>
</td>
</xpath>
</template>
</odoo>

15
all_in_one_purchase_kit/report/purchase_order_templates.xml

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!--Print amount in words in bill-->
<template id="invoice_report_view_amount_in_words"
inherit_id="account.report_invoice_document">
<xpath expr="//div[@name='payment_term']" position="before">
<div style="font-size:15px; padding-top:15px; padding-bottom:15px;">
<span>
<strong>Amount in Words (Total) :</strong>
</span>
<span t-field="o.number_to_words"/>
</div>
</xpath>
</template>
</odoo>

206
all_in_one_purchase_kit/report/purchase_requisition_templates.xml

@ -0,0 +1,206 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!--Purchase requisition report template-->
<template id="report_purchase_requisition">
<t t-call="web.external_layout">
<t t-call="web.html_container">
<div class="page">
<t t-foreach="records" t-as="rec">
<h1>Purchase Requisition :
<t t-if="rec['name']">
<t t-esc="rec['name']"/>
</t>
</h1>
<table class="table table-striped">
<tr>
<th>Employee</th>
<td>
<t t-if="rec['employee_id']">
<t t-esc="rec['employee_id'][1]"/>
</t>
</td>
<th>Requisition Date</th>
<td>
<t t-if="rec['employee_id']">
<t t-esc="rec['requisition_date']"/>
</t>
</td>
</tr>
<tr>
<th>Department</th>
<td>
<t t-if="rec['dept_id']">
<t t-esc="rec['dept_id'][1]"/>
</t>
</td>
<th>Received Date</th>
<td>
<t t-if="rec['receive_date']">
<t t-esc="rec['receive_date']"/>
</t>
</td>
</tr>
<tr>
<th>Requisition Responsible</th>
<td>
<t t-if="rec['user_id']">
<t t-esc="rec['user_id'][1]"/>
</t>
</td>
<th>Requisition Deadline</th>
<td>
<t t-if="rec['requisition_deadline']">
<t t-esc="rec['requisition_deadline']"/>
</t>
</td>
</tr>
<tr>
<th>Company</th>
<td>
<t t-if="rec['company_id']">
<t t-esc="rec['company_id'][1]"/>
</t>
</td>
</tr>
</table>
<h1>Other Information</h1>
<table class="table table-sm">
<tr>
<th>Confirmed By</th>
<td>
<t t-if="rec['confirm_id']">
<t t-esc="rec['confirm_id'][1]"/>
</t>
</td>
<th>Confirmed Date</th>
<td>
<t t-if="rec['confirmed_date']">
<t t-esc="rec['confirmed_date']"/>
</t>
</td>
</tr>
<tr>
<th>Department Manager</th>
<td>
<t t-if="rec['manager_id']">
<t t-esc="rec['manager_id'][1]"/>
</t>
</td>
<th>Department Approval Date</th>
<td>
<t t-if="rec['department_approval_date']">
<t t-esc="rec['department_approval_date']"/>
</t>
</td>
</tr>
<tr>
<th>Approved By:</th>
<td>
<t t-if="rec['requisition_head_id']">
<t t-esc="rec['requisition_head_id'][1]"/>
</t>
</td>
<th>Approved Date:</th>
<td>
<t t-if="rec['approval_date']">
<t t-esc="rec['approval_date']"/>
</t>
</td>
</tr>
<tr>
<th>Rejected By</th>
<td>
<t t-if="rec['rejected_user_id']">
<t t-esc="rec['rejected_user_id'][1]"/>
</t>
</td>
<th>Rejected Date</th>
<td>
<t t-if="rec['reject_date']">
<t t-esc="rec['reject_date']"/>
</t>
</td>
</tr>
</table>
<h1>Picking Details</h1>
<table class="table table-sm">
<tr>
<th>Source Location</th>
<td>
<t t-if="rec['source_location_id']">
<t t-esc="rec['source_location_id'][1]"/>
</t>
</td>
<th>Destination Location</th>
<td>
<t t-if="rec['source_location_id']">
<t t-esc="rec['destination_location_id'][1]"/>
</t>
</td>
</tr>
<tr>
<t t-if="rec['delivery_type_id']">
<th>Delivery To</th>
<td>
<t t-esc="rec['delivery_type_id'][1]"/>
</td>
</t>
<t t-if="rec['internal_picking_id']">
<th>Internal Transfer</th>
<td>
<t t-esc="rec['internal_picking_id'][1]"/>
</td>
</t>
</tr>
</table>
</t>
<h1>Requisition Lines</h1>
<table class='table'>
<thead>
<th>Requisition Action</th>
<th>Product</th>
<th>Description</th>
<th>Quantity</th>
<th>Unit Of Measure</th>
</thead>
<t t-foreach="order_ids" t-as="order">
<tbody>
<td>
<t t-if="order['requisition_type']=='internal_transfer'">
Internal Transfer
</t>
<t t-if="order['requisition_type']=='purchase_order'">
Purchase Order
</t>
</td>
<td>
<t t-if="order['product_id']">
<t t-esc="order['product_id'][1]"/>
</t>
</td>
<td>
<t t-if="order['description']">
<t t-esc="order['description']"/>
</t>
</td>
<td>
<t t-if="order['quantity']">
<t t-esc="order['quantity']"/>
</t>
</td>
<td><t t-if="order['uom']">
<t t-esc="order['uom']"/>
</t>
</td>
</tbody>
</t>
</table>
<h3>Employee Signature :</h3>
<h3>Manager Signature :</h3>
<h3>Approve Signature :</h3>
</div>
</t>
</t>
</template>
</odoo>

30
all_in_one_purchase_kit/security/all_in_one_purchase_kit_groups.xml

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="employee_requisition" model="ir.module.category">
<field name="name">Employee Purchase Requisition</field>
<field name="description">User access level for Material Request
module
</field>
<field name="sequence">20</field>
</record>
<!--User groups-->
<!--User requisition-->
<record id="employee_requisition_user" model="res.groups">
<field name="name">Requisition Users</field>
<field name="category_id" ref="employee_requisition"/>
</record>
<!--Requisition rights for head-->
<record id="employee_requisition_head" model="res.groups">
<field name="name">Department Head</field>
<field name="category_id" ref="employee_requisition"/>
<field name="implied_ids"
eval="[(4, ref('all_in_one_purchase_kit.employee_requisition_user'))]"/>
</record>
<!--Requisition rights for manager-->
<record id="employee_requisition_manager" model="res.groups">
<field name="name">Requisition Manager</field>
<field name="category_id" ref="employee_requisition"/>
<field name="implied_ids"
eval="[(4, ref('all_in_one_purchase_kit.employee_requisition_head'))]"/>
</record>
</odoo>

34
all_in_one_purchase_kit/security/all_in_one_purchase_kit_security.xml

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!--Record rules-->
<!--Rule for User-->
<record id="requisition_user_rule" model="ir.rule">
<field name="name">Requisition User Rule</field>
<field name="model_id" ref="model_employee_purchase_requisition"/>
<field name="domain_force">[('confirm_id', '=', user.id)]</field>
<field name="groups"
eval="[(4, ref('all_in_one_purchase_kit.employee_requisition_user'))]"/>
</record>
<!--Rule for head-->
<record id="department_head_rule" model="ir.rule">
<field name="name">Department Head Rule</field>
<field ref="model_employee_purchase_requisition" name="model_id"/>
<field name="domain_force">[('user_id','=',user.id)]</field>
<field name="groups"
eval="[(4, ref('all_in_one_purchase_kit.employee_requisition_head'))]"/>
</record>
<!--Rule for manager-->
<record id="requisition_manager_rule" model="ir.rule">
<field name="name">Requisition Manager Rule</field>
<field ref="model_employee_purchase_requisition" name="model_id"/>
<field name="domain_force">[(1,'=',1)]</field>
<field name="groups"
eval="[(4, ref('all_in_one_purchase_kit.employee_requisition_manager'))]"/>
</record>
<!--Company rule-->
<record id="requisition_company_rule" model="ir.rule">
<field name="name">Purchase Requisition Company Rule</field>
<field ref="model_employee_purchase_requisition" name="model_id"/>
<field name="domain_force">[('company_id', '=', company_id)]</field>
</record>
</odoo>

9
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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_product_brand_user access.product.brand.user model_product_brand base.group_user 1 1 1 1
3 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
4 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
5 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
6 access_requisition_order_user access.requisition.order.user model_requisition_order base.group_user 1 1 1 1
7 access_dynamic_purchase_report_user access.dynamic.purchase.report.user model_dynamic_purchase_report base.group_user 1 1 1 1
8 access_product_recommendation_user access.product.recommendation.user model_product_recommendation base.group_user 1 1 1 1
9 access_product_recommendation_line_user access.product.recommendation.line.user model_product_recommendation_line base.group_user 1 1 1 1

BIN
all_in_one_purchase_kit/static/description/assets/icons/check.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
all_in_one_purchase_kit/static/description/assets/icons/chevron.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

BIN
all_in_one_purchase_kit/static/description/assets/icons/cogs.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
all_in_one_purchase_kit/static/description/assets/icons/consultation.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
all_in_one_purchase_kit/static/description/assets/icons/ecom-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

BIN
all_in_one_purchase_kit/static/description/assets/icons/education-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

BIN
all_in_one_purchase_kit/static/description/assets/icons/hotel-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

BIN
all_in_one_purchase_kit/static/description/assets/icons/license.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
all_in_one_purchase_kit/static/description/assets/icons/lifebuoy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
all_in_one_purchase_kit/static/description/assets/icons/manufacturing-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

BIN
all_in_one_purchase_kit/static/description/assets/icons/pos-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

BIN
all_in_one_purchase_kit/static/description/assets/icons/puzzle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

BIN
all_in_one_purchase_kit/static/description/assets/icons/restaurant-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

BIN
all_in_one_purchase_kit/static/description/assets/icons/service-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

BIN
all_in_one_purchase_kit/static/description/assets/icons/trading-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

BIN
all_in_one_purchase_kit/static/description/assets/icons/training.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 B

BIN
all_in_one_purchase_kit/static/description/assets/icons/update.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
all_in_one_purchase_kit/static/description/assets/icons/user.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

BIN
all_in_one_purchase_kit/static/description/assets/icons/wrench.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
all_in_one_purchase_kit/static/description/assets/misc/categories.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
all_in_one_purchase_kit/static/description/assets/misc/check-box.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
all_in_one_purchase_kit/static/description/assets/misc/compass.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
all_in_one_purchase_kit/static/description/assets/misc/corporate.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
all_in_one_purchase_kit/static/description/assets/misc/customer-support.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
all_in_one_purchase_kit/static/description/assets/misc/cybrosys-logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
all_in_one_purchase_kit/static/description/assets/misc/features.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

BIN
all_in_one_purchase_kit/static/description/assets/misc/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
all_in_one_purchase_kit/static/description/assets/misc/pictures.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
all_in_one_purchase_kit/static/description/assets/misc/pie-chart.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
all_in_one_purchase_kit/static/description/assets/misc/right-arrow.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

BIN
all_in_one_purchase_kit/static/description/assets/misc/star.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
all_in_one_purchase_kit/static/description/assets/misc/support.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
all_in_one_purchase_kit/static/description/assets/misc/whatsapp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
all_in_one_purchase_kit/static/description/assets/modules/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
all_in_one_purchase_kit/static/description/assets/modules/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
all_in_one_purchase_kit/static/description/assets/modules/3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
all_in_one_purchase_kit/static/description/assets/modules/4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

BIN
all_in_one_purchase_kit/static/description/assets/modules/5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

BIN
all_in_one_purchase_kit/static/description/assets/modules/6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/10.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/11.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/12.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/14.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/15.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/17.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/18.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/19.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/20.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/21.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/22.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/23.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/24.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/25.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/26.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/27.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/28.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/29.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/30.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/31.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

BIN
all_in_one_purchase_kit/static/description/assets/screenshots/32.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save