@ -0,0 +1,51 @@ |
|||
.. 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 |
|||
|
|||
Employee Purchase Requisition |
|||
============================= |
|||
* Employee Purchase Requisition Module for Odoo 18 |
|||
|
|||
Installation |
|||
============ |
|||
- www.odoo.com/documentation/18.0/setup/install.html |
|||
- Install our custom addon |
|||
|
|||
License |
|||
------- |
|||
Affero General Public License v3.0 (AGPL v3) |
|||
(https://www.gnu.org/licenses/agpl-3.0-standalone.html) |
|||
|
|||
Company |
|||
------- |
|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
|||
|
|||
Credits |
|||
------- |
|||
* Developer : (V18) Mufeeda Shirin, |
|||
(V17) Ashok P K |
|||
|
|||
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 https://www.cybrosys.com |
|||
|
|||
Further information |
|||
=================== |
|||
HTML Description: `<static/description/index.html>`__ |
|||
|
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from . import models |
@ -0,0 +1,58 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
{ |
|||
'name': 'Employee Purchase Requisition', |
|||
'version': '18.0.1.0.0', |
|||
'category': 'Purchases', |
|||
'summary': 'Manage material requisition of employees and user', |
|||
'description': """Create the material requisition request and there are |
|||
multi-level approvals for requests from the department head and requisition |
|||
manager. Department head has the option to choose vendors for each material. |
|||
Also we can generate the PDF report for each material requisition""", |
|||
'author': 'Cybrosys Techno Solutions', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'maintainer': 'Cybrosys Techno Solutions', |
|||
'website': 'https://www.cybrosys.com', |
|||
'depends': ['base', 'hr', 'stock', 'purchase'], |
|||
'data': [ |
|||
'security/employee_purchase_requisition_groups.xml', |
|||
'security/employee_purchase_requisition_security.xml', |
|||
'security/ir.model.access.csv', |
|||
'data/ir_sequence_data.xml', |
|||
'views/employee_purchase_requisition_views.xml', |
|||
'views/requisition_order_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_actions.xml', |
|||
'views/employee_purchase_requisition_menu.xml', |
|||
'report/employee_purchase_requisition_templates.xml', |
|||
'report/employee_purchase_requisition_report.xml', |
|||
], |
|||
'images': ['static/description/banner.png'], |
|||
'license': 'AGPL-3', |
|||
'installable': True, |
|||
'auto_install': False, |
|||
'application': True, |
|||
} |
|||
|
@ -0,0 +1,15 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<data noupdate="1"> |
|||
<!-- sequence for employee purchase requisition --> |
|||
<record id="ir_sequence_employee_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,6 @@ |
|||
## Module <employee_purchase_requisition> |
|||
|
|||
#### 19.07.2025 |
|||
#### Version 18.0.1.0.0 |
|||
#### ADD |
|||
- Initial commit for Employee Purchase Requisition |
@ -0,0 +1,27 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from . import employee_purchase_requisition |
|||
from . import hr_department |
|||
from . import hr_employee |
|||
from . import purchase_order |
|||
from . import requisition_order |
|||
from . import stock_picking |
@ -0,0 +1,237 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from odoo import api, fields, models |
|||
from odoo.exceptions import ValidationError |
|||
|
|||
|
|||
class PurchaseRequisition(models.Model): |
|||
"""Class for adding fields and functions for purchase requisition model.""" |
|||
_name = 'employee.purchase.requisition' |
|||
_description = 'Employee Purchase Requisition' |
|||
_inherit = "mail.thread", "mail.activity.mixin" |
|||
|
|||
name = fields.Char(string="Reference No", readonly=True) |
|||
employee_id = fields.Many2one(comodel_name='hr.employee', string='Employee', |
|||
required=True, help='Select an employee') |
|||
dept_id = fields.Many2one(comodel_name='hr.department', string='Department', |
|||
related='employee_id.department_id', store=True, |
|||
help='Select an department') |
|||
user_id = fields.Many2one(comodel_name='res.users', string='Responsible', |
|||
required=True, |
|||
domain=lambda self: [('share', '=', False), |
|||
('id', '!=', self.env.uid)], |
|||
help='Select a user who is responsible for requisition') |
|||
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='Received date') |
|||
requisition_deadline = fields.Date(string="Requisition Deadline", |
|||
help="End date of purchase requisition") |
|||
company_id = fields.Many2one(comodel_name='res.company', string='Company', |
|||
default=lambda self: self.env.company, |
|||
help='Select a company') |
|||
requisition_order_ids = fields.One2many(comodel_name='requisition.order', |
|||
inverse_name='requisition_product_id', |
|||
required=True) |
|||
confirm_id = fields.Many2one(comodel_name='res.users', |
|||
string='Confirmed By', |
|||
default=lambda self: self.env.uid, |
|||
readonly=True, |
|||
help='User who confirmed the requisition.') |
|||
manager_id = fields.Many2one(comodel_name='res.users', |
|||
string='Department Manager', readonly=True, |
|||
help='Select a department manager') |
|||
requisition_head_id = fields.Many2one(comodel_name='res.users', |
|||
string='Approved By', readonly=True, |
|||
help='User who approved the requisition.') |
|||
rejected_user_id = fields.Many2one(comodel_name='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(comodel_name='stock.location', |
|||
string='Source Location', |
|||
help='Source location of requisition.') |
|||
destination_location_id = fields.Many2one(comodel_name='stock.location', |
|||
string="Destination Location", |
|||
help='Destination location of requisition.') |
|||
delivery_type_id = fields.Many2one(comodel_name='stock.picking.type', |
|||
string='Delivery To', |
|||
help='Type of delivery.') |
|||
internal_picking_id = fields.Many2one(comodel_name='stock.picking.type', |
|||
string="Internal Picking") |
|||
requisition_description = fields.Text(string="Reason For Requisition") |
|||
purchase_count = fields.Integer(string='Purchase Count', |
|||
help='Purchase count', |
|||
compute='_compute_purchase_count') |
|||
internal_transfer_count = fields.Integer(string='Internal Transfer count', |
|||
help='Internal transfer count', |
|||
compute='_compute_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')], default='new', |
|||
copy=False, tracking=True) |
|||
|
|||
@api.model |
|||
def create(self, vals): |
|||
"""Function to generate purchase requisition sequence""" |
|||
if vals.get('name', 'New') == 'New': |
|||
vals['name'] = self.env['ir.sequence'].next_by_code( |
|||
'employee.purchase.requisition') or 'New' |
|||
result = super(PurchaseRequisition, self).create(vals) |
|||
return result |
|||
|
|||
def action_confirm_requisition(self): |
|||
"""Function to confirm purchase requisition""" |
|||
self.source_location_id = ( |
|||
self.employee_id.sudo().department_id.department_location_id.id) if ( |
|||
self.employee_id.sudo().department_id.department_location_id) else ( |
|||
self.env.ref('stock.stock_location_stock').id) |
|||
self.destination_location_id = ( |
|||
self.employee_id.sudo().employee_location_id.id) if ( |
|||
self.employee_id.sudo().employee_location_id) else ( |
|||
self.env.ref('stock.stock_location_stock').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 department""" |
|||
for rec in self.requisition_order_ids: |
|||
if rec.requisition_type == 'purchase_order' and not rec.partner_id: |
|||
raise ValidationError('Select a vendor') |
|||
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.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': rec.partner_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'}) |
|||
|
|||
def _compute_internal_transfer_count(self): |
|||
"""Function to compute the transfer count""" |
|||
self.internal_transfer_count = self.env['stock.picking'].search_count([ |
|||
('requisition_order', '=', self.name)]) |
|||
|
|||
def _compute_purchase_count(self): |
|||
"""Function to compute the purchase count""" |
|||
self.purchase_count = self.env['purchase.order'].search_count([ |
|||
('requisition_order', '=', self.name)]) |
|||
|
|||
def action_receive(self): |
|||
"""Received purchase requisition""" |
|||
self.write({'state': 'received'}) |
|||
self.receive_date = fields.Date.today() |
|||
|
|||
def get_purchase_order(self): |
|||
"""Purchase order smart button view""" |
|||
self.ensure_one() |
|||
return { |
|||
'type': 'ir.actions.act_window', |
|||
'name': 'Purchase Order', |
|||
'view_mode': 'list,form', |
|||
'res_model': 'purchase.order', |
|||
'domain': [('requisition_order', '=', self.name)], |
|||
} |
|||
|
|||
def get_internal_transfer(self): |
|||
"""Internal transfer smart tab view""" |
|||
self.ensure_one() |
|||
return { |
|||
'type': 'ir.actions.act_window', |
|||
'name': 'Internal Transfers', |
|||
'view_mode': 'list,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( |
|||
'employee_purchase_requisition.' |
|||
'action_report_purchase_requisition').report_action( |
|||
self, data=data)) |
@ -0,0 +1,31 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class Department(models.Model): |
|||
""" Class for adding new field in employee department""" |
|||
_inherit = 'hr.department' |
|||
|
|||
department_location_id = fields.Many2one(comodel_name='stock.location', |
|||
string='Destination Location', |
|||
help='Select a department location from the list of locations.') |
@ -0,0 +1,31 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class HrEmployeePrivate(models.Model): |
|||
"""Class to add new field in employee form""" |
|||
_inherit = 'hr.employee' |
|||
|
|||
employee_location_id = fields.Many2one(comodel_name='stock.location', |
|||
string="Destination Location", |
|||
help='Select a employee location from the location list') |
@ -0,0 +1,30 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class PurchaseOrder(models.Model): |
|||
"""Class to add new field in purchase order""" |
|||
_inherit = 'purchase.order' |
|||
|
|||
requisition_order = fields.Char(string='Requisition Order', |
|||
help='Set a requisition Order') |
@ -0,0 +1,67 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from odoo import api, fields, models |
|||
|
|||
|
|||
class RequisitionOrder(models.Model): |
|||
"""Model to add Requisition order details""" |
|||
_name = 'requisition.order' |
|||
_description = 'Requisition order' |
|||
|
|||
requisition_product_id = fields.Many2one( |
|||
comodel_name='employee.purchase.requisition', |
|||
help='Requisition product.') |
|||
state = fields.Selection(string='State', |
|||
related='requisition_product_id.state') |
|||
requisition_type = fields.Selection(string='Requisition Type', selection=[ |
|||
('purchase_order', 'Purchase Order'), |
|||
('internal_transfer', 'Internal Transfer'), ], |
|||
help='Type of requisition', |
|||
required=True, default='purchase_order') |
|||
product_id = fields.Many2one(comodel_name='product.product', required=True, |
|||
help='Product') |
|||
description = fields.Text(string="Description", compute='_compute_name', |
|||
store=True, readonly=False, precompute=True, |
|||
help='Product description') |
|||
quantity = fields.Integer(string='Quantity', help='Product quantity') |
|||
uom = fields.Char(related='product_id.uom_id.name', |
|||
string='Unit of Measure', help='Product unit of measure') |
|||
partner_id = fields.Many2one(comodel_name='res.partner', string='Vendor', |
|||
help='Vendor for the requisition', |
|||
readonly=False) |
|||
|
|||
@api.depends('product_id') |
|||
def _compute_name(self): |
|||
"""Compute product description""" |
|||
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.onchange('requisition_type') |
|||
def _onchange_product(self): |
|||
"""Fetching product vendors""" |
|||
vendors_list = [data.partner_id.id for data in |
|||
self.product_id.seller_ids] |
|||
return {'domain': {'partner_id': [('id', 'in', vendors_list)]}} |
@ -0,0 +1,30 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) |
|||
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) |
|||
# |
|||
# You can modify it under the terms of the GNU AFFERO |
|||
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE |
|||
# (AGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################### |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class Picking(models.Model): |
|||
"""Class to add new field in stock picking""" |
|||
_inherit = 'stock.picking' |
|||
|
|||
requisition_order = fields.Char(string='Requisition Order', |
|||
help='Requisition order sequence') |
@ -0,0 +1,11 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!--purchase requisition report--> |
|||
<record id="action_report_purchase_requisition" 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">employee_purchase_requisition.report_purchase_requisition</field> |
|||
<field name="report_file">employee_purchase_requisition.report_purchase_requisition</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,259 @@ |
|||
<?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" |
|||
style="font-family: 'Arial', sans-serif; font-size: 10pt; color: #333;"> |
|||
<t t-foreach="records" t-as="rec"> |
|||
<h3 style="color: #4CAF50; text-align: center; margin-bottom: 20px;"> |
|||
Purchase Requisition: |
|||
<t t-if="rec['name']"> |
|||
<t t-esc="rec['name']"/> |
|||
</t> |
|||
</h3> |
|||
|
|||
<table style="width: 100%; margin-bottom: 20px; border-collapse: collapse;"> |
|||
<tr> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Employee: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['employee_id']"> |
|||
<t t-esc="rec['employee_id'][1]"/> |
|||
</t> |
|||
</td> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Requisition Date: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['requisition_date']"> |
|||
<t t-esc="rec['requisition_date']"/> |
|||
</t> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Department: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['dept_id']"> |
|||
<t t-esc="rec['dept_id'][1]"/> |
|||
</t> |
|||
</td> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Received Date: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['receive_date']"> |
|||
<t t-esc="rec['receive_date']"/> |
|||
</t> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Requisition Responsible: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['user_id']"> |
|||
<t t-esc="rec['user_id'][1]"/> |
|||
</t> |
|||
</td> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Requisition Deadline: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['requisition_deadline']"> |
|||
<t t-esc="rec['requisition_deadline']"/> |
|||
</t> |
|||
</td> |
|||
</tr> |
|||
<!-- Additional rows omitted for brevity --> |
|||
</table> |
|||
|
|||
<h4 style="color: #4CAF50; margin-top: 20px; margin-bottom: 10px;"> |
|||
Other Information |
|||
</h4> |
|||
<table style="width: 100%; margin-bottom: 20px; border-collapse: collapse;"> |
|||
<tr> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Confirmed By: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['confirm_id']"> |
|||
<t t-esc="rec['confirm_id'][1]"/> |
|||
</t> |
|||
</td> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Confirmed Date: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['confirmed_date']"> |
|||
<t t-esc="rec['confirmed_date']"/> |
|||
</t> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Department Manager: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['manager_id']"> |
|||
<t t-esc="rec['manager_id'][1]"/> |
|||
</t> |
|||
</td> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Department Approval Date: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['department_approval_date']"> |
|||
<t t-esc="rec['department_approval_date']"/> |
|||
</t> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Approved By: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['requisition_head_id']"> |
|||
<t t-esc="rec['requisition_head_id'][1]"/> |
|||
</t> |
|||
</td> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Approved Date: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['approval_date']"> |
|||
<t t-esc="rec['approval_date']"/> |
|||
</t> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Rejected By: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['rejected_user_id']"> |
|||
<t t-esc="rec['rejected_user_id'][1]"/> |
|||
</t> |
|||
</td> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Rejected Date: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['reject_date']"> |
|||
<t t-esc="rec['reject_date']"/> |
|||
</t> |
|||
</td> |
|||
</tr> |
|||
<!-- Additional rows omitted for brevity --> |
|||
</table> |
|||
|
|||
<h4 style="color: #4CAF50; margin-top: 20px; margin-bottom: 10px;"> |
|||
Picking Details |
|||
</h4> |
|||
<table style="width: 100%; margin-bottom: 20px; border-collapse: collapse;"> |
|||
<tr> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Source Location: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['source_location_id']"> |
|||
<t t-esc="rec['source_location_id'][1]"/> |
|||
</t> |
|||
</td> |
|||
<th style="font-weight:bold;background-color: #f2f5f2; padding: 8px; text-align: left;"> |
|||
Destination Location: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="rec['destination_location_id']"> |
|||
<t t-esc="rec['destination_location_id'][1]"/> |
|||
</t> |
|||
</td> |
|||
</tr> |
|||
<tr> |
|||
<t t-if="rec['delivery_type_id']"> |
|||
<th style="font-weight:bold;background-color: #f2f2f2; padding: 8px; text-align: left;"> |
|||
Delivery To: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-esc="rec['delivery_type_id'][1]"/> |
|||
</td> |
|||
</t> |
|||
<t t-if="rec['internal_picking_id']"> |
|||
<th style="font-weight:bold;background-color: #f2f5f2; padding: 8px; text-align: left;"> |
|||
Internal Transfer: |
|||
</th> |
|||
<td style="padding: 8px;"> |
|||
<t t-esc="rec['internal_picking_id'][1]"/> |
|||
</td> |
|||
</t> |
|||
</tr> |
|||
<!-- Additional rows omitted for brevity --> |
|||
</table> |
|||
|
|||
<h4 style="color: #4CAF50; margin-top: 20px; margin-bottom: 10px;"> |
|||
Requisition Lines |
|||
</h4> |
|||
<table style="width: 100%; margin-bottom: 20px; border-collapse: collapse; border: 1px solid #ddd;"> |
|||
<thead style="background-color: #4CAF50; color: white;"> |
|||
<tr> |
|||
<th style="padding: 8px;">Requisition |
|||
Action |
|||
</th> |
|||
<th style="padding: 8px;">Product</th> |
|||
<th style="padding: 8px;">Description</th> |
|||
<th style="padding: 8px;">Quantity</th> |
|||
<th style="padding: 8px;">Unit Of Measure |
|||
</th> |
|||
</tr> |
|||
</thead> |
|||
<t t-foreach="order_ids" t-as="order"> |
|||
<tbody> |
|||
<tr> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="order['requisition_type']=='internal_transfer'"> |
|||
Internal Transfer |
|||
</t> |
|||
<t t-if="order['requisition_type']=='purchase_order'"> |
|||
Purchase Order |
|||
</t> |
|||
</td> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="order['product_id']"> |
|||
<t t-esc="order['product_id'][1]"/> |
|||
</t> |
|||
</td> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="order['description']"> |
|||
<t t-esc="order['description']"/> |
|||
</t> |
|||
</td> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="order['quantity']"> |
|||
<t t-esc="order['quantity']"/> |
|||
</t> |
|||
</td> |
|||
<td style="padding: 8px;"> |
|||
<t t-if="order['uom']"> |
|||
<t t-esc="order['uom']"/> |
|||
</t> |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</t> |
|||
</table> |
|||
|
|||
<div style="margin-top: 30px;"> |
|||
<h5 style="color: #333;">Employee Signature:</h5> |
|||
<h5 style="color: #333;">Manager Signature:</h5> |
|||
<h5 style="color: #333;">Approve Signature:</h5> |
|||
</div> |
|||
</t> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</template> |
|||
</odoo> |
@ -0,0 +1,28 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<record model="ir.module.category" id="employee_requisition"> |
|||
<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--> |
|||
<record id="employee_requisition_user" model="res.groups"> |
|||
<field name="name">Requisition Users</field> |
|||
<field name="category_id" ref="employee_requisition"/> |
|||
</record> |
|||
|
|||
<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('employee_purchase_requisition.employee_requisition_user'))]"/> |
|||
</record> |
|||
<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('employee_purchase_requisition.employee_requisition_head'))]"/> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,33 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<!--Record rules--> |
|||
<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('employee_purchase_requisition.employee_requisition_user'))]"/> |
|||
</record> |
|||
|
|||
<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('employee_purchase_requisition.employee_requisition_head'))]"/> |
|||
</record> |
|||
|
|||
<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('employee_purchase_requisition.employee_requisition_manager'))]"/> |
|||
</record> |
|||
|
|||
<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: 2.2 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 628 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 210 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 542 B |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 738 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 926 B |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 189 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 126 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 118 KiB |
After Width: | Height: | Size: 142 KiB |
After Width: | Height: | Size: 138 KiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 115 KiB |
After Width: | Height: | Size: 123 KiB |