900 lines
38 KiB
Python
900 lines
38 KiB
Python
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
# this repository contains the full copyright notices and license terms.
|
|
from trytond.model import (
|
|
Workflow, ModelSQL, ModelView, Unique, fields, sequence_ordered)
|
|
from trytond.wizard import (
|
|
Button, StateAction, StateTransition, StateView, Wizard)
|
|
from trytond.transaction import Transaction
|
|
from trytond.pyson import Bool, Eval, If, Id
|
|
from trytond.pool import Pool
|
|
from trytond.modules.currency.fields import Monetary
|
|
from trytond.modules.product import price_digits
|
|
|
|
import datetime
|
|
from datetime import timedelta
|
|
|
|
from scipy.stats import t
|
|
import matplotlib.pyplot as plt
|
|
import numpy as np
|
|
import math as mt
|
|
|
|
from io import BytesIO
|
|
from trytond.exceptions import UserError
|
|
|
|
_digits = (16, 2)
|
|
|
|
class MaintenanceService(Workflow, ModelSQL, ModelView):
|
|
'Equipment Maintenance Service'
|
|
__name__ = 'optical_equipment_maintenance.service'
|
|
_rec_name = 'rec_name'
|
|
_order_name = 'code'
|
|
|
|
|
|
_states = {'readonly': If(Eval('state') != 'draft', True)}
|
|
|
|
code = fields.Char("Code", readonly=True, select=True)
|
|
reference = fields.Char("Reference", select=True,
|
|
help="The identification of an external origin.")
|
|
description = fields.Char("Description",states=_states)
|
|
sale_date = fields.Char("Sale Date")
|
|
contract_origin = fields.Reference("Contract Base", selection='get_origin_contract', select=True,
|
|
states={'readonly': True})
|
|
sale_origin = fields.Reference("Sale Origin", selection='get_origin', select=True,
|
|
states={'readonly': True})
|
|
company = fields.Many2One('company.company', "Company", readonly=True)
|
|
maintenance_type = fields.Selection([('preventive', 'Preventive'),
|
|
('corrective', 'Corrective')
|
|
], "Maintenance Type", states=_states)
|
|
propietary = fields.Many2One('party.party', "Propietary", required=True, states=_states)
|
|
propietary_address = fields.Many2One('party.address', "Propietary Address", required=True,
|
|
domain=[('party', '=', Eval('propietary'))],
|
|
states=_states)
|
|
lines = fields.One2Many('optical_equipment.maintenance', 'service_maintenance', "Lines",
|
|
states={'readonly': If(Eval('state') != 'in_progress', True)})
|
|
estimated_agended = fields.DateTime("Date Maintenance", states=_states)
|
|
history_agended = fields.Many2Many('optical_equipment_maintenance.service-maintenance.diary', 'maintenance_service', 'agended', "History Agended", readonly=True)
|
|
state_agended = fields.Selection([('no_agenda', "No agenda"),
|
|
('agended', "Agended"),
|
|
('in_progress', "In progress"),
|
|
('finish', "Finish"),
|
|
('failed', "Failed")], "State Agenda", states=_states)
|
|
technical = fields.Many2One('company.employee', "Technical", states=_states)
|
|
|
|
state = fields.Selection([('draft', "Draft"),
|
|
('agended', "Agended"),
|
|
('in_progress', "In Progress"),
|
|
('failed', "Failed"),
|
|
('finished', "Finished")
|
|
], "State", required=True, readonly=True, sort=True)
|
|
|
|
rec_name = fields.Function(fields.Char('rec_name'), 'get_rec_name')
|
|
|
|
@fields.depends('maintenance_type', 'code')
|
|
def get_rec_name(self, name):
|
|
if self.maintenance_type and self.code:
|
|
name = str(self.maintenance_type) + '@' + str(self.code)
|
|
else:
|
|
name = str(self.maintenance_type) + '@' + 'Borrador'
|
|
|
|
return name
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(MaintenanceService, cls).__setup__()
|
|
cls._transitions = ({
|
|
('draft', 'agended'),
|
|
('agended', 'in_progress'),
|
|
('in_progress', 'finished'),
|
|
})
|
|
cls._buttons.update({
|
|
'in_progress': {'invisible': Eval('state').in_(['draft', 'in_progress', 'finished'])},
|
|
'finished': {'invisible': Eval('state').in_(['draft', 'agended', 'finished'])}
|
|
})
|
|
|
|
@staticmethod
|
|
def default_company():
|
|
return Transaction().context.get('company')
|
|
|
|
@classmethod
|
|
def default_maintenance_type(self):
|
|
return 'preventive'
|
|
|
|
@classmethod
|
|
def default_state_agended(self):
|
|
return 'no_agenda'
|
|
|
|
@classmethod
|
|
def default_state(self):
|
|
return 'draft'
|
|
|
|
@classmethod
|
|
def _get_origin(cls):
|
|
'Return list of Model names for origin Reference'
|
|
pool = Pool()
|
|
Sale = pool.get('sale.line')
|
|
|
|
return [Sale.__name__]
|
|
|
|
@classmethod
|
|
def get_origin(cls):
|
|
Model = Pool().get('ir.model')
|
|
get_name = Model.get_name
|
|
models = cls._get_origin()
|
|
|
|
return [(None, '')] + [(m, get_name(m)) for m in models]
|
|
|
|
@classmethod
|
|
def _get_origin_contract(cls):
|
|
'Return list of Model names for origin Reference'
|
|
pool = Pool()
|
|
Contract = pool.get('optical_equipment.contract')
|
|
return [Contract.__name__]
|
|
|
|
|
|
@classmethod
|
|
def get_origin_contract(cls):
|
|
Model = Pool().get('ir.model')
|
|
get_name = Model.get_name
|
|
models = cls._get_origin_contract()
|
|
return [(None, '')] + [(m, get_name(m)) for m in models]
|
|
|
|
@classmethod
|
|
def set_code(cls, maintenance):
|
|
pool = Pool()
|
|
Config = pool.get('optical_equipment.configuration')
|
|
config = Config(2)
|
|
if config.maintenance_sequence != None:
|
|
if not maintenance.code:
|
|
try:
|
|
maintenance.code = config.maintenance_sequence.get()
|
|
maintenance.save()
|
|
except UserError:
|
|
raise UserError(str('Validation Error'))
|
|
else:
|
|
raise UserError(gettext('optical_equipment.msg_not_sequence_equipment'))
|
|
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('in_progress')
|
|
def in_progress(cls, maintenances):
|
|
pass
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('finished')
|
|
def finished(cls, maintenances):
|
|
pass
|
|
|
|
|
|
class Maintenance(Workflow, ModelSQL, ModelView):
|
|
'Equipment Maintenance'
|
|
__name__ = 'optical_equipment.maintenance'
|
|
|
|
_states={'required': True,
|
|
'readonly': Eval('state').in_(['finished'])}
|
|
|
|
service_maintenance = fields.Many2One('optical_equipment_maintenance.service', "Maintenance Service",
|
|
ondelete='CASCADE', select=True,
|
|
states=_states)
|
|
code = fields.Char(
|
|
"Code", select=True,states={'readonly': True })
|
|
maintenance_type = fields.Selection([('preventive', 'Preventive'),
|
|
('corrective', 'Corrective')
|
|
], "Maintenance Type", states=_states)
|
|
state = fields.Selection([('draft', "Draft"),
|
|
('finished', "Finished")
|
|
], "State", readonly=True, sort=False,
|
|
states=_states)
|
|
company = fields.Many2One('company.company', "Company", readonly=True)
|
|
propietary = fields.Many2One('party.party', "Propietary", states=_states,
|
|
depends=['service_maintenance'])
|
|
propietary_address = fields.Many2One('party.address', "Propietary Address",
|
|
states=_states,
|
|
domain=[('party', '=', Eval('propietary'))],
|
|
depends=['service_maintenance'])
|
|
equipment = fields.Many2One('optical_equipment.equipment', "Equipment",
|
|
domain=[('propietary', '=', Eval('propietary'))],
|
|
states=_states,
|
|
depends=['service_maintenance'])
|
|
#when the maintenance is in agended status
|
|
diary = fields.One2Many('optical_equipment_maintenance.diary', 'diary')
|
|
#Preventive maintenance
|
|
initial_operation = fields.Boolean("Verificiación inicial de funcionamiento")
|
|
check_equipment = fields.Boolean("Revisión del Equipo")
|
|
check_electric_system = fields.Boolean("Revisión del sistema electríco")
|
|
clean_int_ext = fields.Boolean("Limpieza interior y exterior")
|
|
clean_eyes = fields.Boolean("Limpieza de lentes y espejos")
|
|
optical = fields.Boolean("Optical")
|
|
check_calibration = fields.Boolean("Verificar Calibración")
|
|
maintenance_activity = fields.One2Many('optical_equipment_maintenance.activity', 'maintenance', "Maintenance Activitys")
|
|
#Calibration
|
|
patterns_equipments = fields.Char("K Pattern", states={'readonly': True},
|
|
depends=['equipment'])
|
|
lines_calibration = fields.One2Many('optical_equipment.maintenance.calibration_sample', 'maintenance', "Lines of Calibration",
|
|
states={'readonly': Eval('state') == 'finished'})
|
|
|
|
calibration_total = fields.One2Many('optical_equipment.maintenance.calibration', 'maintenance', "Calibration Total",
|
|
states={'readonly': Eval('state') == 'finished'})
|
|
maintenance_lines = fields.One2Many('optical_equipment.maintenance.line', 'maintenance', 'Lines')
|
|
description_activity = fields.Char('Activity')
|
|
next_maintenance = fields.Function(fields.Date('Next Maintenance'), 'get_next_maintenance')
|
|
|
|
graph_calibration = fields.Binary('Graphs')
|
|
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super(Maintenance, cls).__setup__()
|
|
cls._transitions.update({
|
|
('draft', 'finished')
|
|
})
|
|
cls._buttons.update({
|
|
'in_progress': {'invisible': Eval('state').in_(['draft', 'in_progress', 'finished'])},
|
|
'finished': {'invisible': (Eval('state').in_(['finished'])) |
|
|
((Eval('maintenance_type') == 'corrective') & (Eval('maintenance_lines') == ())) |
|
|
(Eval('calibration_total') == ())},
|
|
'calibrate': {'invisible': (Eval('lines_calibration') == ()) | (Eval('state').in_(['finished'])),
|
|
'depends': ['state'],}
|
|
})
|
|
|
|
@classmethod
|
|
def view_attributes(cls):
|
|
return super(Maintenance, cls).view_attributes() + [
|
|
('//page[@id="preventive"]', 'states', {
|
|
'invisible': If(Eval('maintenance_type') != 'preventive', True),
|
|
}),
|
|
('//page[@id="corrective"]', 'states',{
|
|
'invisible': If(Eval('maintenance_type') != 'corrective', True),
|
|
})
|
|
]
|
|
|
|
@staticmethod
|
|
def default_company():
|
|
return Transaction().context.get('company')
|
|
|
|
@classmethod
|
|
def default_state(cls):
|
|
return 'draft'
|
|
|
|
@classmethod
|
|
def default_maintenance_type(cls):
|
|
return 'preventive'
|
|
|
|
@classmethod
|
|
def default_state_agended(cls):
|
|
return 'no_agenda'
|
|
|
|
@classmethod
|
|
def default_initial_operation(self):
|
|
return True
|
|
|
|
@classmethod
|
|
def default_check_equipment(self):
|
|
return True
|
|
|
|
@classmethod
|
|
def default_check_electric_system(self):
|
|
return True
|
|
|
|
@classmethod
|
|
def default_clean_int_ext(self):
|
|
return True
|
|
|
|
@classmethod
|
|
def default_clean_eyes(self):
|
|
return True
|
|
|
|
@classmethod
|
|
def default_optical(self):
|
|
return True
|
|
|
|
@classmethod
|
|
def default_check_calibration(self):
|
|
return True
|
|
|
|
def get_next_maintenance(self, action):
|
|
next_maintenance = None
|
|
if self.service_maintenance.estimated_agended:
|
|
if self.propietary.client_type == "ips":
|
|
next_maintenance = self.service_maintenance.estimated_agended + timedelta(days=365)
|
|
else:
|
|
next_maintenance = self.service_maintenance.estimated_agended + timedelta(days=182)
|
|
return next_maintenance
|
|
|
|
def get_standard_deviation(samples):
|
|
"""
|
|
This function calculated the
|
|
standartd deviation
|
|
"""
|
|
sum_samples = sum(samples)
|
|
n_samples = len(samples)
|
|
mean = sum_samples / n_samples
|
|
dev_std_square = sum((l-mean)**2 for l in samples) / (n_samples -1)
|
|
dev_std = mt.sqrt(dev_std_square)
|
|
|
|
return dev_std
|
|
|
|
def get_uncertain_type_A(samples, dev_std):
|
|
"""
|
|
This function calculated the
|
|
uncertain type A
|
|
"""
|
|
n_samples = len(samples)
|
|
uncertain_type_A = dev_std /mt.sqrt(n_samples)
|
|
|
|
return uncertain_type_A
|
|
|
|
def get_uncertain_pattern(self):
|
|
"""
|
|
uncertain_pattern = 0,25 constante viene del equipo
|
|
"""
|
|
uncertain_pattern = 0.25
|
|
|
|
return uncertain_pattern
|
|
|
|
def get_k_certificated_calibration(self):
|
|
k_certificated_calibration = 2
|
|
|
|
return k_certicated_calibration
|
|
|
|
def get_uncertain_U_b1(self):
|
|
uncertain_b1 = MEP / mt.sqrt(3)
|
|
uncertain_b1a = uncertain_pattern / k_certificated_calibration
|
|
|
|
return uncertain_b1
|
|
|
|
def default_d_resolution(self):
|
|
return d
|
|
|
|
def get_uncertain_b2_digital(self):
|
|
uncertain_b2 = d/2*mt.sqrt(3)
|
|
|
|
return uncertain_b2
|
|
|
|
def get_uncertain_b2_analog(self):
|
|
"""
|
|
Incertidumbre por resolución Análoga
|
|
a contante que viene del equipo
|
|
"""
|
|
uncertain_b2_analog = d/a * math.sqrt(3)
|
|
|
|
return uncertain_b2_analog
|
|
|
|
def get_uncertain_combinated(self):
|
|
"""
|
|
Incertidumbre Combinada
|
|
"""
|
|
sum_uncertain_c = uncertain_type_A**2 + uncertain_b1**2 + uncertain_b2**2
|
|
uncertain_c = math.sqrt(sum_uncertain_c)
|
|
|
|
return uncertain_c
|
|
|
|
def get_uncertain_eff(self):
|
|
"""
|
|
Grados Efectivos de libertad
|
|
"""
|
|
uncertain_eff = uncertain_c**4/((uncertain_type_A**4)/(len(sample)-1)+(uncertain_b1**4/U_subi)+(uncertain_b2**4/U_subi))
|
|
|
|
return uncertain_eff
|
|
|
|
def get_create_graph(matrix, patterns):
|
|
image = BytesIO()
|
|
all_data = matrix
|
|
labels = list(patterns)
|
|
fig, ax1 = plt.subplots(nrows=1, ncols=1, figsize=(9, len(labels)+1))
|
|
# rectangular box plot
|
|
bplot1 = ax1.boxplot(all_data,
|
|
vert=True, # vertical box alignment
|
|
patch_artist=True, # fill with color
|
|
labels=labels) # will be used to label x-ticks
|
|
top = 0.3
|
|
bottom = -0.3
|
|
ax1.set_ylim(bottom, top)
|
|
ax1.set_yticks([-0.25,0.0,0.25])
|
|
|
|
ax1.set_title('Error[D]')
|
|
# adding horizontal grid lines
|
|
for ax in [ax1]:
|
|
ax.yaxis.grid(True)
|
|
#ax.set_xlabel('Three separate samples')
|
|
#ax.set_ylabel('Observed values')
|
|
|
|
plt.savefig(image, format='png')
|
|
plt.close()
|
|
|
|
return image.getvalue()
|
|
|
|
|
|
@fields.depends('service_maintenance')
|
|
def on_change_service_maintenance(self):
|
|
self.propietary = self.service_maintenance.propietary
|
|
self.propietary_address = self.service_maintenance.propietary_address
|
|
|
|
@fields.depends('equipment', 'patterns_equipments')
|
|
def on_change_equipment(self):
|
|
if self.equipment and self.equipment.product.calibration:
|
|
self.patterns_equipments = self.equipment.product.k_pattern
|
|
else:
|
|
self.patterns_equipments = None
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('in_progress')
|
|
def in_progress(cls, maintenances):
|
|
pass
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('finished')
|
|
def finished(cls, maintenances):
|
|
for maintenance in maintenances:
|
|
if maintenance.calibration_total == ():
|
|
raise UserError("No puede finalizar este mantenimiento sin una calibración")
|
|
else:
|
|
maintenance.state = 'finished'
|
|
maintenance.code = maintenance.id
|
|
maintenance.save()
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
def calibrate(cls, maintenances):
|
|
pool = Pool()
|
|
CalibrationLineTotal = pool.get('optical_equipment.maintenance.calibration')
|
|
dates = {}
|
|
dates_mistake_pattern = {}
|
|
graph_data_matrix = []
|
|
patterns = set()
|
|
|
|
for maintenance in maintenances:
|
|
maintenance.calibration_total = ()
|
|
if len(maintenance.lines_calibration) < 5:
|
|
raise UserError("Por favor Ingrese mas de (5) Muestras por patrón (Dioptría)")
|
|
else:
|
|
for line in maintenance.lines_calibration:
|
|
if line.value_patterns.pattern not in patterns:
|
|
patterns.add(line.value_patterns.pattern)
|
|
dates[line.value_patterns.pattern] = [line.value_equipment]
|
|
dates_mistake_pattern[line.value_patterns.pattern] = [line.mistake]
|
|
else:
|
|
dates[line.value_patterns.pattern].append(line.value_equipment)
|
|
dates_mistake_pattern[line.value_patterns.pattern].append(line.mistake)
|
|
|
|
|
|
for pattern in patterns:
|
|
samples = dates[pattern]
|
|
mean = sum(samples)/len(samples)
|
|
U_subi = maintenance.equipment.product.Usubi
|
|
uncertain_pattern = maintenance.equipment.product.uncertainy_pattern
|
|
MEP = maintenance.equipment.product.MEP
|
|
dev_std = cls.get_standard_deviation(samples)
|
|
uncertain_type_A = cls.get_uncertain_type_A(samples, dev_std)
|
|
k_certificated_calibration = 2
|
|
uncertain_b1 = MEP / mt.sqrt(3) #Ub1_patron a 2 Decimales
|
|
uncertain_b1a = uncertain_pattern / k_certificated_calibration #Ub1_MEP
|
|
|
|
if maintenance.equipment.product.resolution_type == "analoga":
|
|
a_resolution = maintenance.equipment.product.analog_resolution
|
|
factor_a = maintenance.equipment.product.a_factor_resolution
|
|
uncertain_b2_analog = (a_resolution) / (factor_a*mt.sqrt(3))
|
|
sum_uncertain_c = (uncertain_type_A**2) + (uncertain_b1**2) + (uncertain_b2_analog**2)
|
|
uncertain_c = mt.sqrt(sum_uncertain_c)
|
|
uncertain_eff = uncertain_c**4/((uncertain_type_A**4)/(len(samples)-1)+(uncertain_b1**4/U_subi)+(uncertain_b2_analog**4/U_subi))
|
|
elif maintenance.equipment.product.resolution_type == "digital":
|
|
d_resolution = maintenance.equipment.product.d_resolution
|
|
uncertain_b2_digital = (d_resolution) / (2*mt.sqrt(3))
|
|
sum_uncertain_c = (uncertain_type_A**2) + (uncertain_b1**2) + (uncertain_b2_digital**2)
|
|
uncertain_c = mt.sqrt(sum_uncertain_c)
|
|
uncertain_eff = uncertain_c**4/((uncertain_type_A**4)/(len(samples)-1)+(uncertain_b1**4/U_subi)+(uncertain_b2_digital**4/U_subi))
|
|
|
|
t_student = t.ppf(1-0.025, uncertain_eff)
|
|
uncertain_expanded = round((t_student * uncertain_c),2)
|
|
|
|
if maintenance.equipment.product.resolution_type == "analoga":
|
|
calibrationLineTotal = CalibrationLineTotal(
|
|
graph_dates=str(dates_mistake_pattern[pattern]),
|
|
diopter=pattern,
|
|
mean=mean,
|
|
dev_std=dev_std,
|
|
uncertain_type_A=uncertain_type_A,
|
|
uncertain_pattern=uncertain_pattern,
|
|
k_c_calibration=k_certificated_calibration,
|
|
uncertain_U_b1=uncertain_b1,
|
|
d_resolution=a_resolution,
|
|
uncertain_U_b2_dig=0,
|
|
uncertain_U_b2_ana=uncertain_b2_analog,
|
|
uncertain_combinated=uncertain_c,
|
|
uncertain_eff=uncertain_eff,
|
|
t_student=t_student,
|
|
uncertain_expanded=uncertain_expanded,
|
|
state='Aprobado' if uncertain_expanded <= a_resolution else 'Rechazado'
|
|
)
|
|
maintenance.calibration_total += (calibrationLineTotal,)
|
|
|
|
elif maintenance.equipment.product.resolution_type == "digital":
|
|
calibrationLineTotal = CalibrationLineTotal(
|
|
graph_dates=str(dates_mistake_pattern[pattern]),
|
|
diopter=pattern,
|
|
mean=mean,
|
|
dev_std=dev_std,
|
|
uncertain_type_A=uncertain_type_A,
|
|
uncertain_pattern=uncertain_pattern,
|
|
k_c_calibration=k_certificated_calibration,
|
|
uncertain_U_b1=uncertain_b1,
|
|
d_resolution=d_resolution,
|
|
uncertain_U_b2_dig=uncertain_b2_digital,
|
|
uncertain_U_b2_ana=0,
|
|
uncertain_combinated=uncertain_c,
|
|
uncertain_eff=uncertain_eff,
|
|
t_student=t_student,
|
|
uncertain_expanded=uncertain_expanded,
|
|
state='Aprobado' if uncertain_expanded <= d_resolution else 'Rechazado'
|
|
)
|
|
maintenance.calibration_total += (calibrationLineTotal,)
|
|
|
|
maintenance.save()
|
|
|
|
for i in dates_mistake_pattern.keys():
|
|
graph_data_matrix.append(dates_mistake_pattern[i])
|
|
|
|
image = cls.get_create_graph(graph_data_matrix, patterns)
|
|
maintenance.graph_calibration = image
|
|
maintenance.save()
|
|
|
|
|
|
class Calibration(ModelSQL, ModelView):
|
|
'Calibration of Maintenance'
|
|
__name__ = 'optical_equipment.maintenance.calibration'
|
|
|
|
_states={'readonly': True}
|
|
|
|
maintenance = fields.Many2One('optical_equipment.maintenance', "Maintenance", ondelete="CASCADE",
|
|
select=True, required=True)
|
|
graph_dates = fields.Char("Graph Dates", readonly=True)
|
|
diopter = fields.Float("Diopter", states=_states)
|
|
mean = fields.Float("Mean", states=_states)
|
|
dev_std = fields.Float("Standart Desviation", states=_states)
|
|
uncertain_type_A = fields.Float("Uncertain Type A", states=_states)
|
|
uncertain_pattern = fields.Float("Uncertain Pattern", states=_states)
|
|
k_c_calibration = fields.Float("K Crt Calibration",states=_states)
|
|
uncertain_U_b1 = fields.Float("U_b1", states=_states)
|
|
d_resolution = fields.Float("d_resolution", states=_states)
|
|
uncertain_U_b2_dig = fields.Float("U_b2", states=_states)
|
|
uncertain_U_b2_ana = fields.Float("U_b2", states=_states)
|
|
uncertain_combinated = fields.Float("U_combinated", states=_states)
|
|
uncertain_eff = fields.Float("U eff", states=_states)
|
|
t_student = fields.Float("T Student", states=_states)
|
|
|
|
uncertain_expanded = fields.Float("Uexpand", _digits, states=_states)
|
|
|
|
state = fields.Char('State')
|
|
|
|
class CalibrationSample(sequence_ordered(), ModelView, ModelSQL):
|
|
'Samples of Calibration'
|
|
__name__ = 'optical_equipment.maintenance.calibration_sample'
|
|
|
|
|
|
maintenance = fields.Many2One('optical_equipment.maintenance', 'Maintenance',
|
|
ondelete='CASCADE')
|
|
number_sample = fields.Float("Sample #", _digits)
|
|
value_patterns = fields.Many2One('optical_equipment.product_pattern', "Value Pattern", required=True,
|
|
ondelete='RESTRICT')
|
|
value_equipment = fields.Float("Value in Equipment", _digits, required=True,
|
|
states={'readonly': Eval('value_patterns') == None})
|
|
mistake = fields.Float("Mistake", _digits)
|
|
mistake_rate = fields.Float("% Mistake", _digits,
|
|
states={'readonly': True},
|
|
depends=['mistake'])
|
|
|
|
|
|
@fields.depends('value_patterns', 'value_equipment',
|
|
'mistake', 'mistake_rate')
|
|
def on_change_value_equipment(self):
|
|
if float(self.value_patterns.pattern) < 0:
|
|
self.mistake = self.value_patterns.pattern - self.value_equipment
|
|
else:
|
|
if self.value_patterns.pattern > self.value_equipment:
|
|
self.mistake = self.value_patterns.pattern - self.value_equipment
|
|
else:
|
|
self.mistake = -self.value_patterns.pattern + self.value_equipment
|
|
|
|
if self.value_patterns.pattern == self.value_equipment:
|
|
self.mistake_rate = 0
|
|
else:
|
|
self.mistake_rate = abs(self.mistake / self.value_patterns.pattern) * 100
|
|
|
|
|
|
class AgendedInitial(ModelView):
|
|
'Agended maintenance service'
|
|
__name__ = 'optical_equipment_maintenance.agended'
|
|
|
|
maintenance_service = fields.Many2One('optical_equipment_maintenance.service',"Maintenaince Service",
|
|
required=True, domain=[('state', '=', 'draft')])
|
|
estimated_agended = fields.DateTime("Date Maintenance", required=True)
|
|
technical = fields.Many2One('company.employee', "Technical", required=True)
|
|
|
|
|
|
class AssingAgended(Wizard):
|
|
'Assing Agended'
|
|
__name__ = 'optical_equipment_maintenance.assing_agended'
|
|
|
|
start = StateView('optical_equipment_maintenance.agended',
|
|
'optical_equipment.assing_agended_view_form', [
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
Button('Assing', 'assing_agended', 'tryton-ok', default=True),
|
|
])
|
|
|
|
assing_agended = StateAction('optical_equipment.act_maintenance_service_form')
|
|
|
|
|
|
def do_assing_agended(self, action):
|
|
pool = Pool()
|
|
Diary = pool.get('optical_equipment_maintenance.diary')
|
|
Config = pool.get('optical_equipment.configuration')
|
|
config = Config(3)
|
|
|
|
MaintenanceService = pool.get('optical_equipment_maintenance.service')
|
|
diary = Diary(code=config.agended_sequence.get(),
|
|
maintenance_service=self.start.maintenance_service,
|
|
date_expected=self.start.estimated_agended,
|
|
date_estimated=self.start.estimated_agended + timedelta(days=15),
|
|
date_end=self.start.estimated_agended + timedelta(days=15),
|
|
technical=self.start.technical.id,
|
|
state='agended')
|
|
diary.save()
|
|
|
|
maintenanceService = self.start.maintenance_service
|
|
maintenanceService.estimated_agended = self.start.estimated_agended
|
|
maintenanceService.technical = self.start.technical
|
|
maintenanceService.state_agended = 'agended'
|
|
maintenanceService.state = 'agended'
|
|
maintenanceService.history_agended += (diary.id,)
|
|
maintenanceService.set_code(maintenanceService)
|
|
maintenanceService.save()
|
|
|
|
|
|
class ReAgended(ModelView):
|
|
'Agended maintenance service'
|
|
__name__ = 'optical_equipment_maintenance.reagended'
|
|
|
|
maintenance_service = fields.Many2One('optical_equipment_maintenance.service',"Maintenaince Service",
|
|
required=True, domain=[('state', '=', 'failed')])
|
|
estimated_agended = fields.DateTime("Date Maintenance", required=True)
|
|
technical = fields.Many2One('company.employee', "Technical", required=True)
|
|
|
|
|
|
class ReAssingAgended(Wizard):
|
|
'Assing Agended'
|
|
__name__ = 'optical_equipment_maintenance.reassing_agended'
|
|
|
|
start = StateView('optical_equipment_maintenance.reagended',
|
|
'optical_equipment.reassing_agended_view_form', [
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
Button('Assing', 'assing_agended', 'tryton-ok', default=True),
|
|
])
|
|
|
|
assing_agended = StateAction('optical_equipment.act_maintenance_service_form')
|
|
|
|
def do_assing_agended(self, action):
|
|
pool = Pool()
|
|
Diary = pool.get('optical_equipment_maintenance.diary')
|
|
|
|
diary = Diary(maintenance_service=self.start.maintenance_service,
|
|
date_expected=self.start.estimated_agended,
|
|
date_estimated=self.start.estimated_agended + timedelta(days=15),
|
|
date_end=self.start.estimated_agended + timedelta(days=15),
|
|
technical=self.start.technical.id,
|
|
state='agended')
|
|
diary.save()
|
|
|
|
maintenanceService = self.start.maintenance_service
|
|
maintenanceService.estimated_agended = self.start.estimated_agended
|
|
maintenanceService.technical = self.start.technical
|
|
maintenanceService.state_agended = 'agended'
|
|
maintenanceService.state = 'agended'
|
|
maintenanceService.history_agended += (diary.id,)
|
|
maintenanceService.save()
|
|
|
|
|
|
class ServiceMaintenanceAgended(ModelSQL):
|
|
'Service Maintenance - Agended'
|
|
__name__ = 'optical_equipment_maintenance.service-maintenance.diary'
|
|
|
|
|
|
maintenance_service = fields.Many2One('optical_equipment_maintenance.service', "Maintenance Service")
|
|
agended = fields.Many2One('optical_equipment_maintenance.diary', "Agended")
|
|
|
|
|
|
class MaintenanceLine(ModelSQL, ModelView):
|
|
'Maintenance Line'
|
|
__name__ = 'optical_equipment.maintenance.line'
|
|
|
|
line_replace = fields.Boolean("Replace", states={'readonly': If(Eval('line_maintenance_activity') == True, True)})
|
|
line_maintenance_activity = fields.Boolean("Maintenance Activity", states={'readonly': If(Eval('line_replace') == True, True)})
|
|
maintenance = fields.Many2One('optical_equipment.maintenance', 'Maintenance', ondelete='CASCADE', select=True)
|
|
replacement = fields.Many2One('product.product', 'Replacement', ondelete='RESTRICT',
|
|
domain=[('replacement', '=', True)],
|
|
states={'invisible': (If(Eval('line_maintenance_activity') == True, True)) | (If(Eval('line_replace') == False, True)),
|
|
'required': If(Eval('line_replace') == True, True)},
|
|
depends=['line_replace'])
|
|
maintenance_activity = fields.Many2One('product.product', 'Maintenance activity',
|
|
domain=[('maintenance_activity', '=', True)],
|
|
states={'invisible': If(Eval('line_replace') == True, True) |
|
|
(If(Eval('line_maintenance_activity') == False, True)),
|
|
'required': If(Eval('line_maintenance_actitvity') == True, True)},
|
|
depends=['line_maintenance_activity'])
|
|
quantity = fields.Float("Quantity", required=True, digits='unit')
|
|
actual_quantity = fields.Float(
|
|
"Actual Quantity", digits='unit', readonly=True,
|
|
states={
|
|
'invisible': Eval('type') != 'line',
|
|
})
|
|
unit = fields.Many2One('product.uom', 'Unit', ondelete='RESTRICT',
|
|
states={
|
|
'readonly': Eval('_parent_maintenance.state') != 'draft',
|
|
},domain=[If(Bool(Eval('product_uom_category')),
|
|
('category', '=', Eval('product_uom_category')),
|
|
('category', '!=', -1)),
|
|
])
|
|
product_uom_category = fields.Function(fields.Many2One('product.uom.category', 'Product Uom Category'),
|
|
'on_change_with_product_uom_category')
|
|
company = fields.Function(fields.Many2One('company.company', "Company"),'on_change_with_company')
|
|
|
|
@fields.depends('maintenance', '_parent_maintenance.company')
|
|
def on_change_with_company(self, name=None):
|
|
if self.maintenance and self.maintenance.company:
|
|
return self.maintenance.company.id
|
|
|
|
@fields.depends('line_replace', 'replacement')
|
|
def on_change_line_replace(self, name=None):
|
|
if self.line_replace == False:
|
|
self.replacement = None
|
|
|
|
@fields.depends('line_maintenance_activity', 'maintenance_activity')
|
|
def on_change_line_maintenance_activity(self, name=None):
|
|
if self.line_maintenance_activity == False:
|
|
self.maintenance_activity = None
|
|
|
|
@fields.depends('replacement', 'maintenance', 'unit', 'maintenance')
|
|
def on_change_replacement(self):
|
|
if not self.replacement:
|
|
self.unit = None
|
|
return
|
|
|
|
if not self.unit or self.unit.category != category:
|
|
self.unit = self.replacement.sale_uom
|
|
|
|
@fields.depends('maintenance_activity',
|
|
'quantity', 'unit')
|
|
def on_change_maintenance_activity(self):
|
|
if not self.maintenance_activity:
|
|
self.quantity = None
|
|
self.unit = None
|
|
return
|
|
|
|
self.quantity = 1
|
|
if not self.unit or self.unit.category != category:
|
|
self.unit = self.maintenance_activity.sale_uom
|
|
|
|
|
|
class MaintenanceActivity(ModelView, ModelSQL):
|
|
'Maintenance Activitys'
|
|
__name__ = 'optical_equipment_maintenance.activity'
|
|
|
|
maintenance = fields.Many2One('optical_equipment.maintenance')
|
|
product = fields.Many2One('product.product', 'Product',
|
|
domain=[('maintenance_activity', '=', True)])
|
|
|
|
|
|
class CreateContractInitial(ModelView, ModelSQL):
|
|
'Create Contract Inicial'
|
|
__name__ = 'optical_equipment_create.contract'
|
|
|
|
company = fields.Many2One(
|
|
'company.company', "Company", readonly=True, required=True, select=True,
|
|
states={
|
|
'readonly': (Eval('state') != 'draft') | Eval('party', True),
|
|
},help="Make the subscription belong to the company.")
|
|
party = fields.Many2One(
|
|
'party.party', "Party", required=True,
|
|
help="The party who subscribes.")
|
|
invoice_address = fields.Many2One('party.address', 'Invoice Address',
|
|
required=True, domain=[('party', '=', Eval('party'))])
|
|
payment_term = fields.Many2One('account.invoice.payment_term',
|
|
'Payment Term')
|
|
contact = fields.Many2One(
|
|
'party.contact_mechanism', "Contact", required=True,
|
|
domain=[('party', '=', Eval('party'))],
|
|
context={
|
|
'company': Eval('company', -1),
|
|
})
|
|
start_date = fields.Date("Start Date", required=True)
|
|
end_date = fields.Date("End Date",
|
|
domain=['OR',
|
|
('end_date', '>=', If(
|
|
Bool(Eval('start_date')),
|
|
Eval('start_date', datetime.date.min),
|
|
datetime.date.min)),
|
|
('end_date', '=', None),
|
|
])
|
|
|
|
@staticmethod
|
|
def default_company():
|
|
return Transaction().context.get('company')
|
|
|
|
@classmethod
|
|
def default_start_date(cls):
|
|
pool = Pool()
|
|
Date = pool.get('ir.date')
|
|
return Date.today()
|
|
|
|
|
|
@fields.depends('party')
|
|
def on_change_party(self):
|
|
pool = Pool()
|
|
Date = pool.get('ir.date')
|
|
if self.party:
|
|
self.invoice_address = self.party.address_get(type='invoice')
|
|
if self.party.client_type == "ips":
|
|
self.end_date = Date.today() + timedelta(days=365)
|
|
else:
|
|
self.end_date = Date.today() + timedelta(days=182)
|
|
|
|
|
|
class CreateContract(Wizard):
|
|
__name__ = 'optical_equipment.maintenance.contract'
|
|
|
|
start = StateView('optical_equipment_create.contract',
|
|
'optical_equipment.create_contract_view_form',[
|
|
Button('Cancel', 'end', 'tryton-cancel'),
|
|
Button('Create', 'create_contract', 'tryton-ok', default=True),
|
|
])
|
|
create_contract = StateAction('optical_equipment.act_contract_form')
|
|
|
|
|
|
@property
|
|
def _subscription_start(self):
|
|
return dict(
|
|
party=self.start.party,
|
|
contact=self.start.contact,
|
|
start_date=self.start.start_date,
|
|
end_date=self.start.end_date,
|
|
invoice_address=self.start.invoice_address
|
|
)
|
|
|
|
def do_create_contract(self, action):
|
|
maintenance_service = self.records[0]
|
|
pool = Pool()
|
|
Contract = pool.get('optical_equipment.contract')
|
|
|
|
dates = self._subscription_start
|
|
|
|
prorogues = (maintenance_service,)
|
|
equipments = []
|
|
for line in maintenance_service.lines:
|
|
equipments.append(line.equipment.id)
|
|
|
|
if maintenance_service.contract_origin:
|
|
contract=maintenance_service.contract_origin
|
|
contract.invoice_address=dates['invoice_address']
|
|
contract.contact=dates['contact']
|
|
contract.start_date=dates['start_date']
|
|
contract.end_date=dates['end_date']
|
|
contract.maintenance_services+=prorogues
|
|
contract.equipments=equipments
|
|
contract.state='draft'
|
|
contract.price_contract=maintenance_service.sale_origin.sale.total_amount
|
|
contract.save()
|
|
else:
|
|
contract = Contract(party=dates['party'],
|
|
invoice_address=dates['invoice_address'],
|
|
contact=dates['contact'],
|
|
start_date=dates['start_date'],
|
|
end_date=dates['end_date'],
|
|
maintenance_services=prorogues,
|
|
equipments=equipments,
|
|
state='draft',
|
|
price_contract=maintenance_service.sale_origin.sale.total_amount
|
|
)
|
|
contract.save()
|