Add odex25_maintenance
This commit is contained in:
parent
3a3f834c54
commit
4755d7ddc4
|
|
@ -1,2 +1,2 @@
|
|||
# odex25-standard-moduless
|
||||
# odex25-standard-modules
|
||||
This Repo contains general standard modules for all projects.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
from . import models
|
||||
from . import wizard
|
||||
from . import reports
|
||||
from . import controllers
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
'name':'Maintenance Custom ',
|
||||
'version':'1.0',
|
||||
'summary':'Maintenance Custom system',
|
||||
'sequence': 1,
|
||||
'description':
|
||||
"""
|
||||
""",
|
||||
'depends':['sale','purchase_requisition_custom', 'maintenance','hr_maintenance'],
|
||||
'data':[
|
||||
'security/ir.model.access.csv',
|
||||
'data/ir_sequences_data.xml',
|
||||
'security/groups.xml',
|
||||
'views/maintenance_view.xml',
|
||||
'views/maintenance_asset.xml',
|
||||
'views/maintenance_checklist.xml',
|
||||
'views/menu_security_cus.xml',
|
||||
'wizard/maintenance_report_wiz_view.xml',
|
||||
'reports/equipment_report.xml',
|
||||
'reports/spare_part_report.xml',
|
||||
'reports/general_maintenance_report.xml',
|
||||
'reports/report_maintenance_request.xml',
|
||||
'reports/maintenance_report.xml',
|
||||
'reports/maintenance_team_report.xml',
|
||||
],
|
||||
'qweb': ['static/src/xml/*.xml'],
|
||||
'installable':
|
||||
True,
|
||||
'application':
|
||||
True,
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import service
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
from odoo import http
|
||||
from odoo.http import request
|
||||
from odoo.exceptions import ValidationError
|
||||
from passlib.context import CryptContext
|
||||
import json
|
||||
import xmlrpc.client
|
||||
|
||||
url = 'http://localhost:8069'
|
||||
db = 'laundry'
|
||||
#db = 'test13'
|
||||
|
||||
models = {
|
||||
'product' : {
|
||||
'model' : 'product.product', 'field' : ['lst_price', 'name',]
|
||||
},
|
||||
}
|
||||
|
||||
class Service(http.Controller):
|
||||
|
||||
@http.route('/hello', auth='public')
|
||||
def hello(self):
|
||||
return '<h1>Hello Optimum !!</h1>'
|
||||
|
||||
@http.route('/user/create', auth='public')
|
||||
def user_create(self):
|
||||
user_data = dict(
|
||||
name=request.params.get('name'),
|
||||
login=request.params.get('login'),
|
||||
password=request.params.get('password'),
|
||||
#odoobot_state='not_initialized'
|
||||
)
|
||||
user_model = request.env['res.users']
|
||||
search_res = user_model.sudo().search([('login','=',user_data['login'])])
|
||||
if not search_res :
|
||||
obj = user_model.sudo().create(user_data)
|
||||
res = {
|
||||
'code' : 1,
|
||||
'message' : 'A new User Created Successfully',
|
||||
'result' : {
|
||||
'user_id' : obj.id ,
|
||||
}
|
||||
}
|
||||
else :
|
||||
res = {
|
||||
'code' : -1,
|
||||
'message' : 'Login name is exist',
|
||||
}
|
||||
return json.dumps(res)
|
||||
|
||||
|
||||
@http.route('/user/check', auth='public')
|
||||
def check_user(self):
|
||||
username = request.params.get('login')
|
||||
password = request.params.get('password')
|
||||
common = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url))
|
||||
uid = common.authenticate(db, username, password, {})
|
||||
if uid :
|
||||
res = {
|
||||
'code' : 2,
|
||||
'message' : 'Login Sucessfuly',
|
||||
'result' : {
|
||||
'user_id' : uid ,
|
||||
}
|
||||
}
|
||||
else:
|
||||
res = {
|
||||
'code' : -2,
|
||||
'message' : 'Wrong Login/Password',
|
||||
'result' : {
|
||||
#'user_id' : obj.id ,
|
||||
}
|
||||
}
|
||||
return json.dumps(res)
|
||||
|
||||
|
||||
@http.route('/product/all', auth='public')
|
||||
def all_product(self):
|
||||
product_model = request.env['product.template']
|
||||
res = product_model.sudo().search_read([],['name'])
|
||||
if res :
|
||||
result = {
|
||||
'code' : 3,
|
||||
'message' : 'Request Done',
|
||||
'result' : res
|
||||
}
|
||||
else :
|
||||
result = {
|
||||
'code' : -3,
|
||||
'message' : 'No products',
|
||||
'result' : []
|
||||
}
|
||||
return json.dumps(result)
|
||||
|
||||
|
||||
@http.route('/product/get', auth='public')
|
||||
def get_product(self):
|
||||
product_id = request.params.get('product_id')
|
||||
product_model = request.env['product.template']
|
||||
res = product_model.sudo().search_read([('id', '=' , product_id)],['lst_price', 'name'])
|
||||
result = {}
|
||||
if res :
|
||||
result['code'] = 4
|
||||
result['message'] = 'Request Done'
|
||||
else :
|
||||
result['code'] = 4
|
||||
result['message'] = 'No product'
|
||||
result['result'] = res
|
||||
return json.dumps(result)
|
||||
|
||||
|
||||
@http.route('/variant/all', auth='public')
|
||||
def all_vars(self):
|
||||
product_model = request.env['product.attribute.value']
|
||||
res = product_model.sudo().search_read([],['name'])
|
||||
if res :
|
||||
result = {
|
||||
'code' : 4,
|
||||
'message' : 'Request Done',
|
||||
'result' : res
|
||||
}
|
||||
else :
|
||||
result = {
|
||||
'code' : -4,
|
||||
'message' : 'No Records',
|
||||
'result' : []
|
||||
}
|
||||
return json.dumps(result)
|
||||
|
||||
|
||||
@http.route('/product_var/all', auth='public')
|
||||
def all_product_var(self):
|
||||
product_model = request.env['product.template.attribute.value']
|
||||
res = product_model.sudo().search_read([],['price_extra', 'product_tmpl_id', 'product_attribute_value_id'])
|
||||
if res :
|
||||
result = {
|
||||
'code' : 4,
|
||||
'message' : 'Request Done',
|
||||
'result' : res
|
||||
}
|
||||
else :
|
||||
result = {
|
||||
'code' : -4,
|
||||
'message' : 'No Records',
|
||||
'result' : []
|
||||
}
|
||||
return json.dumps(result)
|
||||
|
||||
|
||||
@http.route('/product_var/get', auth='public')
|
||||
def get_product_var(self):
|
||||
cond = []
|
||||
product_tmpl_id = request.params.get('product_id')
|
||||
product_attribute_value_id = request.params.get('var_id')
|
||||
product_model = request.env['product.template.attribute.value']
|
||||
if product_tmpl_id : cond += [('product_tmpl_id', '=' ,int(product_tmpl_id) )]
|
||||
if product_attribute_value_id : cond += [('product_attribute_value_id', '=' ,int(product_attribute_value_id) )]
|
||||
res = product_model.sudo().search_read(cond,['price_extra', 'product_tmpl_id', 'product_attribute_value_id'])
|
||||
if res :
|
||||
result = {
|
||||
'code' : 4,
|
||||
'message' : 'Request Done',
|
||||
'result' : res
|
||||
}
|
||||
else :
|
||||
result = {
|
||||
'code' : -4,
|
||||
'message' : 'No Records',
|
||||
'result' : []
|
||||
}
|
||||
return json.dumps(result)
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="0">
|
||||
|
||||
<!-- Sequences for maintenance request -->
|
||||
<record id="seq_maintenance_request" model="ir.sequence">
|
||||
<field name="name">Maintenance Request</field>
|
||||
<field name="code">maintenance.request</field>
|
||||
<field name="prefix">M</field>
|
||||
<field name="padding">5</field>
|
||||
<field name="company_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="maintenance_summary" model="maintenance.summary">
|
||||
<field name="name">Maintenance Summary</field>
|
||||
<field name="order_chart">Maintenance Order</field>
|
||||
<field name="priority_chart">Orders Priority</field>
|
||||
<field name="planned_chart">Planned Maintenacne</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,4 @@
|
|||
from . import maintenance
|
||||
from . import maintenance_asset
|
||||
from . import maintenance_checklist
|
||||
from . import maintenance_checklist_line
|
||||
|
|
@ -0,0 +1,659 @@
|
|||
from odoo import _, api, fields, models
|
||||
from datetime import datetime, timedelta, time
|
||||
from odoo.exceptions import RedirectWarning, UserError, ValidationError, AccessError
|
||||
from lxml import etree
|
||||
import simplejson # If not installed, you have to install it by executing pip install simplejson
|
||||
|
||||
from odoo.tools import get_lang
|
||||
|
||||
|
||||
class MaintenanceFailure(models.Model):
|
||||
_name = 'maintenance.failure'
|
||||
|
||||
name = fields.Char('Name', required=True)
|
||||
user_ids = fields.Many2many('res.users', 'failure_supervisor_rel', string='Engineers')
|
||||
|
||||
|
||||
class MaintenanceSpare(models.Model):
|
||||
_name = 'maintenance.request.spare'
|
||||
|
||||
spare_id = fields.Many2one('product.template', string='Spare', domain=[('is_spare', '=', True)])
|
||||
quantity = fields.Integer('Quantity')
|
||||
cost = fields.Float('Cost')
|
||||
request_id = fields.Many2one('maintenance.request', string='Related Request')
|
||||
total = fields.Float('Total', readonly=True, compute='_compute')
|
||||
|
||||
@api.depends('quantity', 'cost')
|
||||
def _compute(self):
|
||||
for rec in self:
|
||||
rec.total = rec.cost * rec.quantity
|
||||
|
||||
@api.onchange('spare_id')
|
||||
def onchange_spare(self):
|
||||
self.cost = self.spare_id.standard_price
|
||||
|
||||
|
||||
class MaintenanceSpare(models.Model):
|
||||
_name = 'maintenance.rootfailure'
|
||||
|
||||
name = fields.Char('Description')
|
||||
|
||||
|
||||
class MaintenanceRequestTask(models.Model):
|
||||
_name = 'maintenance.request.task'
|
||||
|
||||
name = fields.Char('name')
|
||||
employee_id = fields.Many2one('hr.employee', string='Employee')
|
||||
time = fields.Float('Executing Time')
|
||||
duration = fields.Float('Duration')
|
||||
is_done = fields.Boolean('Complete ?')
|
||||
request_id = fields.Many2one('maintenance.request', 'Maintenance Request')
|
||||
|
||||
|
||||
# inherit purchase request
|
||||
class PurchaseOrder(models.Model):
|
||||
_inherit = 'purchase.order'
|
||||
maintenance_id = fields.Many2one('maintenance.request', )
|
||||
|
||||
# end
|
||||
|
||||
class MaintenanceEquipmentRequest(models.Model):
|
||||
_inherit = 'maintenance.request'
|
||||
# todo start
|
||||
partner_id = fields.Many2one(comodel_name='res.partner', string='Partner',
|
||||
)
|
||||
product_category_ids = fields.Many2many('product.category', string='Items Categories')
|
||||
# todo end
|
||||
code = fields.Char('Request No', default='/')
|
||||
# todo start
|
||||
line_ids = fields.One2many(comodel_name='matrial.line', inverse_name='request_id', string='')
|
||||
# todo end
|
||||
failure_id = fields.Many2one('maintenance.failure', string='Failure Type')
|
||||
tool_ids = fields.Many2many('product.template', 'maintenance_tool_rel', string="Tools",
|
||||
domain=[('is_tool', '=', True)])
|
||||
spare_ids = fields.One2many('maintenance.request.spare', 'request_id', string="Spares")
|
||||
maintenance_team_id = fields.Many2one('maintenance.team', string='Team', check_company=True, )
|
||||
stage_type = fields.Selection(string='Stage Type', related='stage_id.stage_type')
|
||||
team_type = fields.Selection([('in', 'Internal Team'), ('out', 'Outsite Entity')], 'Team Type')
|
||||
out_entity_id = fields.Many2one('res.partner', 'Entity', domain=[('is_company', '=', True)])
|
||||
request_date = fields.Datetime('Request Date', tracking=True, default=fields.Datetime.now,
|
||||
help="Date requested for the maintenance to happen")
|
||||
dis_employee_ids = fields.Many2many('hr.employee', 'dis_req_member_rel', string='Team Members')
|
||||
employee_ids = fields.Many2many('hr.employee', 'req_member_rel', string='Team Members')
|
||||
employee_id = fields.Many2one('hr.employee', string='Employee')
|
||||
failure_desc = fields.Text('Failure Description')
|
||||
failure_cause_id = fields.Many2one('maintenance.rootfailure', string='Failure Root Cause')
|
||||
maintenance_work = fields.Text('Maintenance works')
|
||||
dis_priority = fields.Selection([('3', 'A'), ('2', 'B'), ('1', 'C')], string='Priority')
|
||||
priority = fields.Selection([('0', 'Very Low'), ('1', 'Low'), ('2', 'Normal'), ('3', 'High')], string='Priority')
|
||||
maintenance_time = fields.Float('Maintenance Duration')
|
||||
estimated_time = fields.Float('Estimated Duration')
|
||||
task_ids = fields.One2many('maintenance.request.task', 'request_id', string='Tasks')
|
||||
attachment = fields.Binary(string="Instruction Document", attachment=True)
|
||||
done_time = fields.Datetime('Complete Time')
|
||||
start_time = fields.Datetime('Maintenance Begin Time')
|
||||
entry_source = fields.Selection(
|
||||
[('request', 'Request Order'), ('order', 'Order Request'), ('job', 'Equipment Job')], string='Source',
|
||||
default='request')
|
||||
machine_status = fields.Selection(
|
||||
[('out_service', 'Out of Service'), ('part', 'Partially effect'), ('in_service', 'In Service')],
|
||||
string='Machine Status')
|
||||
maintenance_category = fields.Selection([('planned', 'Planned'), ('unplanned', 'Unplanned')],
|
||||
string="Maintenance category ")
|
||||
down_time = fields.Float('Down Time')
|
||||
purchase_create = fields.Boolean(string='Purchase_create')
|
||||
product_loss = fields.Float('losses of production')
|
||||
acquisition_date = fields.Date(string='Acquisition Date')
|
||||
department_id = fields.Many2one('hr.department', string='Department', related='employee_id.department_id',
|
||||
readonly=True, store=True)
|
||||
purchase_order_count = fields.Integer(compute='_compute_purchase_order_count')
|
||||
vendor_id = fields.Many2one(
|
||||
comodel_name='res.partner',
|
||||
string='Vendor',
|
||||
required=False)
|
||||
|
||||
purchase_order_id = fields.Many2one(
|
||||
string='Purchase Order',
|
||||
comodel_name='purchase.order',
|
||||
ondelete='restrict',
|
||||
)
|
||||
|
||||
# todo start
|
||||
def create_purchase_request(self):
|
||||
for rec in self:
|
||||
product_list = []
|
||||
for line in rec.line_ids:
|
||||
product_list.append((0, 6, {
|
||||
'product_id': line.product_id.id,
|
||||
'name': line.name,
|
||||
'price_unit': line.price_unit,
|
||||
'product_qty': line.qty,
|
||||
'product_uom': line.uom_id.id,
|
||||
'account_analytic_id': line.account_id.id,
|
||||
}))
|
||||
create_purchase = self.env['purchase.order'].create({
|
||||
'name': rec.name,
|
||||
'partner_id': rec.partner_id.id,
|
||||
'order_line': product_list,
|
||||
'maintenance_id': rec.id
|
||||
})
|
||||
rec.purchase_order_id = create_purchase.id
|
||||
return create_purchase
|
||||
|
||||
def _compute_purchase_order_count(self):
|
||||
for po in self:
|
||||
items = self.env['purchase.order'].search([
|
||||
('name', '=', self.name),
|
||||
])
|
||||
po.purchase_order_count = len(items)
|
||||
|
||||
def to_open_maintenance_purchase_order(self):
|
||||
xmlid = "purchase.purchase_rfq"
|
||||
action = self.env["ir.actions.act_window"]._for_xml_id(xmlid)
|
||||
action["domain"] = [('maintenance_id', '=', self.id)]
|
||||
action['context']= {'create': False,'edit':False}
|
||||
# action["views"] = [(self.env.ref("purchase.purchase_order_form").id, "form")]
|
||||
return action
|
||||
|
||||
# return {'name': _('Maintenance Purchase Orders'),
|
||||
# 'type': 'ir.actions.act_window',
|
||||
# 'res_model': 'purchase.order',
|
||||
# 'view_mode': 'tree',
|
||||
# 'domain': [('maintenance_id', '=', self.id)],
|
||||
# 'context': "{'create': False,'edit':True}"
|
||||
# # 'target': 'new'
|
||||
# }
|
||||
|
||||
def request_order_creation(self):
|
||||
for rec in self:
|
||||
if not self.env.user.has_group('maintenance_custom.maintenance_order_stage_visibility_stage_group'):
|
||||
raise UserError(_('You cannot Make This Order Please Contact Your Administrator To Make Your Order'))
|
||||
else:
|
||||
res = self.env['maintenance.stage'].search([('stage_type', '=', 'confirm')])
|
||||
if res:
|
||||
rec.stage_id = res
|
||||
|
||||
def maintenance_order_creation(self):
|
||||
for rec in self:
|
||||
if not self.env.user.has_group('maintenance_custom.request_order_stage'):
|
||||
raise UserError(_('You cannot Make This Order Please Contact Your Administrator To Make Your Order'))
|
||||
else:
|
||||
res = self.env['maintenance.stage'].search([('stage_type', '=', 'for_order')])
|
||||
if res:
|
||||
rec.stage_id = res
|
||||
|
||||
def maintenance_order_done(self):
|
||||
for rec in self:
|
||||
if not self.env.user.has_group('maintenance_custom.maintenance_order_done'):
|
||||
raise UserError(_('You cannot Make This Order Please Contact Your Administrator To Make Your Order'))
|
||||
else:
|
||||
res = self.env['maintenance.stage'].search([('stage_type', '=', 'repair_done')])
|
||||
if res:
|
||||
rec.stage_id = res
|
||||
|
||||
def maintenance_order_cancel(self):
|
||||
for rec in self:
|
||||
if not self.env.user.has_group('maintenance_custom.maintenance_order_stage_cancel_visibility_stage_group'):
|
||||
raise UserError(_('You cannot Make Cancel For This Order Please Contact Your Administrator'))
|
||||
else:
|
||||
res = self.env['maintenance.stage'].search([('stage_type', '=', 'cancel')])
|
||||
if res:
|
||||
rec.stage_id = res
|
||||
|
||||
def order_set_to_draft(self):
|
||||
for rec in self:
|
||||
if not self.env.user.has_group('maintenance_custom.maintenance_order_set_to_draft'):
|
||||
raise UserError(_('You cannot Make Set To Draft Please Contact Your Administrator'))
|
||||
else:
|
||||
res = self.env['maintenance.stage'].search([('stage_type', '=', 'draft')])
|
||||
if res:
|
||||
rec.stage_id = res
|
||||
|
||||
def get_po(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': 'Purchase Request',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'purchase.request',
|
||||
'domain': [('maintenance_id', '=', self.id)],
|
||||
'context': "{'create': False}"
|
||||
}
|
||||
|
||||
# todo end
|
||||
|
||||
@api.onchange('stage_id')
|
||||
def _onchange_stage_id(self):
|
||||
print("iam here=================", self.stage_id.sequence)
|
||||
now = datetime.now()
|
||||
if self.stage_id.stage_type == 'confirm':
|
||||
self.request_date = now
|
||||
# self.fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False)
|
||||
|
||||
@api.model
|
||||
def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
|
||||
"""
|
||||
Overrides orm field_view_get.
|
||||
@return: Dictionary of Fields, arch and toolbar.
|
||||
"""
|
||||
|
||||
res = super(MaintenanceEquipmentRequest, self).fields_view_get(view_id=view_id, view_type=view_type,
|
||||
toolbar=toolbar, submenu=submenu)
|
||||
# if doc.xpath("//field[@name='city_id']")
|
||||
if self.env.context: # Check for context value
|
||||
doc = etree.XML(res['arch']) # Get the view architecture of record
|
||||
if view_type == 'form': # Applies only if it is form view
|
||||
for node in doc.xpath("//field"): # Get all the fields navigating through xpath
|
||||
modifiers = simplejson.loads(node.get("modifiers")) # Get all the existing modifiers of each field
|
||||
modifiers['readonly'] = False # Add readonly=True attribute in modifier for each field
|
||||
node.set('modifiers',
|
||||
simplejson.dumps(modifiers)) # Now, set the newly added modifiers to the field
|
||||
res['arch'] = etree.tostring(doc) # Update the view architecture of record with new architecture
|
||||
return res
|
||||
|
||||
@api.onchange('dis_employee_ids', 'user_id', 'team_type')
|
||||
def onchange_members(self):
|
||||
member_ids = []
|
||||
if self.user_id:
|
||||
res = self.env.get('hr.employee').search([('user_id', '=', self.user_id.id)])
|
||||
if res: member_ids.append(res[0].id)
|
||||
if self.dis_employee_ids and self.team_type == 'in':
|
||||
member_ids += self.dis_employee_ids.ids
|
||||
self.employee_ids = [(6, 0, member_ids)]
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
vals['code'] = self.env['ir.sequence'].next_by_code('maintenance.request') or _('New')
|
||||
if 'dis_priority' in vals:
|
||||
vals['priority'] = vals['dis_priority']
|
||||
obj = super(MaintenanceEquipmentRequest, self).create(vals)
|
||||
obj.onchange_members()
|
||||
return obj
|
||||
|
||||
# @api.onchange('failure_id','maintenance_type')
|
||||
# def onchange_failure(self):
|
||||
# domain = [('id','>','0')]
|
||||
# if self.maintenance_type == 'corrective':
|
||||
# dom = self.failure_id and self.failure_id.user_ids.ids or []
|
||||
# domain = [('id', 'in', dom)]
|
||||
# return {
|
||||
# 'value' : {'user_id' : False},
|
||||
# 'domain' : {
|
||||
# 'user_id' : domain
|
||||
# }
|
||||
# }
|
||||
|
||||
def write(self, vals):
|
||||
stage = self.env.get('maintenance.stage')
|
||||
user = self.env.user
|
||||
user_id = user.id
|
||||
if 'dis_priority' in vals:
|
||||
vals['priority'] = vals['dis_priority']
|
||||
if 'stage_id' in vals:
|
||||
new_value = vals['stage_id']
|
||||
old = self.stage_id
|
||||
new = stage.browse(new_value)
|
||||
|
||||
if old.sequence > new.sequence:
|
||||
if old.pre_stage_ids.ids and new_value not in old.pre_stage_ids.ids:
|
||||
raise UserError(_('You cannot use return back to this stage.'))
|
||||
else:
|
||||
if self.stage_id.next_stage_ids and new_value not in self.stage_id.next_stage_ids.ids:
|
||||
raise UserError(_('You cannot use go forword to this stage.'))
|
||||
|
||||
if new.stage_type == 'confirm':
|
||||
if 'employee_id' in vals:
|
||||
em = vals['employee_id']
|
||||
em_id = self.env.get('hr.employee').browse(em)
|
||||
if user_id != em_id.user_id.id:
|
||||
raise UserError(_('You cannot use confrim this request,only requester can perform this action'))
|
||||
else:
|
||||
em_id = self.employee_id
|
||||
if em_id and user_id != em_id.user_id.id:
|
||||
raise UserError(_('You cannot use confrim this request,only requester can perform this action'))
|
||||
now = datetime.now()
|
||||
self.write({'request_date': now})
|
||||
|
||||
if new.stage_type == 'for_order':
|
||||
if self.user_id and self.user_id.id != user_id:
|
||||
raise UserError(_('Only user who create the work order can perform this action'))
|
||||
teams = self.maintenance_team_id.member_ids.ids
|
||||
print("tems================", teams)
|
||||
if user_id not in teams:
|
||||
print("in here===========")
|
||||
raise UserError(_('Only team members for current department team can perform this action'))
|
||||
# if 'equipment_id' in vals:
|
||||
# equipment = vals['equipment_id']
|
||||
# equipment_id = self.env.get('maintenance.equipment').browse(equipment)
|
||||
# if user_id not in equipment_id.maintenance_team_id.member_ids.ids:
|
||||
# raise UserError(_('Only team members can perform this action'))
|
||||
# else:
|
||||
|
||||
# if self.equipment_id and user_id not in self.equipment_id.maintenance_team_id.member_ids.ids:
|
||||
# raise UserError(_('Only team members can perform this action'))
|
||||
self.write({'user_id': user_id})
|
||||
|
||||
if new.stage_type == 'repair_done':
|
||||
if 'user_id' in vals:
|
||||
usr = vals['user_id']
|
||||
usr_id = self.env.get('res.users').browse(usr)
|
||||
# teams = self.env.get('maintenance.team').search([('department_id','=',self.department_id.id)]).member_ids.ids
|
||||
if usr_id and usr_id.id != user_id:
|
||||
raise UserError(
|
||||
_('You cannot use process this request,only supervisor can perform this action'))
|
||||
else:
|
||||
usr_id = self.user_id
|
||||
if usr_id and usr_id.id != user_id:
|
||||
raise UserError(
|
||||
_('You cannot use process this request,only supervisor can perform this action'))
|
||||
|
||||
if new.stage_type == 'request_done':
|
||||
if 'employee_id' in vals:
|
||||
em = vals['employee_id']
|
||||
em_id = self.env.get('hr.employee').browse(em)
|
||||
if user_id != em_id.user_id.id:
|
||||
raise UserError(_('You cannot confirm this request,only requester can perform this action'))
|
||||
else:
|
||||
em_id = self.employee_id
|
||||
if em_id and user_id != em_id.user_id.id:
|
||||
raise UserError(_('You cannot confrim this request,only requester can perform this action'))
|
||||
return super(MaintenanceEquipmentRequest, self).write(vals)
|
||||
|
||||
|
||||
# add new class
|
||||
class MatrialMaintenanceRequest(models.Model):
|
||||
_name = 'matrial.line'
|
||||
_description = 'Matrial maintenacerequest line'
|
||||
|
||||
# for test
|
||||
account_id = fields.Many2one('account.analytic.account', 'Analytic Account', readonly=False, )
|
||||
request_id = fields.Many2one(comodel_name='maintenance.request', string='Request Ref.')
|
||||
product_id = fields.Many2one(comodel_name='product.product', string='Item')
|
||||
qty = fields.Integer(string='Qty')
|
||||
name = fields.Char(string='Descrption')
|
||||
price_unit = fields.Float(string='Unit Price', digits='Product Price')
|
||||
uom_id = fields.Many2one('uom.uom', related='product_id.uom_id', string='Unit of Measure')
|
||||
sum_total = fields.Float(string="sum_total")
|
||||
|
||||
@api.onchange('qty', 'price_unit')
|
||||
def total_sum_lines(self):
|
||||
sum_total = 0
|
||||
# for line in self.line_ids:
|
||||
if self.price_unit and self.qty:
|
||||
self.sum_total = self.qty * self.price_unit
|
||||
|
||||
# get price for product
|
||||
def _product_id_change(self):
|
||||
if not self.product_id:
|
||||
return
|
||||
|
||||
product_lang = self.product_id.with_context(
|
||||
lang=get_lang(self.env, self.partner_id.lang).code,
|
||||
partner_id=self.partner_id.id,
|
||||
company_id=self.company_id.id,
|
||||
)
|
||||
self.name = self._get_product_purchase_description(product_lang)
|
||||
|
||||
@api.constrains('qty')
|
||||
def qty_validation(self):
|
||||
for rec in self:
|
||||
if rec.qty <= 0:
|
||||
raise ValidationError(_("Item Quantity MUST be at Least ONE!"))
|
||||
|
||||
|
||||
# end
|
||||
|
||||
class MaintenanceStage(models.Model):
|
||||
_inherit = 'maintenance.stage'
|
||||
|
||||
for_order = fields.Boolean('use for Order ?')
|
||||
stage_type = fields.Selection([
|
||||
('draft', 'Draft'),
|
||||
('confirm', 'Confirm'),
|
||||
('for_order', 'Orders'),
|
||||
('repair_done', 'Repair Done'),
|
||||
('cancel', 'Cancel'),
|
||||
])
|
||||
|
||||
next_stage_ids = fields.Many2many(
|
||||
string='Next Stage',
|
||||
comodel_name='maintenance.stage',
|
||||
relation='model_request_next_rel',
|
||||
column1='request_id',
|
||||
column2='stage_id',
|
||||
)
|
||||
|
||||
pre_stage_ids = fields.Many2many(
|
||||
string='Previous Stage',
|
||||
comodel_name='maintenance.stage',
|
||||
relation='model_request_pre_rel',
|
||||
column1='request_id',
|
||||
column2='stage_id',
|
||||
)
|
||||
|
||||
|
||||
class Product(models.Model):
|
||||
_inherit = 'product.template'
|
||||
|
||||
is_spare = fields.Boolean('Spare')
|
||||
is_tool = fields.Boolean('Tools')
|
||||
|
||||
|
||||
class EquipmentMaintenaceTasks(models.Model):
|
||||
_name = 'maintenance.equipment.task'
|
||||
|
||||
job_id = fields.Many2one('maintenance.equipment.job', string='Related Maintenance Job')
|
||||
jobs_id = fields.Many2one('maintenance.equipments.jobs', string='Related Maintenance Job')
|
||||
name = fields.Char('Decription')
|
||||
sequence = fields.Integer('Sequence')
|
||||
|
||||
|
||||
class EquipmentMaintenaceJob(models.Model):
|
||||
_name = 'maintenance.equipment.job'
|
||||
|
||||
name = fields.Char('Decription')
|
||||
equipment_id = fields.Many2one('maintenance.equipment', string='Equipment')
|
||||
start_date = fields.Date('Maintenance Begin Date')
|
||||
next_action_date = fields.Date('Next Preventive')
|
||||
period = fields.Integer('Preventive Maintenance Frequency')
|
||||
period_type = fields.Selection([('hour', 'By Hour'), ('day', 'Daily'), ('weekly', 'Weekly'),('month', 'Monthly'), ('year', 'Yearly')])
|
||||
maintenance_time = fields.Float('Maintenance Duration')
|
||||
user_id = fields.Many2one('res.users', string='supervisor')
|
||||
active = fields.Boolean('Active', default=True)
|
||||
task_ids = fields.One2many('maintenance.equipment.task', 'job_id', string='Tasks')
|
||||
attachment = fields.Binary(string="Instruction Document", attachment=True)
|
||||
|
||||
@api.onchange('start_date')
|
||||
def onchange_start_date(self):
|
||||
self.next_action_date = self.start_date
|
||||
|
||||
def write(self, vals):
|
||||
if 'start_date' in vals:
|
||||
vals['next_action_date'] = vals['start_date']
|
||||
return super(EquipmentMaintenaceJob, self).write(vals)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if 'start_date' in vals:
|
||||
vals['next_action_date'] = vals['start_date']
|
||||
return super(EquipmentMaintenaceJob, self).create(vals)
|
||||
|
||||
class EquipmentsMaintenacesJobs(models.Model):
|
||||
_name = 'maintenance.equipments.jobs'
|
||||
|
||||
name = fields.Char('Decription')
|
||||
equipments_id = fields.Many2many('maintenance.equipment', string='Equipments')
|
||||
equipment_id = fields.Many2one('maintenance.equipment', string='Equipments')
|
||||
start_date = fields.Date('Maintenance Begin Date')
|
||||
next_action_date = fields.Date('Next Preventive')
|
||||
period = fields.Integer('Preventive Maintenance Frequency')
|
||||
period_type = fields.Selection([('hour', 'By Hour'), ('day', 'Daily'), ('weekly', 'Weekly'),('month', 'Monthly'), ('year', 'Yearly')])
|
||||
maintenance_time = fields.Float('Maintenance Duration')
|
||||
user_id = fields.Many2one('res.users', string='supervisor')
|
||||
active = fields.Boolean('Active', default=True)
|
||||
task_ids = fields.One2many('maintenance.equipment.task', 'jobs_id', string='Tasks')
|
||||
attachment = fields.Binary(string="Instruction Document", attachment=True)
|
||||
|
||||
@api.onchange('start_date')
|
||||
def onchange_start_date(self):
|
||||
self.next_action_date = self.start_date
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
# Create a record in the current model
|
||||
if 'start_date' in vals:
|
||||
vals['next_action_date'] = vals['start_date']
|
||||
job = super(EquipmentsMaintenacesJobs, self).create(vals)
|
||||
ids= vals['equipments_id'][0][2]
|
||||
equipments = self.env['maintenance.equipment'].browse(ids)
|
||||
tasks = [(0, 0, {'name': t.name}) for t in job.task_ids]
|
||||
for equipment in equipments:
|
||||
equipment.write({
|
||||
'job_ids': [(0, 0,{
|
||||
'name':job.name,
|
||||
'equipment_id':equipment.id,
|
||||
'start_date':job.start_date,
|
||||
'next_action_date':job.next_action_date,
|
||||
'period':job.period,
|
||||
'period_type':job.period_type,
|
||||
'maintenance_time':job.maintenance_time,
|
||||
'user_id':job.user_id.id,
|
||||
'active':job.active,
|
||||
'task_ids':tasks,
|
||||
'attachment':job.attachment
|
||||
})]})
|
||||
return job
|
||||
|
||||
def write(self, vals):
|
||||
if 'start_date' in vals:
|
||||
vals['next_action_date'] = vals['start_date']
|
||||
# ids = self.equipments_id.ids
|
||||
# equipments = self.env['maintenance.equipment'].browse(ids)
|
||||
# tasks = [(0, 0, {'name': t.name, 'job_id': self.id}) for t in self.task_ids]
|
||||
# # Update related equipment records
|
||||
# for equipment in equipments:
|
||||
# equipment.write({
|
||||
# 'job_ids': [(0,0, {
|
||||
# 'name': self.name,
|
||||
# 'equipment_id': equipment.id,
|
||||
# 'start_date': self.start_date,
|
||||
# 'next_action_date': self.next_action_date,
|
||||
# 'period': self.period,
|
||||
# 'period_type': self.period_type,
|
||||
# 'maintenance_time': self.maintenance_time,
|
||||
# 'user_id': self.user_id.id,
|
||||
# 'active': self.active,
|
||||
# 'task_ids': tasks,
|
||||
# 'attachment': self.attachment
|
||||
# })]})
|
||||
return super(EquipmentsMaintenacesJobs, self).write(vals)
|
||||
|
||||
def creat_equi(self):
|
||||
self.equipment_id.create_maintenance_jobs()
|
||||
|
||||
|
||||
|
||||
|
||||
class MaintenanceEquipment(models.Model):
|
||||
_inherit = 'maintenance.equipment'
|
||||
|
||||
job_ids = fields.One2many('maintenance.equipment.job', 'equipment_id')
|
||||
location2 = fields.Many2one('equipment.locations')
|
||||
job_ids_for_equipments = fields.One2many('maintenance.equipments.jobs', 'equipments_id')
|
||||
|
||||
# This is cron job for maintenance request for only one equipment
|
||||
def create_maintenance_job(self):
|
||||
current_date = fields.Date.today()
|
||||
job_model = self.env.get('maintenance.equipment.job')
|
||||
res_job = job_model.search([('next_action_date', '=', current_date)])
|
||||
order_model = self.env.get('maintenance.request')
|
||||
res_stage = self.env.get('maintenance.stage').search([('stage_type', '=', 'for_order')], order='sequence')
|
||||
stage_id = res_stage and res_stage[0].id or False
|
||||
for job in res_job:
|
||||
tasks = [(0, 0, {'name': t.name}) for t in job.task_ids]
|
||||
res_order = order_model.create({
|
||||
'name': job.name,
|
||||
'user_id': job.user_id.id,
|
||||
'stage_id': stage_id,
|
||||
'maintenance_type': 'preventive',
|
||||
'task_ids': tasks,
|
||||
'attachment': job.attachment,
|
||||
'entry_source': 'job',
|
||||
'equipment_id': job.equipment_id.id,
|
||||
'schedule_date': current_date,
|
||||
})
|
||||
#This is for maintenance request for group of equipments at the same time
|
||||
def create_maintenance_jobs(self):
|
||||
current_date = fields.Date.today()
|
||||
jobs_model = self.env.get('maintenance.equipments.jobs')
|
||||
res_job = jobs_model.search([('next_action_date', '=', current_date)])
|
||||
order_model = self.env.get('maintenance.request')
|
||||
res_stage = self.env.get('maintenance.stage').search([('stage_type', '=', 'for_order')], order='sequence')
|
||||
stage_id = res_stage and res_stage[0].id or False
|
||||
for job in res_job:
|
||||
tasks = [(0, 0, {'name': t.name}) for t in job.task_ids]
|
||||
for equipment in job.equipments_id:
|
||||
res_order = order_model.create({
|
||||
'name': job.name,
|
||||
'user_id': job.user_id.id,
|
||||
'stage_id': stage_id,
|
||||
'maintenance_type': 'preventive',
|
||||
'task_ids': tasks,
|
||||
'attachment': job.attachment,
|
||||
'entry_source': 'job',
|
||||
'equipment_id': equipment.id,
|
||||
'schedule_date': current_date,
|
||||
})
|
||||
|
||||
class MaintenanceSummary(models.Model):
|
||||
_name = 'maintenance.summary'
|
||||
|
||||
name = fields.Char('Description')
|
||||
total_orders = fields.Integer('Total Orders', compute='_compute_total')
|
||||
total_open = fields.Integer('Open', compute='_compute_total')
|
||||
total_repair = fields.Integer('Repaired', compute='_compute_total')
|
||||
total_close = fields.Integer('Closed', compute='_compute_total')
|
||||
order_chart = fields.Char('Maintenance Orders')
|
||||
priority_chart = fields.Char('Priority')
|
||||
total_low = fields.Integer('Low', compute='_compute_total')
|
||||
total_normal = fields.Integer('Normal', compute='_compute_total')
|
||||
total_high = fields.Integer('High', compute='_compute_total')
|
||||
planned_chart = fields.Char('Planned Maintenacne')
|
||||
total_planned = fields.Integer('Planned', compute='_compute_total')
|
||||
total_unplanned = fields.Integer('Un Planned', compute='_compute_total')
|
||||
total_partially_effect = fields.Integer('Total Partiall Effect', compute='_compute_total')
|
||||
total_downtime = fields.Integer('Total Downtime', compute='_compute_total')
|
||||
total_outservice = fields.Integer('Total Out of Service', compute='_compute_total')
|
||||
total_loss = fields.Integer('Loss of Production', compute='_compute_total')
|
||||
|
||||
def _compute_total(self):
|
||||
order_model = self.env.get('maintenance.request')
|
||||
stage_model = self.env.get('maintenance.stage')
|
||||
stage_close = stage_model.search([('stage_type', '=', 'request_done')]).ids
|
||||
stage_repair = stage_model.search([('stage_type', '=', 'repair_done')]).ids
|
||||
stage_open = stage_model.search([('stage_type', 'not in', ['repair_done', 'request_done'])]).ids
|
||||
self.total_orders = order_model.search_count([])
|
||||
self.total_open = order_model.search_count([('stage_id', 'in', stage_open)])
|
||||
self.total_repair = order_model.search_count([('stage_id', 'in', stage_repair)])
|
||||
self.total_close = order_model.search_count([('stage_id', 'in', stage_close)])
|
||||
self.total_low = order_model.search_count([('priority', '=', 1)])
|
||||
self.total_normal = order_model.search_count([('priority', '=', 2)])
|
||||
self.total_high = order_model.search_count([('priority', '=', 3)])
|
||||
self.total_planned = order_model.search_count([('maintenance_category', '=', 'planned')])
|
||||
self.total_unplanned = order_model.search_count(
|
||||
['|', ('maintenance_category', '=', 'unplanned'), ('maintenance_category', '=', False)])
|
||||
self.total_partially_effect = order_model.search_count([('machine_status', '=', 'part')])
|
||||
self.total_outservice = order_model.search_count([('machine_status', '=', 'out_service')])
|
||||
total_loss = 0
|
||||
total_downtime = 0
|
||||
for req in order_model.search([('machine_status', '=', 'part')]):
|
||||
total_loss += req.product_loss
|
||||
for req in order_model.search([('machine_status', '=', 'out_service')]):
|
||||
total_downtime += req.down_time
|
||||
self.total_downtime = total_downtime
|
||||
self.total_loss = total_loss
|
||||
|
||||
class Locations(models.Model):
|
||||
_name = 'equipment.locations'
|
||||
|
||||
name = fields.Char('Description')
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
from odoo import api, fields, models
|
||||
|
||||
class MaintenanceAsset(models.Model):
|
||||
_inherit = 'maintenance.request'
|
||||
|
||||
asset_id = fields.Many2one(string="Asset",
|
||||
comodel_name='account.asset',
|
||||
required=False)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
from odoo import api, fields, models
|
||||
|
||||
class MaintenanceChecklist(models.Model):
|
||||
_inherit = 'maintenance.request'
|
||||
|
||||
checklist_lines = fields.One2many(
|
||||
comodel_name='checklist.line',
|
||||
inverse_name='checklist_id',
|
||||
string='Checklist',
|
||||
required=False)
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class MaintenanceChecklistLines(models.Model):
|
||||
_name = 'checklist.line'
|
||||
_description = 'Inspection Checklist For Maintenance Lines'
|
||||
|
||||
|
||||
name = fields.Char(
|
||||
string='Name',
|
||||
required=True)
|
||||
description = fields.Char(
|
||||
string='Description',
|
||||
required=False)
|
||||
checklist_id = fields.Many2one(
|
||||
comodel_name='maintenance.request',
|
||||
string='',
|
||||
required=False)
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
from . import general_maintenance_report
|
||||
|
|
@ -0,0 +1,242 @@
|
|||
<odoo>
|
||||
<template id="equipment_report">
|
||||
<t t-call="web.html_container">
|
||||
<t t-call="web.external_layout">
|
||||
<style>
|
||||
body{
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.date_tb{
|
||||
display: table;
|
||||
}
|
||||
|
||||
.date_th{
|
||||
display: table;
|
||||
}
|
||||
.date_tb div{
|
||||
display: table-cell;
|
||||
border-color: #888888;
|
||||
border: 1px solid #dee2e6;
|
||||
padding: 10px;
|
||||
min-width:30px;
|
||||
}
|
||||
.date_th{
|
||||
background-color: #dee2e6;
|
||||
}
|
||||
.box{
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
margin-top:10px;
|
||||
width: 150px;
|
||||
height: 100px;
|
||||
min-width: 150px;
|
||||
min-height: 100px;
|
||||
max-width: 150px;
|
||||
max-height: 100px;
|
||||
color:white;
|
||||
font-weight:bold;
|
||||
}
|
||||
.box-title{
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.box-content{
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.main-box-container, date_th{
|
||||
margin:30px;
|
||||
}
|
||||
|
||||
.box-container{
|
||||
|
||||
}
|
||||
.main-box-container .left{
|
||||
float: left;
|
||||
margin-top:10px;
|
||||
}
|
||||
|
||||
.main-box-container .right{
|
||||
margin-left:300px;
|
||||
}
|
||||
.main-box-container .row{
|
||||
display: table;
|
||||
border-spacing: 20px;
|
||||
}
|
||||
|
||||
.main-box-container .row .box{
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.data_tb{
|
||||
text-align:center;
|
||||
}
|
||||
.data_tb th, #filters_tb th{
|
||||
background-color: #dee2e6;
|
||||
}
|
||||
|
||||
.data_tb td , .data_tb th{
|
||||
border-color: #888888;
|
||||
border: 1px solid black;
|
||||
padding: 10px;
|
||||
min-width:30px;
|
||||
|
||||
}
|
||||
|
||||
#filters_tb, #filters_tb th, #filters_tb td{
|
||||
border: 1px solid black;
|
||||
text-align : center;
|
||||
padding : 15px;
|
||||
}
|
||||
|
||||
#filters_tb th, #filters_tb td{
|
||||
min-width: 150px;
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
.zooba{
|
||||
background-color:#66CDAA;
|
||||
|
||||
}
|
||||
|
||||
.over{
|
||||
background-color:#DC143C;
|
||||
}
|
||||
|
||||
.high{
|
||||
background-color:red;
|
||||
}
|
||||
.open{
|
||||
background-color:#FFD700;
|
||||
}
|
||||
.closed{
|
||||
background-color:#228B22 ;
|
||||
}
|
||||
.total_work_order{
|
||||
background-color:#87CEFA ;
|
||||
}
|
||||
.plan{
|
||||
background-color:#6495ED ;
|
||||
}
|
||||
.hours{
|
||||
background-color:#1E90FF ;
|
||||
}
|
||||
.cost{
|
||||
background-color:#663399 ;
|
||||
}
|
||||
.downtime{
|
||||
background-color:#9370DB ;
|
||||
}
|
||||
.loss{
|
||||
background-color:#4B0082 ;
|
||||
}
|
||||
</style>
|
||||
|
||||
<center>
|
||||
<table id="filters_tb">
|
||||
<tr>
|
||||
<th>Date From</th>
|
||||
<th>Date To</th>
|
||||
<th>Equipment</th>
|
||||
<th>Category</th>
|
||||
<th>Opreater</th>
|
||||
<th>Spare Part</th>
|
||||
<th>Machine Status</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span t-esc="time_from" /></td>
|
||||
<td><span t-esc="time_to" /> </td>
|
||||
<td><span t-esc="filters.get('equipment_id', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('category_id', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('user_id', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('spare_id', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('machine_status', 'ALL')" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="main-box-container">
|
||||
<div class="row">
|
||||
<div class="box zooba">
|
||||
<div class="box-title">TOTAL EQUIPMENT</div>
|
||||
<div class="box-content"><span t-esc="total['total_equipment']" /></div>
|
||||
</div>
|
||||
<!--div class="box total_work_order">
|
||||
<div class="box-title">TOTAL Requests</div>
|
||||
<div class="box-content"><span t-esc="total['total_orders']" /></div>
|
||||
</div>
|
||||
<div class="box total_work_order">
|
||||
<div class="box-title">TOTAL WORK ORDERS</div>
|
||||
<div class="box-content"><span t-esc="total['total_orders']" /></div>
|
||||
</div-->
|
||||
<div class="box high">
|
||||
<div class="box-title">HIGH PRIORITY</div>
|
||||
<div class="box-content"><span t-esc="total['total_high']" /></div>
|
||||
</div>
|
||||
<div class="box open">
|
||||
<div class="box-title">OPEN ORDERS</div>
|
||||
<div class="box-content"><span t-esc="total['total_open']" /></div>
|
||||
</div>
|
||||
<div class="box closed">
|
||||
<div class="box-title">CLOSED ORDERS</div>
|
||||
<div class="box-content"><span t-esc="total['total_colse']" /></div>
|
||||
</div>
|
||||
<div class="box plan">
|
||||
<div class="box-title">PLANNED VS UNPLANNED</div>
|
||||
<div class="box-content"><span t-esc="total['total_planned']" />%</div>
|
||||
</div>
|
||||
<div class="box downtime">
|
||||
<div class="box-title">TOTAL DOWNTIME</div>
|
||||
<div class="box-content"><span t-esc="total['total_downtime']" /> H</div>
|
||||
</div>
|
||||
<div class="box loss">
|
||||
<div class="box-title">TOTAL LOSSES</div>
|
||||
<br />
|
||||
<div class="box-content"><span t-esc="total['total_loss']" /> Units</div>
|
||||
</div>
|
||||
<div class="box cost">
|
||||
<div class="box-title">Repair COST</div>
|
||||
<div class="box-content"><span t-esc="total['total_cost']" /> SDG</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="data_tb">
|
||||
<tr>
|
||||
<th>NO</th>
|
||||
<th>EQUIPMENT</th>
|
||||
<th>Vendor</th>
|
||||
<th>Opreater</th>
|
||||
<th>Category</th>
|
||||
<th>Corrective Maintenance</th>
|
||||
<th>Preventive Maintenance</th>
|
||||
<th>Machine Status</th>
|
||||
<th>Down-Time</th>
|
||||
<th>Losses</th>
|
||||
<th>Cost</th>
|
||||
</tr>
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<tr>
|
||||
<td><span t-esc="o_index+1"/></td>
|
||||
<td><span t-esc="o['name']"/></td>
|
||||
<td><span t-esc="o['vendor']"/></td>
|
||||
<td><span t-esc="o['opreater']"/></td>
|
||||
<td><span t-esc="o['category']"/></td>
|
||||
<td><span t-esc="o['corrective']"/></td>
|
||||
<td><span t-esc="o['preventive']"/></td>
|
||||
<td><span t-esc="o['machine_status']"/></td>
|
||||
<td><span t-esc="o['down_time']"/></td>
|
||||
<td><span t-esc="o['loss']"/></td>
|
||||
<td><span t-esc="o['cost']"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</table>
|
||||
</center>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
def to_str(array):
|
||||
return ",".join(str(i) for i in array)
|
||||
|
||||
|
||||
class GeneralMaintenanceReport(models.AbstractModel):
|
||||
_name = 'report.maintenance_custom.general_maintenance_report'
|
||||
@api.model
|
||||
def _get_report_values(self, docids, data=None):
|
||||
report_obj = self.env['ir.actions.report']
|
||||
report = report_obj._get_report_from_name('maintenance_custom.general_maintenance_report')
|
||||
rec_ids = data['form']['rec_ids']
|
||||
docs = self.env.get(report.model).search([('id' , 'in', rec_ids)])
|
||||
docargs = {
|
||||
'doc_ids': docids,
|
||||
'doc_model': report.model,
|
||||
'docs': docs,
|
||||
}
|
||||
docargs.update(data['form'])
|
||||
return docargs
|
||||
|
||||
|
||||
class SparePartReport(models.AbstractModel):
|
||||
_name = 'report.maintenance_custom.spare_part_report'
|
||||
|
||||
def _get_spare_data(self,order_ids,spare_ids,spare_categ_ids):
|
||||
cond = ""
|
||||
if spare_ids:
|
||||
cond += " AND spare_id in (%s)"%(to_str(spare_ids),)
|
||||
if spare_categ_ids:
|
||||
cond += " AND categ_id in (%s)"%(to_str(spare_categ_ids),)
|
||||
query = '''
|
||||
select
|
||||
spare_id as spare_id ,p.name as name, count(request_id) as order_count ,
|
||||
sum(down_time) as down_time , sum(product_loss) as loss, sum(quantity * cost) as cost,
|
||||
sum(quantity) as consume , cat.name as category
|
||||
from maintenance_request_spare sp
|
||||
join maintenance_request req on sp.request_id = req.id
|
||||
join product_template p on p.id = spare_id
|
||||
join product_category cat on cat.id = p.categ_id
|
||||
where request_id in (%s) %s
|
||||
group by spare_id, p.id, cat.id
|
||||
'''%(to_str(order_ids),cond)
|
||||
self.env.cr.execute(query)
|
||||
res = self.env.cr.dictfetchall()
|
||||
spare_model = self.env.get('product.template')
|
||||
for rec in res:
|
||||
sn = spare_model.browse(rec['spare_id']).barcode or '-'
|
||||
qty = spare_model.browse(rec['spare_id']).qty_available
|
||||
rec.update({'sn' : sn , 'stock' : qty})
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _get_report_values(self, docids, data=None):
|
||||
report_obj = self.env['ir.actions.report']
|
||||
report = report_obj._get_report_from_name('maintenance_custom.spare_part_report')
|
||||
rec_ids = data['form']['rec_ids']
|
||||
spare_categ_ids = data['form']['spare_categ_ids']
|
||||
spare_ids = data['form']['spare_ids']
|
||||
docs = self._get_spare_data(rec_ids,spare_ids,spare_categ_ids)
|
||||
docargs = {
|
||||
'doc_ids': docids,
|
||||
'doc_model': report.model,
|
||||
'docs': docs,
|
||||
}
|
||||
docargs.update(data['form'])
|
||||
return docargs
|
||||
|
||||
class EquipmentReport(models.AbstractModel):
|
||||
_name = 'report.maintenance_custom.equipment_report'
|
||||
|
||||
def _get_data(self,order_ids,equipment_ids=None,category_ids=None):
|
||||
cond = ""
|
||||
if equipment_ids:
|
||||
cond += " AND eq.id in (%s)"%(to_str(equipment_ids),)
|
||||
if category_ids:
|
||||
cond += " AND categ.id in (%s)"%(to_str(category_ids),)
|
||||
order_str = ','.join(str(i) for i in order_ids)
|
||||
query = '''
|
||||
SELECT
|
||||
eq.id as equipment_id , eq.name , vendor_partner.name as vendor , op_partner.name as opreater , categ.name as category,
|
||||
sum(req.down_time) as down_time , sum(req.product_loss) as loss,
|
||||
count(corrective.id) as corrective, count(preventive.id) as preventive
|
||||
FROM maintenance_equipment eq
|
||||
LEFT JOIN res_partner vendor_partner on vendor_partner.id = eq.partner_id
|
||||
LEFT JOIN res_users users on technician_user_id = users.id
|
||||
LEFT JOIN res_partner op_partner on users.partner_id = op_partner.id
|
||||
LEFT JOIN maintenance_equipment_category categ on categ.id = eq.category_id
|
||||
LEFT JOIN maintenance_request req on req.equipment_id = eq.id and req.id in (%s)
|
||||
LEFT JOIN maintenance_request preventive on preventive.id = req.id and preventive.maintenance_type = 'preventive'
|
||||
LEFT JOIN maintenance_request corrective on corrective.id = req.id and corrective.maintenance_type = 'corrective'
|
||||
WHERE 1 = 1 %s
|
||||
GROUP BY eq.id , vendor_partner.id, op_partner.id , categ.id
|
||||
'''%(order_str,cond)
|
||||
self.env.cr.execute(query)
|
||||
res = self.env.cr.dictfetchall()
|
||||
done_stage = self.env.get('maintenance.stage').search([('stage_type', '=', 'request_done')])
|
||||
done_ids = done_stage.ids
|
||||
order_model = self.env.get('maintenance.request')
|
||||
machine_status_dict = dict(
|
||||
out_service='Out of Service',
|
||||
part='Partially effect',
|
||||
in_service='In Service'
|
||||
)
|
||||
for rec in res:
|
||||
equipment_id = rec['equipment_id']
|
||||
order_res = order_model.search([('equipment_id','=',equipment_id),('stage_id', 'not in', done_ids)],order='request_date')
|
||||
machine_status = order_res and order_res[-1].machine_status or '-'
|
||||
cost = 0
|
||||
equ_order_res = order_model.search([('equipment_id','=',equipment_id),('id', 'in', order_ids)]).ids
|
||||
order_spares = self.env.get('maintenance.request.spare').search([('request_id', 'in', equ_order_res)])
|
||||
for line in order_spares:
|
||||
cost += line.quantity * line.cost
|
||||
rec.update({'machine_status' : machine_status_dict.get(machine_status, '-') , 'cost' : cost})
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _get_report_values(self, docids, data=None):
|
||||
report_obj = self.env['ir.actions.report']
|
||||
report = report_obj._get_report_from_name('maintenance_custom.spare_part_report')
|
||||
rec_ids = data['form']['rec_ids']
|
||||
category_ids = data['form']['category_ids']
|
||||
equipment_ids = data['form']['equipment_ids']
|
||||
docs = self._get_data(rec_ids,equipment_ids,category_ids)
|
||||
docargs = {
|
||||
'doc_ids': docids,
|
||||
'doc_model': report.model,
|
||||
'docs': docs,
|
||||
}
|
||||
docargs.update(data['form'])
|
||||
return docargs
|
||||
|
||||
class TeamReport(models.AbstractModel):
|
||||
_name = 'report.maintenance_custom.maintenance_team_report'
|
||||
|
||||
def _get_data(self,order_ids,employee_ids=None,department_ids=None):
|
||||
cond = ""
|
||||
if employee_ids:
|
||||
cond += " AND emp.id in (%s)"%(to_str(employee_ids),)
|
||||
if department_ids:
|
||||
cond += " AND dep.id in (%s)"%(to_str(department_ids),)
|
||||
query = '''
|
||||
SELECT emp.name as name , job.name as job , dep.name as department,
|
||||
count(on_time.id) as on_time, count(over_due.id) as over_due,
|
||||
sum(EXTRACT(EPOCH FROM work_hours.done_time-work_hours.start_time)/3600) as work_hours,
|
||||
count(closed.id) as closed , count(opened.id) as opened
|
||||
FROM hr_employee emp
|
||||
LEFT JOIN req_member_rel rel on rel.hr_employee_id = emp.id and rel.maintenance_request_id in (%s)
|
||||
LEFT JOIN hr_department dep on dep.id = emp.department_id
|
||||
LEFT JOIN hr_job job on job.id = emp.job_id
|
||||
LEFT JOIN maintenance_request on_time on on_time.id = rel.maintenance_request_id
|
||||
AND on_time.duration > 0 AND on_time.done_time <= on_time.schedule_date + interval '1' HOUR * on_time.duration
|
||||
LEFT JOIN maintenance_request over_due on over_due.id = rel.maintenance_request_id
|
||||
AND over_due.duration > 0 AND over_due.done_time > over_due.schedule_date + interval '1' HOUR * over_due.duration
|
||||
LEFT JOIN maintenance_request work_hours on work_hours.id = rel.maintenance_request_id
|
||||
LEFT JOIN maintenance_request opened on opened.id = rel.maintenance_request_id and opened.stage_id not in (select id from maintenance_stage where stage_type = 'request_done' )
|
||||
LEFT JOIN maintenance_request closed on closed.id = rel.maintenance_request_id and closed.stage_id in (select id from maintenance_stage where stage_type = 'request_done' )
|
||||
WHERE 1 = 1 %s
|
||||
group by emp.id, job.id , dep.id
|
||||
'''%(to_str(order_ids),cond)
|
||||
self.env.cr.execute(query)
|
||||
res = self.env.cr.dictfetchall()
|
||||
for rec in res:
|
||||
if rec.get('work_hours'):
|
||||
rec.update({
|
||||
'work_hours' : round(rec['work_hours'] , 2),
|
||||
})
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _get_report_values(self, docids, data=None):
|
||||
report_obj = self.env['ir.actions.report']
|
||||
report = report_obj._get_report_from_name('maintenance_custom.maintenance_team_report')
|
||||
rec_ids = data['form']['rec_ids']
|
||||
employee_ids = data['form']['employee_ids']
|
||||
department_ids = data['form']['department_ids']
|
||||
docs = self._get_data(rec_ids,employee_ids,department_ids)
|
||||
docargs = {
|
||||
'doc_ids': docids,
|
||||
'doc_model': report.model,
|
||||
'docs': docs,
|
||||
}
|
||||
docargs.update(data['form'])
|
||||
return docargs
|
||||
|
|
@ -0,0 +1,270 @@
|
|||
<odoo>
|
||||
<template id="general_maintenance_report">
|
||||
<t t-call="web.html_container">
|
||||
<t t-call="web.external_layout">
|
||||
<style>
|
||||
body{
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.date_tb{
|
||||
display: table;
|
||||
}
|
||||
|
||||
.date_th{
|
||||
display: table;
|
||||
}
|
||||
.date_tb div{
|
||||
display: table-cell;
|
||||
border-color: #888888;
|
||||
border: 1px solid #dee2e6;
|
||||
padding: 10px;
|
||||
min-width:30px;
|
||||
}
|
||||
.date_th{
|
||||
background-color: #dee2e6;
|
||||
}
|
||||
.box{
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
margin-top:10px;
|
||||
width: 150px;
|
||||
height: 100px;
|
||||
min-width: 150px;
|
||||
min-height: 100px;
|
||||
max-width: 150px;
|
||||
max-height: 100px;
|
||||
color:white;
|
||||
font-weight: bold;
|
||||
}
|
||||
.box-title{
|
||||
margin: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.box-content{
|
||||
margin: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.main-box-container, date_th{
|
||||
margin:30px;
|
||||
}
|
||||
|
||||
.box-container{
|
||||
|
||||
}
|
||||
.main-box-container .left{
|
||||
float: left;
|
||||
margin-top:10px;
|
||||
}
|
||||
|
||||
.main-box-container .right{
|
||||
margin-left:300px;
|
||||
}
|
||||
.main-box-container .row{
|
||||
display: table;
|
||||
border-spacing: 20px;
|
||||
}
|
||||
|
||||
.main-box-container .row .box{
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.data_tb{
|
||||
text-align:center;
|
||||
}
|
||||
.data_tb th, #filters_tb th{
|
||||
background-color: #dee2e6;
|
||||
}
|
||||
|
||||
.data_tb td , .data_tb th{
|
||||
border-color: #888888;
|
||||
border: 1px solid black;
|
||||
padding: 10px;
|
||||
min-width:30px;
|
||||
|
||||
}
|
||||
|
||||
#filters_tb, #filters_tb th, #filters_tb td{
|
||||
border: 1px solid black;
|
||||
text-align : center;
|
||||
padding : 15px;
|
||||
}
|
||||
|
||||
#filters_tb th, #filters_tb td{
|
||||
min-width: 150px;
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
.zooba{
|
||||
background-color:#66CDAA;
|
||||
|
||||
}
|
||||
|
||||
.over{
|
||||
background-color:#DC143C;
|
||||
}
|
||||
|
||||
.high{
|
||||
background-color:red;
|
||||
}
|
||||
.open{
|
||||
background-color:#FFD700;
|
||||
}
|
||||
.closed{
|
||||
background-color:#228B22 ;
|
||||
}
|
||||
.total_work_order{
|
||||
background-color:#87CEFA ;
|
||||
}
|
||||
.plan{
|
||||
background-color:#6495ED ;
|
||||
}
|
||||
.hours{
|
||||
background-color:#1E90FF ;
|
||||
}
|
||||
.cost{
|
||||
background-color:#663399 ;
|
||||
}
|
||||
.downtime{
|
||||
background-color:#9370DB ;
|
||||
}
|
||||
.loss{
|
||||
background-color:#4B0082 ;
|
||||
}
|
||||
</style>
|
||||
|
||||
<center>
|
||||
<table id="filters_tb">
|
||||
<tr>
|
||||
<th>Date From</th>
|
||||
<th>Date To</th>
|
||||
<th>Equipment</th>
|
||||
<th>Category</th>
|
||||
<th>FAILURE TYPE</th>
|
||||
<th>Supervisor</th>
|
||||
<th>Team Member</th>
|
||||
<th>Team Type</th>
|
||||
<th>Spare Part</th>
|
||||
<th>Machine Status</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span t-esc="time_from" /></td>
|
||||
<td><span t-esc="time_to" /> </td>
|
||||
<td><span t-esc="filters.get('equipment_id', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('category_id', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('failure_id', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('user_id', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('employee_id', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('team_type', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('spare_id', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('machine_status', 'ALL')" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="main-box-container">
|
||||
<div class="">
|
||||
<div class="row">
|
||||
<div class="box zooba">
|
||||
<div class="box-title">TOTAL EQUIPMENT</div>
|
||||
<div class="box-content"><span t-esc="total['total_equipment']" /></div>
|
||||
</div>
|
||||
<div class="box total_work_order">
|
||||
<div class="box-title">TOTAL WORK ORDERS</div>
|
||||
<div class="box-content"><span t-esc="total['total_orders']" /></div>
|
||||
</div>
|
||||
<div class="box closed">
|
||||
<div class="box-title">CLOSED ORDERS</div>
|
||||
<div class="box-content"><span t-esc="total['total_colse']" /></div>
|
||||
</div>
|
||||
<div class="box open">
|
||||
<div class="box-title">OPEN ORDERS</div>
|
||||
<div class="box-content"><span t-esc="total['total_open']" /></div>
|
||||
</div>
|
||||
<div class="box over">
|
||||
<div class="box-title">OVER DUUE TASKS</div>
|
||||
<div class="box-content"><span t-esc="total['total_over_due']" /></div>
|
||||
</div>
|
||||
<div class="box high">
|
||||
<div class="box-title">HIGH PRIORITY</div>
|
||||
<div class="box-content"><span t-esc="total['total_high']" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="box zooba">
|
||||
<div class="box-title"><br />TOTAL STAFF<br /> </div>
|
||||
<div class="box-content"><span t-esc="total['total_members']" /></div>
|
||||
</div>
|
||||
<div class="box plan">
|
||||
<div class="box-title">PLANNED VS UNPLANNED</div>
|
||||
<div class="box-content"><span t-esc="total['total_planned']" /></div>
|
||||
</div>
|
||||
<div class="box hours">
|
||||
<div class="box-title"> WORKING HOURS</div>
|
||||
<div class="box-content"><span t-esc="total['total_working_hours']" />H</div>
|
||||
</div>
|
||||
<div class="box cost">
|
||||
<div class="box-title"><br />REPAIR COST<br /> </div>
|
||||
<div class="box-content"><span t-esc="total['total_cost']" /> SDG</div>
|
||||
</div>
|
||||
<div class="box downtime">
|
||||
<div class="box-title">TOTAL DOWNTIME</div>
|
||||
<div class="box-content"><span t-esc="total['total_downtime']" /> H</div>
|
||||
</div>
|
||||
<div class="box loss">
|
||||
<div class="box-title"><br />TOTAL LOSSES <br /> </div>
|
||||
<div class="box-content"><span t-esc="total['total_loss']" /> Unit</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="data_tb">
|
||||
<tr>
|
||||
<th>JOB NO</th>
|
||||
<th>DATE</th>
|
||||
<th>EQUIPMENT</th>
|
||||
<th>TITLE</th>
|
||||
<th>MAINTENANCE Type</th>
|
||||
<th>FAILURE TYPE</th>
|
||||
<th>PRIORITY</th>
|
||||
<th>ASSIGN STAFF</th>
|
||||
<th>TEAM</th>
|
||||
<th>MAN POWER</th>
|
||||
<th>Machine Status</th>
|
||||
<th>Down-Time</th>
|
||||
<th>LOSSES</th>
|
||||
<th>WORK Stage</th>
|
||||
</tr>
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<tr>
|
||||
<td><span t-field="o.code"/></td>
|
||||
<td><span t-field="o.request_date"/></td>
|
||||
<td><span t-field="o.equipment_id.name"/></td>
|
||||
<td><span t-field="o.name"/></td>
|
||||
<td><span t-field="o.maintenance_type"/></td>
|
||||
<td><span t-field="o.failure_id.name"/></td>
|
||||
<td><span t-field="o.priority"/></td>
|
||||
<td><span t-field="o.user_id.name"/></td>
|
||||
<td>
|
||||
<span t-if="o.team_type=='in'"><span t-field="o.team_type"/></span>
|
||||
<span t-if="o.team_type=='out'"><span t-field="o.out_entity_id.name"/></span>
|
||||
</td>
|
||||
<td><span t-esc="len(o.employee_ids.ids)" /></td>
|
||||
<td><span t-field="o.machine_status"/></td>
|
||||
<td><span t-field="o.down_time"/></td>
|
||||
<td><span t-field="o.product_loss"/></td>
|
||||
<td><span t-field="o.stage_id.name"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</table>
|
||||
</center>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<report id="action_report_maintenance"
|
||||
model="maintenance.request"
|
||||
string="Maintenance Form"
|
||||
report_type="qweb-pdf"
|
||||
name="maintenance_custom.report_maintenance_request"
|
||||
/>
|
||||
|
||||
<report id="action_general_maintenance_report"
|
||||
model="maintenance.request"
|
||||
string="General Maintenance"
|
||||
report_type="qweb-pdf"
|
||||
name="maintenance_custom.general_maintenance_report"
|
||||
menu="False"
|
||||
/>
|
||||
|
||||
<report id="action_spare_part_report"
|
||||
model="maintenance.request"
|
||||
string="Spare Parts"
|
||||
report_type="qweb-pdf"
|
||||
name="maintenance_custom.spare_part_report"
|
||||
menu="False"
|
||||
/>
|
||||
|
||||
<report id="action_equipment_report"
|
||||
model="maintenance.request"
|
||||
string="Equipment"
|
||||
report_type="qweb-pdf"
|
||||
name="maintenance_custom.equipment_report"
|
||||
menu="False"
|
||||
/>
|
||||
|
||||
<report id="action_maintenance_team_report"
|
||||
model="maintenance.request"
|
||||
string="Maintenance Team"
|
||||
report_type="qweb-pdf"
|
||||
name="maintenance_custom.maintenance_team_report"
|
||||
menu="False"
|
||||
/>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,210 @@
|
|||
<odoo>
|
||||
<template id="maintenance_team_report">
|
||||
<t t-call="web.html_container">
|
||||
<t t-call="web.external_layout">
|
||||
<style>
|
||||
body{
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.date_tb{
|
||||
display: table;
|
||||
}
|
||||
|
||||
.date_th{
|
||||
display: table;
|
||||
}
|
||||
.date_tb div{
|
||||
display: table-cell;
|
||||
border-color: #888888;
|
||||
border: 1px solid #dee2e6;
|
||||
padding: 10px;
|
||||
min-width:30px;
|
||||
}
|
||||
.date_th{
|
||||
background-color: #dee2e6;
|
||||
}
|
||||
.box{
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
margin-top:10px;
|
||||
width: 150px;
|
||||
height: 100px;
|
||||
min-width: 150px;
|
||||
min-height: 100px;
|
||||
max-width: 150px;
|
||||
max-height: 100px;
|
||||
color:white;
|
||||
font-weight:bold;
|
||||
}
|
||||
.box-title{
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.box-content{
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.main-box-container, date_th{
|
||||
margin:30px;
|
||||
}
|
||||
|
||||
.box-container{
|
||||
|
||||
}
|
||||
.main-box-container .left{
|
||||
float: left;
|
||||
margin-top:10px;
|
||||
}
|
||||
|
||||
.main-box-container .right{
|
||||
margin-left:300px;
|
||||
}
|
||||
.main-box-container .row{
|
||||
display: table;
|
||||
border-spacing: 20px;
|
||||
}
|
||||
|
||||
.main-box-container .row .box{
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.data_tb{
|
||||
text-align:center;
|
||||
}
|
||||
.data_tb th, #filters_tb th{
|
||||
background-color: #dee2e6;
|
||||
}
|
||||
|
||||
.data_tb td , .data_tb th{
|
||||
border-color: #888888;
|
||||
border: 1px solid black;
|
||||
padding: 10px;
|
||||
min-width:30px;
|
||||
|
||||
}
|
||||
|
||||
#filters_tb, #filters_tb th, #filters_tb td{
|
||||
border: 1px solid black;
|
||||
text-align : center;
|
||||
padding : 15px;
|
||||
}
|
||||
|
||||
#filters_tb th, #filters_tb td{
|
||||
min-width: 150px;
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
.zooba{
|
||||
background-color:#66CDAA;
|
||||
|
||||
}
|
||||
|
||||
.over{
|
||||
background-color:#DC143C;
|
||||
}
|
||||
|
||||
.high{
|
||||
background-color:red;
|
||||
}
|
||||
.open{
|
||||
background-color:#FFD700;
|
||||
}
|
||||
.closed{
|
||||
background-color:#228B22 ;
|
||||
}
|
||||
.total_work_order{
|
||||
background-color:#87CEFA ;
|
||||
}
|
||||
.plan{
|
||||
background-color:#6495ED ;
|
||||
}
|
||||
.hours{
|
||||
background-color:#1E90FF ;
|
||||
}
|
||||
.cost{
|
||||
background-color:#663399 ;
|
||||
}
|
||||
.downtime{
|
||||
background-color:#9370DB ;
|
||||
}
|
||||
.loss{
|
||||
background-color:#4B0082 ;
|
||||
}
|
||||
</style>
|
||||
|
||||
<center>
|
||||
<table id="filters_tb">
|
||||
<tr>
|
||||
<th>Date From</th>
|
||||
<th>Date To</th>
|
||||
<th>Departments</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span t-esc="time_from" /></td>
|
||||
<td><span t-esc="time_to" /> </td>
|
||||
<td><span t-esc="filters.get('department_id', 'ALL')" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="main-box-container">
|
||||
<div class="row">
|
||||
<div class="box zooba">
|
||||
<div class="box-title">TOTAL Tasks</div>
|
||||
<br />
|
||||
<div class="box-content"><span t-esc="total['total_orders']" /></div>
|
||||
</div>
|
||||
<div class="box open">
|
||||
<div class="box-title">OPEN ORDERS</div>
|
||||
<div class="box-content"><span t-esc="total['total_open']" /></div>
|
||||
</div>
|
||||
<!--div class="box closed">
|
||||
<div class="box-title">DONE ON TIME</div>
|
||||
<div class="box-content">22</div>
|
||||
</div-->
|
||||
<div class="box over">
|
||||
<div class="box-title">OVER DUE TASKS</div>
|
||||
<div class="box-content"><span t-esc="total['over_due_percentage']" />%</div>
|
||||
</div>
|
||||
<div class="box cost">
|
||||
<div class="box-title">WORKING HOURS</div>
|
||||
<div class="box-content"><span t-esc="total['total_working_hours']" /> H</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="data_tb">
|
||||
<tr>
|
||||
<th>NO</th>
|
||||
<th>NAME</th>
|
||||
<th>POSITION</th>
|
||||
<th>DEPARMENT</th>
|
||||
<th>OPENNED TASKS</th>
|
||||
<th>CLOSED TASKS</th>
|
||||
<th>ON-TIME</th>
|
||||
<th>OVERDUE</th>
|
||||
<th>WORKING HOURS</th>
|
||||
</tr>
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<tr>
|
||||
<td><span t-esc="o_index+1"/></td>
|
||||
<td><span t-esc="o['name']"/></td>
|
||||
<td><span t-esc="o['job']"/></td>
|
||||
<td><span t-esc="o['department']"/></td>
|
||||
<td><span t-esc="o['opened']"/></td>
|
||||
<td><span t-esc="o['closed']"/></td>
|
||||
<td><span t-esc="o['on_time']"/></td>
|
||||
<td><span t-esc="o['over_due']"/></td>
|
||||
<td><span t-esc="o['work_hours']"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</table>
|
||||
</center>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
<odoo>
|
||||
<template id="report_maintenance_request">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<t t-call="web.external_layout">
|
||||
<style>
|
||||
|
||||
td, th{
|
||||
padding:5px;
|
||||
}
|
||||
|
||||
table{
|
||||
border: 1px solid black;
|
||||
text-align:center;
|
||||
margin-bottom:40px;
|
||||
|
||||
}
|
||||
th{
|
||||
background-color:cadetblue;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
th,td{
|
||||
border: 1px solid black;
|
||||
min-width:80px;
|
||||
min-height:20px;
|
||||
height:20px;
|
||||
}
|
||||
|
||||
#failure_tb th , #repair_tb th , #down_tb th , #manager_tb th {
|
||||
word-wrap: break-word;
|
||||
min-width:30px;
|
||||
max-width:60px;
|
||||
}
|
||||
|
||||
#repair_tb th {
|
||||
word-wrap: break-word;
|
||||
min-width:30px;
|
||||
max-width:100px;
|
||||
}
|
||||
</style>
|
||||
<center>
|
||||
<div class="page">
|
||||
<h1>Failure report</h1>
|
||||
<table width="90%" height="100%">
|
||||
<tr>
|
||||
<th colspan="8">REQUEST INFORMATION</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>REQUESTER</th><td colspan="2"><span t-field="o.employee_id.name"/></td>
|
||||
<th>REQUEST NO</th><td colspan="1"><span t-field="o.code"/></td>
|
||||
<th>DATE/TIME</th><td colspan="2"><span t-field="o.request_date"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th >EQUIPMENT</th><td colspan="2"><span t-field="o.equipment_id.name"/></td>
|
||||
<th>EQUIPMENT CONDITION</th><td colspan="4"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<span t-if="o.maintenance_type=='corrective'">
|
||||
<table width="90%" height="100%" id="failure_tb">
|
||||
<tr>
|
||||
<th colspan="8">FAILURE</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>FAILURE TYPE</th><td colspan="2"><span t-field="o.failure_id.name"/></td>
|
||||
<th>FAILED COMPONANT</th><td colspan="4"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>FAILURE CAUSE</th><td colspan="7"><span t-field="o.failure_cause_id.name"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>HOW FAILURE WAS DETECTED</th><td colspan="7"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="90%" height="100%" id="repair_tb">
|
||||
<tr>
|
||||
<th colspan="8">REPAIRING AND CORRECTION ACTION</th>
|
||||
</tr>
|
||||
<tr height="120px">
|
||||
<th>CORRECTION ACTION</th>
|
||||
<td colspan="8"><span t-field="o.maintenance_work"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>REPAIR COMPLATE DATE AND TIME</th>
|
||||
<td><span t-field="o.done_time"/></td>
|
||||
<th>REPAIR DURATION</th>
|
||||
<td><span t-field="o.duration"/></td>
|
||||
<th>EQUIPMENT CONDITION</th>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="90%" height="100%" id="down_tb">
|
||||
<tr>
|
||||
<th colspan="8">DOWNTIME AND LOSSES</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>DOWNTIME</th>
|
||||
<td colspan="3"><span t-field="o.down_time"/></td>
|
||||
<th>LOSSES OF PRODUCTION</th>
|
||||
<td colspan="3"><span t-field="o.product_loss"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</span>
|
||||
<span t-if="o.maintenance_type=='preventive'">
|
||||
<table width="90%" height="100%" id="down_tb">
|
||||
<tr>
|
||||
<th colspan="8">Tasks Details</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Task Title</th>
|
||||
<th>Employee</th>
|
||||
<th>Executing Time</th>
|
||||
<th>Duration</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
<t t-foreach="o.task_ids" t-as="t">
|
||||
<tr>
|
||||
<td><span t-field="t.name"/></td>
|
||||
<td><span t-field="t.employee_id.name"/></td>
|
||||
<td><span t-field="t.time"/></td>
|
||||
<td><span t-field="t.duration"/></td>
|
||||
<td>
|
||||
<span t-if="t.is_done">Done</span>
|
||||
<span t-else="" >Pending</span>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
<span t-if="len(o.task_ids) < 3">
|
||||
<t t-foreach="range(3-len(o.task_ids))" t-as="i">
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</t>
|
||||
</span>
|
||||
</table>
|
||||
</span>
|
||||
<table width="90%" height="100%" id="manager_tb">
|
||||
<tr>
|
||||
<th>SUPERVISOR</th>
|
||||
<td colspan="3"><span t-field="o.user_id"/></td>
|
||||
<th>MANAGER</th>
|
||||
<td colspan="3">Administrator</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</center>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
<odoo>
|
||||
<template id="spare_part_report">
|
||||
<t t-call="web.html_container">
|
||||
<t t-call="web.external_layout">
|
||||
<style>
|
||||
body{
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.date_tb{
|
||||
display: table;
|
||||
}
|
||||
|
||||
.date_th{
|
||||
display: table;
|
||||
}
|
||||
.date_tb div{
|
||||
display: table-cell;
|
||||
border-color: #888888;
|
||||
border: 1px solid #dee2e6;
|
||||
padding: 10px;
|
||||
min-width:30px;
|
||||
}
|
||||
.date_th{
|
||||
background-color: #dee2e6;
|
||||
}
|
||||
.box{
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
margin-top:10px;
|
||||
width: 150px;
|
||||
height: 100px;
|
||||
min-width: 150px;
|
||||
min-height: 100px;
|
||||
max-width: 150px;
|
||||
max-height: 100px;
|
||||
color:white;
|
||||
font-weight:bold;
|
||||
}
|
||||
.box-title{
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.box-content{
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.main-box-container, date_th{
|
||||
margin:30px;
|
||||
}
|
||||
|
||||
.box-container{
|
||||
|
||||
}
|
||||
.main-box-container .left{
|
||||
float: left;
|
||||
margin-top:10px;
|
||||
}
|
||||
|
||||
.main-box-container .right{
|
||||
margin-left:300px;
|
||||
}
|
||||
.main-box-container .row{
|
||||
display: table;
|
||||
border-spacing: 20px;
|
||||
}
|
||||
|
||||
.main-box-container .row .box{
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.data_tb{
|
||||
text-align:center;
|
||||
}
|
||||
.data_tb th, #filters_tb th{
|
||||
background-color: #dee2e6;
|
||||
}
|
||||
|
||||
.data_tb td , .data_tb th{
|
||||
border-color: #888888;
|
||||
border: 1px solid black;
|
||||
padding: 10px;
|
||||
min-width:100px;
|
||||
|
||||
}
|
||||
|
||||
#filters_tb, #filters_tb th, #filters_tb td{
|
||||
border: 1px solid black;
|
||||
text-align : center;
|
||||
padding : 15px;
|
||||
}
|
||||
|
||||
#filters_tb th, #filters_tb td{
|
||||
min-width: 150px;
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
.zooba{
|
||||
background-color:#66CDAA;
|
||||
|
||||
}
|
||||
|
||||
.over{
|
||||
background-color:#DC143C;
|
||||
}
|
||||
|
||||
.high{
|
||||
background-color:red;
|
||||
}
|
||||
.open{
|
||||
background-color:#FFD700;
|
||||
}
|
||||
.closed{
|
||||
background-color:#228B22 ;
|
||||
}
|
||||
.total_work_order{
|
||||
background-color:#87CEFA ;
|
||||
}
|
||||
.plan{
|
||||
background-color:#6495ED ;
|
||||
}
|
||||
.hours{
|
||||
background-color:#1E90FF ;
|
||||
}
|
||||
.cost{
|
||||
background-color:#663399 ;
|
||||
}
|
||||
.downtime{
|
||||
background-color:#9370DB ;
|
||||
}
|
||||
.loss{
|
||||
background-color:#4B0082 ;
|
||||
}
|
||||
</style>
|
||||
<center>
|
||||
<table id="filters_tb">
|
||||
<tr>
|
||||
<th>Date From</th>
|
||||
<th>Date To</th>
|
||||
<th>Spare Part</th>
|
||||
<th>Category</th>
|
||||
<th>Equipment</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span t-esc="time_from" /></td>
|
||||
<td><span t-esc="time_to" /> </td>
|
||||
<td><span t-esc="filters.get('spare_id', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('spare_categ_id', 'ALL')" /></td>
|
||||
<td><span t-esc="filters.get('equipment_id', 'ALL')" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="main-box-container">
|
||||
<div class="row">
|
||||
<div class="box zooba">
|
||||
<div class="box-title">TOTAL EQUIPMENT</div>
|
||||
<div class="box-content"><span t-esc="total['total_equipment']" /></div>
|
||||
</div>
|
||||
<div class="box total_work_order">
|
||||
<div class="box-title">TOTAL WORK ORDERS</div>
|
||||
<div class="box-content"><span t-esc="total['total_orders']" /></div>
|
||||
</div>
|
||||
<div class="box high">
|
||||
<div class="box-title">HIGH PRIORITY</div>
|
||||
<div class="box-content"><span t-esc="total['total_high']" /></div>
|
||||
</div>
|
||||
<div class="box downtime">
|
||||
<div class="box-title">TOTAL DOWNTIME</div>
|
||||
<div class="box-content"><span t-esc="total['total_downtime']" /> H</div>
|
||||
</div>
|
||||
<div class="box loss">
|
||||
<div class="box-title">TOTAL LOSSES</div>
|
||||
<div class="box-content"><span t-esc="total['total_loss']" /> </div>
|
||||
</div>
|
||||
<div class="box cost">
|
||||
<div class="box-title">Repair COST</div>
|
||||
<div class="box-content"><span t-esc="total['total_cost']" /> SDG</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="data_tb">
|
||||
<tr>
|
||||
<th>NO</th>
|
||||
<th>PART</th>
|
||||
<th>S/N</th>
|
||||
<th>CATEGORY</th>
|
||||
<th>CONSUMPTION</th>
|
||||
<th>STOCK</th>
|
||||
<th>NO. OF WORK ORDER</th>
|
||||
<th>Down-Time</th>
|
||||
<th>LOSSES</th>
|
||||
<th>COST</th>
|
||||
</tr>
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<tr>
|
||||
<td><span t-esc="o_index+1"/></td>
|
||||
<td><span t-esc="o['name']"/></td>
|
||||
<td><span t-esc="o['sn']"/></td>
|
||||
<td><span t-esc="o['category']"/></td>
|
||||
<td><span t-esc="o['consume']"/></td>
|
||||
<td><span t-esc="o['stock']"/></td>
|
||||
<td><span t-esc="o['order_count']"/></td>
|
||||
<td><span t-esc="o['down_time']"/></td>
|
||||
<td><span t-esc="o['loss']"/></td>
|
||||
<td><span t-esc="o['cost']"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</table>
|
||||
</center>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="maintenance_order_stage_visibility_stage_group" model="res.groups">
|
||||
<field name="name">Maintenance Order Acceptation</field>
|
||||
</record>
|
||||
<record id="request_order_stage" model="res.groups">
|
||||
<field name="name">Request Order Acceptation</field>
|
||||
</record>
|
||||
<record id="maintenance_order_done" model="res.groups">
|
||||
<field name="name">Maintenance Order Done</field>
|
||||
</record>
|
||||
<record id="maintenance_order_stage_cancel_visibility_stage_group" model="res.groups">
|
||||
<field name="name">Maintenance Order Cancel</field>
|
||||
</record>
|
||||
<record id="maintenance_order_set_to_draft" model="res.groups">
|
||||
<field name="name">Maintenance Order ٍSet To Draft</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_equipment_job,equipment.job.user,model_maintenance_equipment_job,base.group_user,1,0,0,0
|
||||
access_equipment_job_admin_user,equipment.job.admin.user,model_maintenance_equipment_job,maintenance.group_equipment_manager,1,1,1,1
|
||||
access_equipments_jobs,equipments.jobs,model_maintenance_equipments_jobs,,1,1,1,1
|
||||
access_equipment_task,equipment.task.user,model_maintenance_equipment_task,base.group_user,1,0,0,0
|
||||
access_equipment_task_admin_user,equipment.task.admin.user,model_maintenance_equipment_task,maintenance.group_equipment_manager,1,1,1,1
|
||||
access_request_task,request.task.user,model_maintenance_request_task,base.group_user,1,0,0,0
|
||||
access_request_task_admin_user,request.task.admin.user,model_maintenance_request_task,maintenance.group_equipment_manager,1,1,1,1
|
||||
access_maintenance_rootfailure,access_maintenance_rootfailure,model_maintenance_rootfailure,base.group_user,1,0,0,0
|
||||
access_maintenance_rootfailure_admin,access_maintenance_rootfailure,model_maintenance_rootfailure,maintenance.group_equipment_manager,1,1,1,1
|
||||
access_maintenance_report_wiz,access_maintenance_report_wiz,model_maintenance_report_wiz,base.group_user,1,1,1,1
|
||||
access_maintenance_failure,access_maintenance_failure,model_maintenance_failure,base.group_user,1,0,0,0
|
||||
access_maintenance_failure_admin,access_maintenance_failure_admin,model_maintenance_failure,maintenance.group_equipment_manager,1,1,1,1
|
||||
access_maintenance_req_spare,access_maintenance_req_spare,model_maintenance_request_spare,base.group_user,1,0,0,0
|
||||
access_maintenance_req_spare_admin,access_maintenance_req_spare_admin,model_maintenance_request_spare,maintenance.group_equipment_manager,1,1,1,1
|
||||
access_maintenance_summary,maintenance_summary_user,model_maintenance_summary,base.group_user,1,0,0,0
|
||||
access_maintenance_matrial,maintenance_matrial_user,model_matrial_line,base.group_user,1,1,1,1
|
||||
access_checklist_line,maintenance_checklist_line,model_checklist_line,base.group_user,1,1,1,1
|
||||
access_equipment_locations,equipment_locations,model_equipment_locations,,1,1,1,1
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* DOM element rendering detection
|
||||
* https://davidwalsh.name/detect-node-insertion
|
||||
*/
|
||||
@keyframes chartjs-render-animation {
|
||||
from { opacity: 0.99; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
.chartjs-render-monitor {
|
||||
animation: chartjs-render-animation 0.001s;
|
||||
}
|
||||
|
||||
/*
|
||||
* DOM element resizing detection
|
||||
* https://github.com/marcj/css-element-queries
|
||||
*/
|
||||
.chartjs-size-monitor,
|
||||
.chartjs-size-monitor-expand,
|
||||
.chartjs-size-monitor-shrink {
|
||||
position: absolute;
|
||||
direction: ltr;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
visibility: hidden;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.chartjs-size-monitor-expand > div {
|
||||
position: absolute;
|
||||
width: 1000000px;
|
||||
height: 1000000px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.chartjs-size-monitor-shrink > div {
|
||||
position: absolute;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1 @@
|
|||
@keyframes chartjs-render-animation{from{opacity:.99}to{opacity:1}}.chartjs-render-monitor{animation:chartjs-render-animation 1ms}.chartjs-size-monitor,.chartjs-size-monitor-expand,.chartjs-size-monitor-shrink{position:absolute;direction:ltr;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1}.chartjs-size-monitor-expand>div{position:absolute;width:1000000px;height:1000000px;left:0;top:0}.chartjs-size-monitor-shrink>div{position:absolute;width:200%;height:200%;left:0;top:0}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,71 @@
|
|||
odoo.define('maintenance.charts', function (require) {
|
||||
"use strict";
|
||||
|
||||
var AbstractField = require('web.AbstractField');
|
||||
var registry = require('web.field_registry');
|
||||
|
||||
var FieldChart = AbstractField.extend({
|
||||
className: 'pichart',
|
||||
_render: function () {
|
||||
var self = this
|
||||
var fields = self.attrs.keys.split(';')
|
||||
var labels = self.attrs.labels.split(';')
|
||||
var backgroundColors = self.attrs.backgroundColors.split(';')
|
||||
var borderColors = self.attrs.borderColors.split(';')
|
||||
var cutoutPercentage = 50
|
||||
if (self.attrs.cutoutPercentage){
|
||||
cutoutPercentage = self.attrs.cutoutPercentage
|
||||
}
|
||||
|
||||
self._rpc({
|
||||
model: self.model,
|
||||
method: 'search_read',
|
||||
fields: fields,
|
||||
domain: [['id', '=', self.res_id]],
|
||||
}).then(function (result) {
|
||||
var vals = result[0]
|
||||
var data = []
|
||||
for (var f = 0 ; f < fields.length ; f++) {
|
||||
var fld = fields[f]
|
||||
data += [vals[fld]]
|
||||
}
|
||||
var ctx = document.createElement("canvas");
|
||||
var myChart = new Chart(ctx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels:labels ,
|
||||
datasets: [{
|
||||
label: '# Work Orders',
|
||||
data: data,
|
||||
backgroundColor : backgroundColors,
|
||||
borderColor:borderColors,
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive : true,
|
||||
cutoutPercentage : cutoutPercentage,
|
||||
title: {
|
||||
display: true,
|
||||
text: self.value,
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position : 'right',
|
||||
labels : {
|
||||
boxWidth : 15,
|
||||
usePointStyle : false,
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
//this.$el.empty();
|
||||
self.$el.append(ctx)
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
registry.add('pichart', FieldChart)
|
||||
});
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
odoo.oepetstore = function(instance, local) {
|
||||
var _t = instance.web._t,
|
||||
_lt = instance.web._lt;
|
||||
var QWeb = instance.web.qweb;
|
||||
|
||||
local.HomePage = instance.Widget.extend({
|
||||
start: function() {
|
||||
console.log("pet store home page loaded");
|
||||
},
|
||||
});
|
||||
|
||||
instance.web.client_actions.add(
|
||||
'petstore.homepage', 'instance.oepetstore.HomePage');
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
|
||||
|
||||
.o_kanban_view.o_kanban_ungrouped.o_kanban_dashboard.o_maintenance_summary {
|
||||
|
||||
.panel.large {
|
||||
width: 70%;
|
||||
}
|
||||
.panel.med {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.o_kanban_record{
|
||||
background-color: white;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.box-title{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.panel-title{
|
||||
font-size: 16px;
|
||||
font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
letter-spacing: 0;
|
||||
font-weight: bold;
|
||||
color: #888888;
|
||||
padding: 0 0 4px;
|
||||
border-bottom: 1px solid #F2F2F2;
|
||||
|
||||
}
|
||||
|
||||
.boxes{
|
||||
display: table;
|
||||
border-spacing: 12px;
|
||||
font-size: 14px;
|
||||
margin-top:5px;
|
||||
width: 100%; /*Optional*/
|
||||
}
|
||||
|
||||
.box{
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-color: #ced4da;
|
||||
border: 1px solid #dee2e6;
|
||||
background-color: white;
|
||||
color: #5D8DA8;
|
||||
text-align: center;
|
||||
margin-top:50px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.box:hover{
|
||||
color: #324e5d;
|
||||
}
|
||||
.box-title{
|
||||
margin: 10px;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.box-content{
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
.danger{
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.done{
|
||||
color:#28a745;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates xml:space="preserve">
|
||||
<t t-name="ChartTemplate">
|
||||
<div style="background-color: red;">This is some simple HTML</div>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<templates>
|
||||
<div t-name="maintenance.report.action">
|
||||
<div>
|
||||
<h1>Hello</h1>
|
||||
</div>
|
||||
</div>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<!-- Inherit Form View to Modify it -->
|
||||
<record id="equipment_order_form_inherit" model="ir.ui.view">
|
||||
<field name="name">equipment.order.form.inherit</field>
|
||||
<field name="model">maintenance.request</field>
|
||||
<field name="inherit_id" ref="maintenance_custom.hr_equipment_order_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='email_cc']" position="before">
|
||||
|
||||
<label for="asset_id" invisible="0"/>
|
||||
<div invisible="0">
|
||||
<field name="asset_id"
|
||||
class="oe_inline"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
<record id="asset_maintenance_order_form_inherit" model="ir.ui.view">
|
||||
<field name="name">asset.maintenance.order.form.inherit</field>
|
||||
<field name="model">maintenance.request</field>
|
||||
<field name="inherit_id" ref="maintenance.hr_equipment_request_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='company_id']" position="after">
|
||||
<field name="asset_id"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<!-- Inherit Form View to Modify it -->
|
||||
<record id="equipment_request_form_checklist" model="ir.ui.view">
|
||||
<field name="name">equipment.request.form.checklist</field>
|
||||
<field name="model">maintenance.request</field>
|
||||
<field name="inherit_id" ref="maintenance.hr_equipment_request_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page[@name='assets_info']" position="after">
|
||||
<page string="Checklist" name="checklist_info">
|
||||
<field name="checklist_lines">
|
||||
<tree string="Checklist For Inspection" editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="description"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,726 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<odoo>
|
||||
<template id="assets_backend" name="maintenance assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" type="text/scss" href="/maintenance_custom/static/src/summary.scss"/>
|
||||
<link rel="stylesheet" type="text/scss" href="/maintenance_custom/static/src/js/Chart.css"/>
|
||||
<script type="text/javascript" src="/maintenance_custom/static/src/js/Chart.js"></script>
|
||||
<script type="text/javascript" src="/maintenance_custom/static/src/js/maintenance_charts.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<record id="product_template_only_form_view_inhrit" model="ir.ui.view">
|
||||
<field name="name">product.template</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_only_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="barcode" position="after">
|
||||
<field name="is_spare"/>
|
||||
<field name="is_tool"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="equipments_locations_view_form" model="ir.ui.view">
|
||||
<field name="name">equipment.locations</field>
|
||||
<field name="model">equipment.locations</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<field name="name"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="equipments_locations_view_tree" model="ir.ui.view">
|
||||
<field name="name">equipment.locations.tree</field>
|
||||
<field name="model">equipment.locations</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Equipment Locations">
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="equipments_locations_action" model="ir.actions.act_window">
|
||||
<field name="name">Equipment Locations</field>
|
||||
<field name="res_model">equipment.locations</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_equipment_job_view_form" model="ir.ui.view">
|
||||
<field name="name">maintenance.equipment.job</field>
|
||||
<field name="model">maintenance.equipment.job</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only" string="Title" readonly="True"/>
|
||||
<h1>
|
||||
<field name="name" placeholder="Maintenance Request" required="1"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="user_id" required="1"/>
|
||||
<field name="period" required="1"/>
|
||||
<field name="start_date" required="1"/>
|
||||
<field name="attachment" required="0"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="period_type" required="1"/>
|
||||
<field name="maintenance_time" widget="float_time"/>
|
||||
<field name="next_action_date" readonly="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Related Tasks">
|
||||
<field name="task_ids" nolabel="1">
|
||||
<tree editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_equipments_jobs_view_form" model="ir.ui.view">
|
||||
<field name="name">maintenance.equipments.jobs</field>
|
||||
<field name="model">maintenance.equipments.jobs</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="creat_equi" type="object" class="oe_stat_button" icon="fa-wrench"
|
||||
string="Create Jobs">
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only" string="Title" readonly="True"/>
|
||||
<h1>
|
||||
<field name="name" placeholder="Maintenance Request" required="1"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="equipments_id" required="1" widget="many2many_tags"/>
|
||||
<field name="user_id" required="1"/>
|
||||
<field name="period" required="1"/>
|
||||
<field name="start_date" required="1" />
|
||||
<field name="attachment" required="0" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="period_type" required="1"/>
|
||||
<field name="maintenance_time" widget="float_time"/>
|
||||
<field name="next_action_date" readonly="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Related Tasks">
|
||||
<field name="task_ids" nolabel="1">
|
||||
<tree editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name" />
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_equipment_view_form_inherit" model="ir.ui.view">
|
||||
<field name="name">maintenance.equipment.form</field>
|
||||
<field name="model">maintenance.equipment</field>
|
||||
<field name="inherit_id" ref="maintenance.hr_equipment_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//button[1]" position="after">
|
||||
<button name="create_maintenance_job" type="object" class="oe_stat_button" icon="fa-wrench"
|
||||
string="Create Jobs">
|
||||
</button>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='location']" position="replace">
|
||||
<field name="location2"/>
|
||||
</xpath>
|
||||
<xpath expr="//page[3]" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//page[3]" position="after">
|
||||
<page string="Maintenance">
|
||||
<field name="job_ids">
|
||||
<tree>
|
||||
<field name="name"/>
|
||||
<field name="user_id"/>
|
||||
<field name="next_action_date"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="hr_equipment_stage_view_tree_inherit" model="ir.ui.view">
|
||||
<field name="name">maintenance.stage.tree</field>
|
||||
<field name="model">maintenance.stage</field>
|
||||
<field name="inherit_id" ref="maintenance.hr_equipment_stage_view_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="done" position="after">
|
||||
<field name="stage_type"/>
|
||||
<field name="next_stage_ids" widget="many2many_tags"/>
|
||||
<field name="pre_stage_ids" widget="many2many_tags"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="hr_maintenance.maintenance_request_view_form_inherit_hr" model="ir.ui.view">
|
||||
<field name="name">maintenance.form</field>
|
||||
<field name="model">maintenance.request</field>
|
||||
<field name="inherit_id" ref="maintenance.hr_equipment_request_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="replace">
|
||||
<field name="name" placeholder="Maintenance Request"
|
||||
attrs="{'readonly':[('stage_type','=','confirm')]}"/>
|
||||
</field>
|
||||
<xpath expr="//header" position="inside">
|
||||
<button class="oe_highlight" type="object" name="request_order_creation" string="Confirm"
|
||||
attrs="{'invisible':[('stage_type' , '!=' , 'draft')]}"/>
|
||||
<button class="oe_highlight" type="object" name="maintenance_order_creation" string="Maintenance Order"
|
||||
attrs="{'invisible':[('stage_type' , '!=' , 'confirm')]}"/>
|
||||
<button class="oe_highlight" type="object" name="order_set_to_draft" string="Set To Draft"
|
||||
attrs="{'invisible':[('stage_type' , '!=' , 'cancel')]}"/>
|
||||
</xpath>
|
||||
<xpath expr="//sheet" position="inside">
|
||||
<notebook>
|
||||
<page string="Matrials" name="purchase_request_info">
|
||||
<field name="line_ids">
|
||||
<tree editable="bottom">
|
||||
|
||||
<field name="product_id"
|
||||
domain="[('purchase_ok', '=', True),('categ_id','child_of',parent.product_category_ids)]"
|
||||
options="{'no_create' : True , 'no_edit' : True ,'no_open' : True}"/>
|
||||
<field name="uom_id"
|
||||
attrs="{'column_required':[('parent.stage_type' , '!=' , 'draft')]}"/>
|
||||
<field name="qty" attrs="{'column_required':[('parent.stage_type' , '!=' , 'draft')]}"/>
|
||||
<field name="price_unit"
|
||||
attrs="{'column_required':[('parent.stage_type' , '!=' , 'draft')]}"/>
|
||||
|
||||
<field name="name"/>
|
||||
<!-- <field name="product_id"-->
|
||||
<!-- domain="[('purchase_ok', '=', True),('categ_id','child_of',parent.product_category_ids)]"-->
|
||||
<!-- options="{'no_create' : True , 'no_edit' : True ,'no_open' : True}"/>-->
|
||||
<!-- <field name="qty" attrs="{'column_required':[('parent.stage_type' , '!=' , 'draft')]}"/>-->
|
||||
<!-- <field name="uom_id"-->
|
||||
<!-- attrs="{'column_required':[('parent.stage_type' , '!=' , 'draft')]}"/>-->
|
||||
<!-- <field name="price_unit"-->
|
||||
<!-- attrs="{'column_required':[('parent.stage_type' , '!=' , 'draft')]}"/>-->
|
||||
<field name="sum_total" force_save="1" sum="Total amount"/>
|
||||
<field name="account_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Account Assets Info" name="assets_info">
|
||||
<group>
|
||||
<field name="employee_id"/>
|
||||
<field name="department_id"/>
|
||||
<field name="user_id"/>
|
||||
<field name="acquisition_date"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</xpath>
|
||||
|
||||
<!-- todo end -->
|
||||
<field name="description" position="replace"/>
|
||||
<xpath expr="//group[1]" position="replace">
|
||||
<notebook>
|
||||
<page string="Request">
|
||||
<group>
|
||||
<group>
|
||||
<field name="code" readonly="True"/>
|
||||
<field name="employee_id" string="Requester"
|
||||
options="{'no_create_edit': True, 'no_open': True}"
|
||||
attrs="{'readonly':[('stage_type','=','confirm')]}"/>
|
||||
<field name="equipment_id" string="Machine" options="{'no_create': True}"
|
||||
context="{'default_company_id':company_id, 'default_category_id':category_id}"
|
||||
attrs="{'readonly':[('stage_type','=','confirm')]}"/>
|
||||
<field name="category_id" options="{'no_create': True}"
|
||||
groups="maintenance.group_equipment_manager"
|
||||
context="{'default_company_id':company_id}" invisible="1"/>
|
||||
<field name="done" invisible="1"/>
|
||||
<field name="close_date" invisible="1" attrs="{'invisible': [('done', '!=', True)]}"
|
||||
readonly="True"/>
|
||||
<field name="archive" invisible="1"/>
|
||||
<field name="maintenance_type" widget="radio" invisible="1"/>
|
||||
<field name="done_time"
|
||||
attrs="{'invisible':[('stage_type','not in', ['request_done' , 'repair_done'])], 'required' : [('stage_type','in', ['request_done' , 'repair_done'])],'readonly':[('stage_type','=','confirm')]}"/>
|
||||
<field name="down_time" widget="float_time"
|
||||
attrs="{'invisible':['|','|' ,('machine_status','!=','out_service'),('stage_type','not in', ['request_done' , 'repair_done']),('maintenance_type','!=', 'corrective')],'readonly':[('stage_type','=','confirm')]}"
|
||||
class="oe_inline"/>
|
||||
<field name="product_loss"
|
||||
attrs="{'invisible':['|','|' ,('machine_status','!=','part'),('stage_type','not in', ['request_done' , 'repair_done']),('maintenance_type','!=', 'corrective')],'readonly':[('stage_type','=','confirm')]}"
|
||||
class="oe_inline"/>
|
||||
<field name="dis_priority" widget="radio"/>
|
||||
<field name="vendor_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="request_date" readonly="True"/>
|
||||
<field name="department_id" attrs="{'readonly':[('stage_type','=','confirm')]}"
|
||||
options="{'no_create': True}"/>
|
||||
<field name="maintenance_team_id"/>
|
||||
<field name="machine_status" invisible="0"
|
||||
attrs="{'readonly':[('stage_type','=','confirm')]}"/>
|
||||
<field name="failure_id"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('stage_type', '=' , 'order')],'invisible':[('stage_type','not in',['for_order', 'request_done' , 'repair_done'])],'required':[('stage_type','in',['for_order' , 'request_done' , 'repair_done'])]}"/>
|
||||
<field name="user_id" options="{'no_create': True}" string="Supervisor"
|
||||
attrs="{'invisible':[('stage_type','not in',['for_order', 'request_done' , 'repair_done'])],'required':[('stage_type','in',['for_order' , 'request_done' , 'repair_done'])],'readonly':[('stage_type','=','confirm')]}"/>
|
||||
<field name="schedule_date"
|
||||
attrs="{'invisible':[('stage_type','not in',['for_order','repair_done','request_done'])],'readonly':[('stage_type','=','confirm')]}"/>
|
||||
<field name="stage_type" invisible="1"/>
|
||||
<label for="duration"
|
||||
attrs="{'invisible':[('stage_type','not in',['for_order','repair_done','request_done'])],'readonly':[('stage_type','=','confirm')]}"/>
|
||||
<div attrs="{'invisible':[('stage_type','not in',['for_order','repair_done','request_done'])],'readonly':[('stage_type','=','confirm')]}">
|
||||
<field name="duration" widget="float_time" class="oe_inline"/>
|
||||
<span class="ml8">hours</span>
|
||||
</div>
|
||||
|
||||
<field name="email_cc" string="Email cc" groups="base.group_no_one" invisible="1"/>
|
||||
<field name="company_id" attrs="{'readonly':['|',('stage_type','=','confirm')]}"
|
||||
options="{'no_create': True}" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Description">
|
||||
<field name="description" attrs="{'readonly':[('stage_type','=','confirm')]}" nolabel="1"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</xpath>
|
||||
<!-- todo start -->
|
||||
<xpath expr="//field[@name='employee_id']" position="after">
|
||||
<field name="partner_id"/>
|
||||
<field name="product_category_ids" required="1" widget="many2many_tags"/>
|
||||
</xpath>
|
||||
<!-- todo end-->
|
||||
</field>
|
||||
</record>
|
||||
<!-- Inherit Form View to Modify it -->
|
||||
<record id="hr_equipment_request_view_form_custom" model="ir.ui.view">
|
||||
<field name="name">hr.equipment.request.view.form.custom</field>
|
||||
<field name="model">maintenance.request</field>
|
||||
<field name="inherit_id" ref="maintenance.hr_equipment_request_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='stage_id']" position="attributes">
|
||||
<attribute name="options">{'no_edit': True}</attribute>
|
||||
</xpath>
|
||||
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- maintenance order form-->
|
||||
<record id="hr_equipment_order_view_form" model="ir.ui.view">
|
||||
<field name="name">equipment.order.form</field>
|
||||
<field name="model">maintenance.request</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Maintenance Order">
|
||||
<header>
|
||||
<field name="stage_id" widget="statusbar"/>
|
||||
<field name="purchase_order_id" invisible="1"/>
|
||||
<button class="oe_highlight" type="object" name="maintenance_order_done" string="Done"
|
||||
attrs="{'invisible':[('stage_type' , '!=' , 'for_order')]}"/>
|
||||
<button string="Reopen Request" name="reset_equipment_request" type="object"
|
||||
attrs="{'invisible': [('archive', '=', False)]}"/>
|
||||
<button name="create_purchase_request" type="object" string="Create Purchase Request"
|
||||
class="oe_highlight" attrs="{'invisible':['|',('stage_type' , '!=' , 'for_order'),('purchase_order_id' , '!=' , False)]}"/>
|
||||
<button name="archive_equipment_request" type="object" string="Cancel"
|
||||
class="oe_highlight" attrs="{'invisible':[('stage_type' , '!=' , 'for_order')]}"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box">
|
||||
<button width='200' class="oe_stat_button" type="object"
|
||||
name="to_open_maintenance_purchase_order"
|
||||
icon="fa-file" attrs="{'invisible':[('stage_type' , '!=' , 'for_order')]}">
|
||||
<field string="Purchase Request" name="purchase_order_count" widget="statinfo"
|
||||
attrs="{'invisible':[('stage_type' , '!=' , 'for_order')]}"/>
|
||||
</button>
|
||||
</div>
|
||||
<div attrs="{'invisible': [('archive', '=', False)]}">
|
||||
<span class="badge badge-warning float-right">Canceled</span>
|
||||
</div>
|
||||
<div class="oe_right">
|
||||
<field name="kanban_state" class="oe_inline" widget="state_selection"/>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only" string="Title" readonly="True"/>
|
||||
<h1>
|
||||
<field name="name" attrs="{'readonly':[('stage_type','=','confirm')]}"
|
||||
placeholder="Maintenance Request"/>
|
||||
</h1>
|
||||
</div>
|
||||
<notebook>
|
||||
<page string="Matrials" name="purchase_request_info">
|
||||
<field name="line_ids">
|
||||
<tree editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="product_id"/>
|
||||
<field name="qty"
|
||||
attrs="{'column_required':[('parent.stage_type' , '!=' , 'draft')]}"/>
|
||||
<field name="uom_id"/>
|
||||
<field name="price_unit"
|
||||
attrs="{'column_required':[('parent.stage_type' , '!=' , 'draft')]}"/>
|
||||
<field name="sum_total" force_save="1" sum="Total amount"/>
|
||||
<field name="account_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Request Details">
|
||||
<group>
|
||||
<group>
|
||||
<field name="code" readonly="True"/>
|
||||
<field name="partner_id" />
|
||||
<field name="employee_id" string="Requester"
|
||||
options="{'no_create_edit': True, 'no_open': True}"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
<field name="equipment_id" string="Machine"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"
|
||||
context="{'default_company_id':company_id, 'default_category_id':category_id}"/>
|
||||
<field name="purchase_order_id" readonly="1" attrs="{'invisible':[('purchase_order_id','=',False)]}"/>
|
||||
<field name="category_id"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"
|
||||
groups="maintenance.group_equipment_manager"
|
||||
context="{'default_company_id':company_id}" invisible="1"/>
|
||||
<field name="done" invisible="1"/>
|
||||
<field name="close_date" invisible="1" attrs="{'invisible': [('done', '!=', True)]}"
|
||||
readonly="True"/>
|
||||
<field name="archive" invisible="1"/>
|
||||
<field name="entry_source" invisible="1"/>
|
||||
<field name="done_time"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')],'invisible':[('stage_type','not in', ['request_done' , 'repair_done'])]}"/>
|
||||
<field name="down_time" widget="float_time" attrs="{
|
||||
'readonly' : ['|',('stage_type','=','confirm'),('entry_source' , '!=' , 'order')],
|
||||
'invisible':['|','|' ,('machine_status','!=','out_service'),('stage_type','not in', ['request_done' , 'repair_done']),('maintenance_type','!=', 'corrective')]}"
|
||||
class="oe_inline"/>
|
||||
<field name="product_loss" attrs="{
|
||||
'readonly' : ['|',('stage_type','=','confirm'),('entry_source' , '!=' , 'order')],
|
||||
'invisible':['|','|' ,('machine_status','!=','part'),('stage_type','not in', ['request_done' , 'repair_done']),('maintenance_type','!=', 'corrective')]}"
|
||||
class="oe_inline"/>
|
||||
<field name="dis_priority"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"
|
||||
widget="radio"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="request_date" readonly="1"/>
|
||||
<field name="department_id"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
<field name="machine_status" invisible="0"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
<field name="maintenance_type" widget="radio" invisible="0"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
<field name="maintenance_category"
|
||||
attrs="{ 'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
<!-- 'invisible':[('entry_source','!=', 'order')],-->
|
||||
<field name="failure_id"
|
||||
attrs="{'invisible':[('maintenance_type','!=', 'corrective')]}"/>
|
||||
<field name="user_id" string="Supervisor" options="{'no_create': True}"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
<field name="employee_ids" invisible="1" options="{'no_create': True}"
|
||||
widget="many2many_tags"/>
|
||||
<field name="schedule_date" invisible="0"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
<field name="stage_type" invisible="1"/>
|
||||
<label for="duration" invisible="0"/>
|
||||
<div invisible="0">
|
||||
<field name="duration"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"
|
||||
widget="float_time" class="oe_inline"/>
|
||||
<span class="ml8">hours</span>
|
||||
</div>
|
||||
|
||||
<field name="email_cc" string="Email cc" groups="base.group_no_one" invisible="1"/>
|
||||
<field name="company_id" options="{'no_create': True}"
|
||||
groups="base.group_multi_company" readonly="True"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Description">
|
||||
<field name="description" nolabel="1"
|
||||
attrs="{'readonly':[('entry_source', '!=' , 'order')]}"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Checklist" name="checklist_info">
|
||||
<field name="checklist_lines">
|
||||
<tree string="Checklist For Inspection" editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="description"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Supervisor">
|
||||
<group>
|
||||
<group>
|
||||
<field name="user_id" string="Supervisor" options="{'no_create': True}"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
<field name="maintenance_team_id"
|
||||
attrs="{'invisible':[('maintenance_type','!=', 'corrective')],'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"
|
||||
options="{'no_create': True}" invisible="1"/>
|
||||
<field name="team_type"
|
||||
attrs="{'invisible':[('maintenance_type','!=', 'corrective')],'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
<field name="start_time"
|
||||
attrs="{'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="failure_id"
|
||||
attrs="{'invisible':[('maintenance_type','!=', 'corrective')],'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
<field name="out_entity_id" options="{'no_create': True}"
|
||||
attrs="{'invisible' : [('team_type' , '!=' , 'out')],'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
<field name="dis_employee_ids" options="{'no_create': True}" widget="many2many_tags"
|
||||
attrs="{'invisible' : [('team_type' , '!=' , 'in')],'readonly':['|',('stage_type','=','confirm'),('entry_source', '!=' , 'order')]}"/>
|
||||
<field name="employee_ids" invisible="1" options="{'no_create': True}"
|
||||
widget="many2many_tags"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Failure Description"
|
||||
attrs="{'invisible':[('maintenance_type','!=', 'corrective')]}">
|
||||
<field name="failure_desc" nolabel="1"/>
|
||||
</group>
|
||||
<group string="Failure root cause"
|
||||
attrs="{'invisible':[('maintenance_type','!=', 'corrective')]}">
|
||||
<field name="failure_cause_id" nolabel="1"/>
|
||||
</group>
|
||||
<group string="Maintenance Work"
|
||||
attrs="{'invisible':[('maintenance_type','!=', 'corrective')]}">
|
||||
<field name="maintenance_work" nolabel="1"/>
|
||||
</group>
|
||||
<group attrs="{'invisible':[('maintenance_type','!=', 'preventive')]}">
|
||||
<field name="attachment" required="0" readonly="1"/>
|
||||
</group>
|
||||
<group string="Tasks" attrs="{'invisible':[('maintenance_type','!=', 'preventive')]}">
|
||||
<field name="task_ids" nolabel="1">
|
||||
<tree editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="employee_id" required="1"/>
|
||||
<field name="time" widget="float_time"/>
|
||||
<field name="duration" widget="float_time"/>
|
||||
<field name="is_done"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
<group string="Tools">
|
||||
<field name="tool_ids" nolabel="1" widget="many2many_tags"/>
|
||||
</group>
|
||||
<!-- <group string="Spares">-->
|
||||
<!-- <field name="spare_ids" nolabel="1">-->
|
||||
<!-- <tree editable="bottom">-->
|
||||
<!-- <field name="spare_id"/>-->
|
||||
<!-- <field name="quantity"/>-->
|
||||
<!-- <field name="cost"/>-->
|
||||
<!-- <field name="total"/>-->
|
||||
<!-- </tree>-->
|
||||
<!-- </field>-->
|
||||
<!-- </group>-->
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="activity_ids" widget="mail_activity"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="maintenance_failure_view_form" model="ir.ui.view">
|
||||
<field name="name">maintenance.failure.form</field>
|
||||
<field name="model">maintenance.failure</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Fiulre Types">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
</group>
|
||||
<group string='Related Engineers'>
|
||||
<field name="user_ids" nolabel="1"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="maintenance_summary_kanban" model="ir.ui.view">
|
||||
<field name="name">Maintenance Summary</field>
|
||||
<field name="model">maintenance.summary</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban class="oe_background_grey o_kanban_dashboard o_maintenance_summary" create="0">
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="panel med">
|
||||
<field name="order_chart" widget="pichart" keys="total_open;total_repair;total_close"
|
||||
labels="Open;Repaired;Closed"
|
||||
backgroundColors="rgba(255, 99, 132, 0.2);rgba(54, 162, 235, 0.2);rgba(255, 206, 86, 0.2)"
|
||||
borderColors="rgba(255, 99, 132, 1);rgba(54, 162, 235, 1);rgba(255, 206, 86, 1)"/>
|
||||
</div>
|
||||
<div class="panel med">
|
||||
<field name="priority_chart" widget="pichart" keys="total_low;total_normal;total_high"
|
||||
labels="Low;Normal;High" backgroundColors="#80ff00;#e0ff33;red"
|
||||
borderColors="#80ff00;#e0ff33;red"/>
|
||||
</div>
|
||||
<div class="panel med">
|
||||
<field name="planned_chart" widget="pichart" keys="total_planned;total_unplanned"
|
||||
labels="Planned;Un Planned" backgroundColors="#87CEFA;#F0F8FF"
|
||||
borderColors="#F0F8FF;#F0F8FF" cutoutPercentage="85"/>
|
||||
</div>
|
||||
<div class="panel med">
|
||||
<div class="boxes">
|
||||
<div class="box zooba">
|
||||
<div class="box-title">Partially effect</div>
|
||||
<div class="box-content">
|
||||
<field name="total_partially_effect"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box zooba">
|
||||
<div class="box-title">losses of production</div>
|
||||
<div class="box-content">
|
||||
<field name="total_loss"/>
|
||||
units
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="boxes">
|
||||
<div class="box zooba">
|
||||
<div class="box-title">Out of Service</div>
|
||||
<div class="box-content">
|
||||
<field name="total_outservice"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box zooba">
|
||||
<div class="box-title">Downtime</div>
|
||||
<div class="box-content">
|
||||
<field name="total_downtime"/>
|
||||
Hour(s)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Form view for "model" -->
|
||||
<record id="purchase_order_custom_form_view" model="ir.ui.view">
|
||||
<field name="name">view.purchase.order.form</field>
|
||||
<field name="model">purchase.order</field>
|
||||
<field name="inherit_id" ref="purchase_requisition_custom.purchase_order_custom_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='request_id']" position="after">
|
||||
<field name="maintenance_id" readonly="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="maintenance_failure_view_tree" model="ir.ui.view">
|
||||
<field name="name">maintenance.failure.tree</field>
|
||||
<field name="model">maintenance.failure</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Fiulre Types">
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="maintenance_failure_action" model="ir.actions.act_window">
|
||||
<field name="name">Failure Types</field>
|
||||
<field name="res_model">maintenance.failure</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<record id="maintenance_equipments_group_action" model="ir.actions.act_window">
|
||||
<field name="name">Maintenance Equipments</field>
|
||||
<field name="res_model">maintenance.equipments.jobs</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_equipment_order_action" model="ir.actions.act_window">
|
||||
<field name="name">Maintenance Orders</field>
|
||||
<field name="res_model">maintenance.request</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'default_user_id': uid, 'default_entry_source' : 'order'}</field>
|
||||
<field name="domain">['|',('stage_id.stage_type','=','for_order'),('entry_source','=','order')]</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new maintenance request
|
||||
</p>
|
||||
<p>
|
||||
Follow the process of the request and communicate with the collaborator.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="maintenance.hr_equipment_request_action" model="ir.actions.act_window">
|
||||
<field name="domain">['|',('maintenance_type','=','corrective'),('entry_source','=',
|
||||
'request'),('stage_id.stage_type','!=','for_order')]
|
||||
</field>
|
||||
<field name="context">{'default_user_id': uid , 'default_maintenance_category':'unplanned'}</field>
|
||||
</record>
|
||||
|
||||
<record id="action_order_tree" model="ir.actions.act_window.view">
|
||||
<field eval="1" name="sequence"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="act_window_id" ref="hr_equipment_order_action"/>
|
||||
</record>
|
||||
|
||||
<record id="action_request_tree" model="ir.actions.act_window.view">
|
||||
<field eval="1" name="sequence"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="act_window_id" ref="maintenance.hr_equipment_request_action"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="action_order_form" model="ir.actions.act_window.view">
|
||||
<field eval="2" name="sequence"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="hr_equipment_order_view_form"/>
|
||||
<field name="act_window_id" ref="hr_equipment_order_action"/>
|
||||
</record>
|
||||
|
||||
<record id="action_request_form" model="ir.actions.act_window.view">
|
||||
<field eval="2" name="sequence"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="maintenance.hr_equipment_request_view_form"/>
|
||||
<field name="act_window_id" ref="maintenance.hr_equipment_request_action"/>
|
||||
</record>
|
||||
|
||||
<record id="maintenance_summary_dashboard_action" model="ir.actions.act_window">
|
||||
<field name="name">Maintenance Summary</field>
|
||||
<field name="res_model">maintenance.summary</field>
|
||||
<field name="view_id" ref="maintenance_summary_kanban"/>
|
||||
<field name="view_mode">kanban</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Add a new record in the Equipment Category
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_m_request_form" name="Maintenance Orders" parent="maintenance.menu_m_request"
|
||||
action="hr_equipment_order_action" groups="maintenance.group_equipment_manager,base.group_user"
|
||||
sequence="1"/>
|
||||
<menuitem id="menu_m_group_form" name="Maintenance Equipments Group" parent="maintenance.menu_m_request"
|
||||
action="maintenance_equipments_group_action" sequence="5"/>
|
||||
|
||||
<menuitem action="sale.product_template_action" id="menu_product_template_action"
|
||||
parent="maintenance.menu_maintenance_configuration" sequence="1"/>
|
||||
|
||||
<menuitem action="maintenance_failure_action" id="menu_failure_types" name="Failure Types"
|
||||
parent="maintenance.menu_maintenance_configuration" sequence="1"/>
|
||||
|
||||
<menuitem id="maintenance_summary_dashboard_menu" name="Maintenance Summary"
|
||||
parent="maintenance.maintenance_reporting" groups="maintenance.group_equipment_manager,base.group_user"
|
||||
action="maintenance_summary_dashboard_action"/>
|
||||
<menuitem id="equipments_locations_menu" name="Equipments Locations"
|
||||
parent="maintenance.menu_maintenance_configuration"
|
||||
action="equipments_locations_action"/>
|
||||
|
||||
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Customize menu security -->
|
||||
<odoo>
|
||||
<record model="ir.ui.menu" id="maintenance.menu_maintenance_title">
|
||||
<field name="groups_id" eval="[(6,0,[ref('maintenance.group_equipment_manager')])]"/>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1 @@
|
|||
from . import maintenance_report_wiz
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
from datetime import datetime
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
def to_str(array):
|
||||
return ",".join(str(i) for i in array)
|
||||
|
||||
|
||||
class MaintenanceReportWiz(models.TransientModel):
|
||||
_name = 'maintenance.report.wiz'
|
||||
|
||||
time_from = fields.Datetime('From', required=True)
|
||||
time_to = fields.Datetime('To', required=True)
|
||||
equipment_ids = fields.Many2many('maintenance.equipment', 'equipment_report_wiz_rel' , string='Equipment')
|
||||
category_ids = fields.Many2many('maintenance.equipment.category', 'equipment_cat_report_wiz_rel', string='Equipment Category' )
|
||||
spare_categ_ids = fields.Many2many('product.category', 'spare_cat_report_wiz_rel', string='Spare Category' )
|
||||
failure_ids = fields.Many2many('maintenance.failure', 'failure_report_wiz_rel' , string='Failure Type')
|
||||
user_ids = fields.Many2many('res.users', 'users_report_wiz_rel' , string='Supervisor')
|
||||
department_ids = fields.Many2many('hr.department', 'dep_report_wiz_rel' , string='Department')
|
||||
employee_ids = fields.Many2many('hr.employee', 'emp_report_wiz_rel' , string='Members')
|
||||
team_type = fields.Selection([('in', 'Internal Team'), ('out', 'Outsite Entity')], string='Team Type')
|
||||
spare_ids = fields.Many2many('product.template', 'spare_report_wiz_rel' , string='Spare Parts', domain=[('is_spare','=',True)])
|
||||
machine_status = fields.Selection([('out_service', 'Out of Service'),('part','Partially effect'),('in_service','In Service')], string='Machine Status')
|
||||
report_type = fields.Selection([
|
||||
('general', 'General Report'),
|
||||
('spare','Spare Parts'),
|
||||
('equipment', 'Equipment'),
|
||||
('team','Team Members')], string='Report Type')
|
||||
|
||||
def _filters(self):
|
||||
cond = []
|
||||
filters = {}
|
||||
if self.time_from :
|
||||
cond.append(['request_date', '>=' , self.time_from])
|
||||
if self.time_to :
|
||||
cond.append(['request_date', '<=' , self.time_to])
|
||||
if self.equipment_ids :
|
||||
cond.append(['equipment_id', 'in' , self.equipment_ids.ids])
|
||||
stri = ",".join(i.name for i in self.equipment_ids)
|
||||
filters.update({'equipment_id' :stri})
|
||||
if self.category_ids:
|
||||
equipment_ids = self.env.get('maintenance.equipment').search([('category_id', 'in',self.category_ids.ids )])
|
||||
cond.append(['equipment_id', 'in' , equipment_ids.ids])
|
||||
stri = ",".join(i.name for i in self.category_ids)
|
||||
filters.update({'category_id' :stri})
|
||||
if self.user_ids :
|
||||
cond.append(['user_id', 'in' , self.user_ids.ids])
|
||||
stri = ",".join(i.name for i in self.user_ids)
|
||||
filters.update({'user_id' :stri})
|
||||
if self.failure_ids :
|
||||
cond.append(['failure_id', 'in' , self.failure_ids.ids])
|
||||
stri = " , ".join(i.name for i in self.failure_ids)
|
||||
filters.update({'failure_id' :stri})
|
||||
if self.team_type :
|
||||
cond.append(['team_type', '=' , self.team_type])
|
||||
stri = self.team_type == 'in' and 'Internal Team' or 'Outsite Entity'
|
||||
filters.update({'team_type' :stri})
|
||||
if self.machine_status :
|
||||
cond.append(['machine_status', '=' , self.machine_status])
|
||||
stri = self.team_type
|
||||
filters.update({'machine_status' :stri})
|
||||
if self.spare_ids or self.report_type == 'spare' :
|
||||
ids = self.spare_ids and self.spare_ids.ids or self.env.get('product.template').search([('is_spare', '=', True)]).ids
|
||||
spare_ids = self.env.get('maintenance.request.spare').search([('spare_id', 'in',ids )])
|
||||
order_ids = [s.request_id.id for s in spare_ids]
|
||||
cond.append(['id', 'in' , order_ids])
|
||||
stri = " , ".join(i.name for i in self.spare_ids)
|
||||
filters.update({'spare_id' :stri})
|
||||
if self.department_ids or self.employee_ids or self.report_type == 'team' :
|
||||
emp_cond = []
|
||||
if self.department_ids :
|
||||
emp_cond += [('department_id', 'in', self.department_ids.ids)]
|
||||
dep_stri = " , ".join(i.name for i in self.department_ids)
|
||||
filters.update({'department_id' :dep_stri})
|
||||
emp_ids = self.employee_ids.ids and self.employee_ids.ids or self.env.get('hr.employee').search(emp_cond).ids
|
||||
emp_ids_str = " , ".join(str(i) for i in emp_ids)
|
||||
query = '''
|
||||
select maintenance_request_id from req_member_rel where hr_employee_id in (%s)
|
||||
'''%(emp_ids_str)
|
||||
self.env.cr.execute(query)
|
||||
res = self.env.cr.fetchall()
|
||||
order_ids = [r[0] for r in res]
|
||||
cond.append(['id', 'in' , order_ids])
|
||||
stri = " , ".join(i.name for i in self.env['hr.employee'].browse(emp_ids))
|
||||
filters.update({'employee_id' :stri})
|
||||
if self.spare_categ_ids:
|
||||
product_ids = self.env.get('product.template').search([('categ_id', 'in',self.spare_categ_ids.ids ),('is_spare', '=', True)])
|
||||
spare_ids = self.env.get('maintenance.request.spare').search([('spare_id', 'in',product_ids.ids )])
|
||||
order_ids = [s.request_id.id for s in spare_ids]
|
||||
cond.append(['id', 'in' , order_ids])
|
||||
stri = " , ".join(i.name for i in self.spare_categ_ids)
|
||||
filters.update({'spare_categ_id' :stri})
|
||||
return cond , filters
|
||||
|
||||
def print_report(self):
|
||||
cond , filters = self._filters()
|
||||
requests = self.env.get('maintenance.request').search(cond)
|
||||
if not requests :
|
||||
raise ValidationError(_('Connot Find any Request/Order .'))
|
||||
time_from = self.time_from
|
||||
time_to = self.time_to
|
||||
totals = self.compute_general_report(requests)
|
||||
data = {
|
||||
'form' : {
|
||||
'time_from' : time_from,
|
||||
'time_to' : time_to,
|
||||
'total' : totals,
|
||||
'filters' : filters,
|
||||
'rec_ids' : requests.ids + [0],
|
||||
'spare_categ_ids' : self.spare_categ_ids.ids,
|
||||
'spare_ids' : self.spare_ids.ids,
|
||||
'category_ids' : self.category_ids.ids,
|
||||
'equipment_ids' : self.equipment_ids.ids,
|
||||
'employee_ids' : self.employee_ids.ids,
|
||||
'department_ids' : self.department_ids.ids,
|
||||
},
|
||||
}
|
||||
if self.report_type == 'general':
|
||||
report = self.env.ref('maintenance_custom.action_general_maintenance_report').report_action(requests,data=data)
|
||||
elif self.report_type == 'spare':
|
||||
report = self.env.ref('maintenance_custom.action_spare_part_report').report_action(requests,data=data)
|
||||
if self.report_type == 'equipment':
|
||||
report = self.env.ref('maintenance_custom.action_equipment_report').report_action(requests,data=data)
|
||||
if self.report_type == 'team':
|
||||
report = self.env.ref('maintenance_custom.action_maintenance_team_report').report_action(requests,data=data)
|
||||
return report
|
||||
|
||||
|
||||
|
||||
def _get_total_members(self, order_str):
|
||||
query = '''
|
||||
SELECT
|
||||
count(distinct hr_employee_id )
|
||||
FROM req_member_rel WHERE maintenance_request_id IN (%s)
|
||||
|
||||
'''%(order_str)
|
||||
self.env.cr.execute(query)
|
||||
try :
|
||||
total = self.env.cr.fetchall()[0][0]
|
||||
except :
|
||||
total = 0
|
||||
return total
|
||||
|
||||
|
||||
def _get_total_equipment(self, order_str):
|
||||
query = '''
|
||||
SELECT count(distinct equipment_id)
|
||||
FROM maintenance_request WHERE id IN (%s)
|
||||
'''%(order_str)
|
||||
self.env.cr.execute(query)
|
||||
try :
|
||||
total = self.env.cr.fetchall()[0][0]
|
||||
except :
|
||||
total = 0
|
||||
return total
|
||||
|
||||
|
||||
def _get_total_cost(self, order_str):
|
||||
query = '''
|
||||
SELECT sum(quantity * cost) FROM maintenance_request_spare WHERE request_id IN (%s)
|
||||
'''%(order_str)
|
||||
self.env.cr.execute(query)
|
||||
try :
|
||||
total = self.env.cr.fetchall()[0][0]
|
||||
except :
|
||||
total = 0
|
||||
return total
|
||||
|
||||
|
||||
def _get_total_downtime(self, order_str):
|
||||
query = '''
|
||||
SELECT sum(down_time)
|
||||
FROM maintenance_request WHERE id IN (%s) and machine_status = 'out_service'
|
||||
'''%(order_str)
|
||||
self.env.cr.execute(query)
|
||||
try :
|
||||
total = self.env.cr.fetchall()[0][0]
|
||||
except :
|
||||
total = 0
|
||||
return total
|
||||
|
||||
|
||||
def _get_total_loss(self, order_str):
|
||||
query = '''
|
||||
SELECT sum(product_loss)
|
||||
FROM maintenance_request WHERE id IN (%s) and machine_status = 'part'
|
||||
'''%(order_str)
|
||||
self.env.cr.execute(query)
|
||||
try :
|
||||
total = self.env.cr.fetchall()[0][0]
|
||||
except :
|
||||
total = 0
|
||||
return total
|
||||
|
||||
|
||||
def _get_total_over_due(self, order_str):
|
||||
query = '''
|
||||
SELECT count(id) FROM maintenance_request
|
||||
WHERE duration > 0 AND done_time >= schedule_date + interval '1' HOUR * duration
|
||||
AND id in (%s) and stage_id in (select id from maintenance_stage where stage_type = 'request_done' )
|
||||
'''%(order_str)
|
||||
self.env.cr.execute(query)
|
||||
try :
|
||||
total = self.env.cr.fetchall()[0][0]
|
||||
except :
|
||||
total = 0
|
||||
return total
|
||||
|
||||
|
||||
def _get_total_planned(self, order_ids):
|
||||
count = self.env.get('maintenance.request').search_count([
|
||||
('id', 'in', order_ids),
|
||||
('maintenance_category','=', 'planned')
|
||||
])
|
||||
return count
|
||||
|
||||
|
||||
def _get_high_priority(self, order_ids):
|
||||
count = self.env.get('maintenance.request').search_count([
|
||||
('id', 'in', order_ids),
|
||||
('priority','=', '3')
|
||||
])
|
||||
return count
|
||||
|
||||
|
||||
def _get_total_closed(self, order_ids):
|
||||
res = self.env.get('maintenance.stage').search([('stage_type', '=', 'request_done')])
|
||||
stage_done = res.ids
|
||||
count = self.env.get('maintenance.request').search_count([
|
||||
('id', 'in', order_ids),
|
||||
('stage_id','in', stage_done),
|
||||
])
|
||||
return count
|
||||
|
||||
|
||||
def _get_total_open(self,order_ids):
|
||||
res = self.env.get('maintenance.stage').search([('stage_type', '!=', 'request_done')])
|
||||
stage_open = res.ids
|
||||
count = self.env.get('maintenance.request').search_count([
|
||||
('id', 'in', order_ids),
|
||||
('stage_id','in', stage_open),
|
||||
])
|
||||
return count
|
||||
|
||||
def _get_total_working_hours(self,order_str):
|
||||
res = self.env.get('maintenance.stage').search([('done', '=', True)])
|
||||
stage_done = res.ids
|
||||
query = '''
|
||||
SELECT sum(EXTRACT(EPOCH FROM done_time-start_time)/3600) FROM maintenance_request
|
||||
WHERE Stage_id in (%s) and id in (%s)
|
||||
'''%(to_str(stage_done), order_str)
|
||||
self.env.cr.execute(query)
|
||||
try :
|
||||
total = self.env.cr.fetchall()[0][0]
|
||||
total = round(total,2)
|
||||
except :
|
||||
total = 0
|
||||
return total
|
||||
|
||||
|
||||
def compute_general_report(self, orders):
|
||||
order_ids = orders.ids
|
||||
order_str = ",".join(str(i) for i in order_ids)
|
||||
total_orders = len(order_ids)
|
||||
planned = round((self._get_total_planned(order_ids) / float(total_orders) * 100 ), 2)
|
||||
overdue = self._get_total_over_due(order_str)
|
||||
over_due_percentage = overdue / total_orders * 100
|
||||
over_due_percentage = round(over_due_percentage, 2)
|
||||
res = {
|
||||
'total_equipment' : self._get_total_equipment(order_str),
|
||||
'total_members' : self._get_total_members(order_str),
|
||||
'total_orders' : total_orders ,
|
||||
'total_over_due' : overdue,
|
||||
'over_due_percentage' : over_due_percentage ,
|
||||
'total_planned' : planned,
|
||||
'total_high' : self._get_high_priority(order_ids),
|
||||
'total_loss' : self._get_total_loss(order_str),
|
||||
'total_downtime' : self._get_total_downtime(order_str),
|
||||
'total_colse' : self._get_total_closed(order_ids),
|
||||
'total_open' : self._get_total_open(order_ids),
|
||||
'total_working_hours' : self._get_total_working_hours(order_str),
|
||||
'total_cost' : self._get_total_cost(order_str),
|
||||
}
|
||||
return res
|
||||
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="maintenance_report_wiz_view" model="ir.ui.view">
|
||||
<field name="name">maintenance.report.wiz.form</field>
|
||||
<field name="model">maintenance.report.wiz</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Maintenance Reports">
|
||||
<group>
|
||||
|
||||
<group>
|
||||
|
||||
<field name="time_from" />
|
||||
<field name="category_ids" widget="many2many_tags" attrs="{'invisible':[('report_type','not in', ['general'])]}"/>
|
||||
<field name="spare_categ_ids" widget="many2many_tags" attrs="{'invisible':[('report_type','not in', ['spare'])]}" />
|
||||
<field name="failure_ids" widget="many2many_tags" attrs="{'invisible':[('report_type','not in', ['general'])]}" />
|
||||
<field name="user_ids" widget="many2many_tags" attrs="{'invisible':[('report_type','not in', ['general'])]}" />
|
||||
<field name="spare_ids" widget="many2many_tags" attrs="{'invisible':[('report_type', 'in', ['team'])]}"/>
|
||||
<field name="department_ids" widget="many2many_tags" attrs="{'invisible':[('report_type','not in', ['team'])]}" />
|
||||
<field name="machine_status" attrs="{'invisible':[('report_type','not in', ['general' ,'equipment'])]}" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="time_to" />
|
||||
<field name="employee_ids" widget="many2many_tags" attrs="{'invisible':[('report_type','not in', ['general', 'team'])]}" />
|
||||
<field name="equipment_ids" widget="many2many_tags" attrs="{'invisible':[('report_type','in', ['team'])]}"/>
|
||||
<field name="team_type" attrs="{'invisible':[('report_type','not in', ['general'])]}" />
|
||||
<field name="report_type" invisible="1" />
|
||||
</group>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="print_report" type="object" string="Print" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_maintenance_report_wiz" model="ir.actions.act_window">
|
||||
<field name="name">General Maintenance Reports</field>
|
||||
<field name="res_model">maintenance.report.wiz</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="context">{'default_report_type' : 'general'}</field>
|
||||
</record>
|
||||
|
||||
<record id="action_spare_report_wiz" model="ir.actions.act_window">
|
||||
<field name="name">Spare Parts Reports</field>
|
||||
<field name="res_model">maintenance.report.wiz</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="context">{'default_report_type' : 'spare'}</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="action_equipment_report_wiz" model="ir.actions.act_window">
|
||||
<field name="name">Equipment Reports</field>
|
||||
<field name="res_model">maintenance.report.wiz</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="context">{'default_report_type' : 'equipment'}</field>
|
||||
</record>
|
||||
|
||||
<record id="action_team_report_wiz" model="ir.actions.act_window">
|
||||
<field name="name">Teams Reports</field>
|
||||
<field name="res_model">maintenance.report.wiz</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="context">{'default_report_type' : 'team'}</field>
|
||||
</record>
|
||||
|
||||
|
||||
<menuitem
|
||||
action="action_maintenance_report_wiz"
|
||||
id="maintenance_report_menu"
|
||||
name="Maintenance Reports"
|
||||
parent="maintenance.maintenance_reporting"
|
||||
/>
|
||||
|
||||
<menuitem
|
||||
action="action_spare_report_wiz"
|
||||
id="spare_report_menu"
|
||||
name="Spare Parts Reports"
|
||||
parent="maintenance.maintenance_reporting"
|
||||
/>
|
||||
|
||||
<menuitem
|
||||
action="action_equipment_report_wiz"
|
||||
id="equipment_report_menu"
|
||||
name="Equipment Reports"
|
||||
parent="maintenance.maintenance_reporting"
|
||||
/>
|
||||
|
||||
<menuitem
|
||||
action="action_team_report_wiz"
|
||||
id="team_report_menu"
|
||||
name="Maintenance Team Reports"
|
||||
parent="maintenance.maintenance_reporting"
|
||||
/>
|
||||
|
||||
</odoo>
|
||||
Loading…
Reference in New Issue