@ -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>`__ |
@ -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 |
@ -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, |
|||
} |
@ -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 |
@ -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))) |
@ -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> |
@ -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> |
@ -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 |
@ -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 |
@ -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 |
@ -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() |
@ -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) |
@ -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' |
|||
) |
@ -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' |
|||
) |
@ -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) |
@ -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, |
|||
}) |
@ -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}) |
@ -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" |
|||
) |
@ -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 |
@ -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', |
|||
} |
@ -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 |
@ -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] |
@ -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") |
@ -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)}} |
@ -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' |
|||
) |
@ -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 |
@ -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> |
@ -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> |
@ -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 |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
|
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 589 B |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 967 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 162 KiB |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 178 KiB |
After Width: | Height: | Size: 152 KiB |
After Width: | Height: | Size: 183 KiB |
After Width: | Height: | Size: 135 KiB |
After Width: | Height: | Size: 157 KiB |
After Width: | Height: | Size: 149 KiB |
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 198 KiB |
After Width: | Height: | Size: 156 KiB |
After Width: | Height: | Size: 73 KiB |
After Width: | Height: | Size: 156 KiB |
After Width: | Height: | Size: 286 KiB |
After Width: | Height: | Size: 159 KiB |
After Width: | Height: | Size: 278 KiB |
After Width: | Height: | Size: 143 KiB |
After Width: | Height: | Size: 308 KiB |
After Width: | Height: | Size: 201 KiB |
After Width: | Height: | Size: 174 KiB |
After Width: | Height: | Size: 142 KiB |
After Width: | Height: | Size: 168 KiB |
After Width: | Height: | Size: 161 KiB |
After Width: | Height: | Size: 184 KiB |
After Width: | Height: | Size: 200 KiB |
After Width: | Height: | Size: 215 KiB |