diff --git a/maintenance_usage/README.rst b/maintenance_usage/README.rst
new file mode 100644
index 00000000..865420ea
--- /dev/null
+++ b/maintenance_usage/README.rst
@@ -0,0 +1,41 @@
+*************************
+Hibou - Maintenance Usage
+*************************
+
+Keep track of usage on different types of equipment.
+
+For more information and add-ons, visit `Hibou.io `_.
+
+=============
+Main Features
+=============
+
+* New Model: Maintenance Usage Log
+* Adds new fields for usage on equipments.
+* Adds new descriptive UOM on categories.
+* Allows users to create preventative maintenance requests based on usage.
+* Creates Maintenance Log based on changes in usage or employee ownership, to provide a report on equipment changes over time.
+
+
+.. image:: https://user-images.githubusercontent.com/15882954/41305818-f62a43b6-6e28-11e8-9d30-80d06b273354.png
+ :alt: 'Equipment Detail'
+ :width: 988
+ :align: left
+
+New Equipment Usage View
+
+.. image:: https://user-images.githubusercontent.com/15882954/41305848-09a038ec-6e29-11e8-9ad5-7b3d34bd7b64.png
+ :alt: 'Equipment Usage Detail'
+ :width: 988
+ :align: left
+
+
+
+
+=======
+License
+=======
+
+Please see `LICENSE `_.
+
+Copyright Hibou Corp. 2018
diff --git a/maintenance_usage/__init__.py b/maintenance_usage/__init__.py
new file mode 100644
index 00000000..0650744f
--- /dev/null
+++ b/maintenance_usage/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/maintenance_usage/__manifest__.py b/maintenance_usage/__manifest__.py
new file mode 100644
index 00000000..d8d6eaba
--- /dev/null
+++ b/maintenance_usage/__manifest__.py
@@ -0,0 +1,26 @@
+{
+ 'name': 'Equipment Usage',
+ 'version': '12.0.1.0.0',
+ 'author': 'Hibou Corp. ',
+ 'category': 'Human Resources',
+ 'summary': 'Keep track of usage on different types of equipment.',
+ 'description': """
+Equipment Usage
+===============
+
+Keep track of usage on different types of equipment. Adds fields for usage on equipments
+and descriptive UOM on categories.
+
+Create preventative maintenance requests based on usage.
+""",
+ 'website': 'https://hibou.io/',
+ 'depends': [
+ 'hr_maintenance',
+ ],
+ 'data': [
+ 'security/ir.model.access.csv',
+ 'views/maintenance_views.xml',
+ ],
+ 'installable': True,
+ 'auto_install': False,
+}
\ No newline at end of file
diff --git a/maintenance_usage/models/__init__.py b/maintenance_usage/models/__init__.py
new file mode 100644
index 00000000..12bf298f
--- /dev/null
+++ b/maintenance_usage/models/__init__.py
@@ -0,0 +1 @@
+from . import maintenance
diff --git a/maintenance_usage/models/maintenance.py b/maintenance_usage/models/maintenance.py
new file mode 100644
index 00000000..61ce9130
--- /dev/null
+++ b/maintenance_usage/models/maintenance.py
@@ -0,0 +1,113 @@
+from math import floor
+from odoo import api, fields, models
+
+
+class MaintenanceEquipmentCategory(models.Model):
+ _inherit = 'maintenance.equipment.category'
+
+ usage_uom_id = fields.Many2one('uom.uom', string='Usage UOM')
+
+
+class MaintenanceEquipment(models.Model):
+ _inherit = 'maintenance.equipment'
+
+ employee_id = fields.Many2one(track_visibility=False)
+ department_id = fields.Many2one(track_visibility=False)
+ usage_qty = fields.Float(string='Usage', default=0.0)
+ usage_uom_id = fields.Many2one('uom.uom', related='category_id.usage_uom_id')
+ usage_log_ids = fields.One2many('maintenance.usage.log', 'equipment_id', string='Usage')
+ usage_count = fields.Integer(string='Usage Count', compute='_compute_usage_count')
+ maintenance_usage = fields.Float(string='Preventative Usage')
+
+ def _compute_usage_count(self):
+ for equipment in self:
+ equipment.usage_count = len(equipment.usage_log_ids)
+
+ @api.model
+ def create(self, values):
+ record = super(MaintenanceEquipment, self).create(values)
+ # create first usage record
+ record._log_usage()
+ return record
+
+ @api.multi
+ def write(self, values):
+ usage_qty = values.get('usage_qty')
+ employee_id = values.get('employee_id')
+ department_id = values.get('department_id')
+ if any((usage_qty, employee_id, department_id)):
+ for equipment in self:
+ log_values = {}
+
+ if (equipment.usage_qty is not None
+ and usage_qty is not None
+ and abs(usage_qty - equipment.usage_qty) > 0.0001):
+ log_values['qty'] = usage_qty
+ if employee_id != equipment.employee_id.id:
+ log_values['employee_id'] = employee_id
+ if department_id != equipment.department_id.id:
+ log_values['department_id'] = department_id
+
+ if log_values:
+ equipment._log_usage(values=log_values)
+
+ # Check to have the original fields before write.
+ self._check_maintenance_usage(usage_qty)
+
+ result = super(MaintenanceEquipment, self).write(values)
+ return result
+
+ def _log_usage(self, values={}):
+ values['equipment_id'] = self.id
+ values['date'] = fields.Datetime.now()
+ self.env['maintenance.usage.log'].create(values)
+
+ @api.multi
+ def _check_maintenance_usage(self, usage_qty):
+ for e in self.filtered(lambda e: e.maintenance_usage):
+ try:
+ if floor(e.usage_qty / e.maintenance_usage) != floor(usage_qty / e.maintenance_usage):
+ next_requests = self.env['maintenance.request'].search([('stage_id.done', '=', False),
+ ('equipment_id', '=', e.id),
+ ('maintenance_type', '=', 'preventive'),
+ ])
+ if not next_requests:
+ e._create_new_request(fields.Date.today())
+ except TypeError:
+ pass
+
+ def action_open_usage_log(self):
+ for equipment in self:
+ action = self.env.ref('maintenance_usage.maintenance_usage_log_action_reports').read()[0]
+ action['domain'] = [('equipment_id', '=', equipment.id)]
+ action['context'] = {
+ 'default_equipment_id': equipment.id,
+ 'default_employee_id': equipment.employee_id.id,
+ 'default_department_id': equipment.department_id.id,
+ 'default_qty': equipment.usage_qty,
+ }
+ return action
+
+
+class MaintenanceUsageLog(models.Model):
+ _name = 'maintenance.usage.log'
+ _order = 'date DESC'
+ _log_access = False
+
+ date = fields.Datetime(string='Date', default=fields.Datetime.now)
+ equipment_id = fields.Many2one('maintenance.equipment', string='Equipment', required=True)
+ employee_id = fields.Many2one('hr.employee', string='Employee')
+ department_id = fields.Many2one('hr.department', string='Department')
+ qty = fields.Float(string='Quantity')
+ uom_id = fields.Many2one(string='Unit of Measure', related='equipment_id.category_id.usage_uom_id')
+
+ @api.model
+ def create(self, values):
+ equipment = self.env['maintenance.equipment'].browse(values.get('equipment_id'))
+ if not values.get('employee_id'):
+ values['employee_id'] = equipment.employee_id.id
+ if not values.get('department_id'):
+ values['department_id'] = equipment.department_id.id
+ if not values.get('qty'):
+ values['qty'] = equipment.usage_qty
+ return super(MaintenanceUsageLog, self).create(values)
diff --git a/maintenance_usage/security/ir.model.access.csv b/maintenance_usage/security/ir.model.access.csv
new file mode 100644
index 00000000..aea213d8
--- /dev/null
+++ b/maintenance_usage/security/ir.model.access.csv
@@ -0,0 +1,3 @@
+"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
+"manage_maintenance_usage_log","manage maintenance.usage.log","model_maintenance_usage_log","stock.group_stock_manager",1,1,1,1
+"access_maintenance_usage_log","access maintenance.usage.log","model_maintenance_usage_log","base.group_user",1,0,1,0
\ No newline at end of file
diff --git a/maintenance_usage/tests/__init__.py b/maintenance_usage/tests/__init__.py
new file mode 100644
index 00000000..bd38ce7a
--- /dev/null
+++ b/maintenance_usage/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_maintenance_usage
diff --git a/maintenance_usage/tests/test_maintenance_usage.py b/maintenance_usage/tests/test_maintenance_usage.py
new file mode 100644
index 00000000..d0d9992f
--- /dev/null
+++ b/maintenance_usage/tests/test_maintenance_usage.py
@@ -0,0 +1,43 @@
+from odoo.tests import common
+
+
+class TestMaintenanceUsage(common.TransactionCase):
+ """Tests for usage on creation and update
+ """
+
+ def test_create(self):
+ test_usage = 21.0
+ equipment = self.env['maintenance.equipment'].create({
+ 'name': 'Monitor',
+ 'usage_qty': test_usage,
+ })
+
+ self.assertTrue(equipment.usage_log_ids)
+ self.assertEqual(equipment.usage_log_ids[0].qty, test_usage)
+
+ def test_update(self):
+ test_usage = 21.0
+ test_usage2 = 50.1
+ equipment = self.env['maintenance.equipment'].create({
+ 'name': 'Monitor',
+ 'usage_qty': test_usage,
+ })
+ equipment.usage_qty = test_usage2
+ updated_usage = equipment.usage_log_ids.filtered(lambda u: abs(u.qty - test_usage2) < 0.01)
+
+ self.assertTrue(updated_usage)
+ self.assertAlmostEqual(updated_usage[0].qty, test_usage2)
+
+ def test_maintenance_usage(self):
+ test_usage = 21.0
+ test_usage2 = 50.1
+ equipment = self.env['maintenance.equipment'].create({
+ 'name': 'Monitor',
+ 'usage_qty': test_usage,
+ 'maintenance_usage': 20.0,
+ 'maintenance_team_id': self.env['maintenance.team'].search([], limit=1).id
+ })
+ self.assertFalse(equipment.maintenance_ids)
+
+ equipment.usage_qty = test_usage2
+ self.assertTrue(equipment.maintenance_ids)
diff --git a/maintenance_usage/views/maintenance_views.xml b/maintenance_usage/views/maintenance_views.xml
new file mode 100644
index 00000000..2baf2b73
--- /dev/null
+++ b/maintenance_usage/views/maintenance_views.xml
@@ -0,0 +1,154 @@
+
+
+
+ maintenance.equipment.category.inherited
+ maintenance.equipment.category
+
+
+
+
+
+
+
+
+
+
+
+ equipment.form.inherited
+ maintenance.equipment
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ equipment.usage.log.search
+ maintenance.usage.log
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ equipment.usage.log.form
+ maintenance.usage.log
+
+
+
+
+
+
+ equipment.usage.log.tree
+ maintenance.usage.log
+
+
+
+
+
+
+
+
+
+
+
+
+
+ equipment.usage.log.graph
+ maintenance.usage.log
+
+
+
+
+
+
+
+
+
+ equipment.usage.log.pivot
+ maintenance.usage.log
+
+
+
+
+
+
+
+
+
+ equipment.usage.log.calendar
+ maintenance.usage.log
+
+
+
+
+
+
+
+
+
+
+ Equipment Usage
+ maintenance.usage.log
+ tree,form,graph,pivot,calendar
+
+
+ No usage.
+
+
+
+
+
+
\ No newline at end of file