# 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 import math as mt import numpy as np from trytond.exceptions import UserError class MaintenanceService(Workflow, ModelSQL, ModelView): 'Equipment Maintenance Service' __name__ = 'optical_equipment_maintenance.service' _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) @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() Sale = pool.get('optical_equipment.contract') return [Sale.__name__] @classmethod def get_origin_contract(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 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' service_maintenance = fields.Many2One('optical_equipment_maintenance.service', "Maintenance Service", ondelete='CASCADE', select=True) code = fields.Char( "Code", select=True,states={'readonly': True }) maintenance_type = fields.Selection([('preventive', 'Preventive'), ('corrective', 'Corrective') ], "Maintenance Type") state = fields.Selection([('draft', "Draft"), ('finished', "Finished") ], "State",required=True, readonly=True, sort=False) company = fields.Many2One('company.company', "Company", readonly=True) propietary = fields.Many2One('party.party', "Propietary", depends=['service_maintenance']) propietary_address = fields.Many2One('party.address', "Propietary Address", domain=[('party', '=', Eval('propietary'))], depends=['service_maintenance'] ) equipment = fields.Many2One('optical_equipment.equipment', "Equipment", required=True, domain=[('propietary', '=', Eval('propietary'))], depends=['service_maintenance']) #when the maintenance is in agended status diary = fields.One2Many('optical_equipment_maintenance.diary', 'diary') #estimated_agended = fields.DateTime("Date Maintenance") #state_agended = fields.Selection([('no_agenda', "No agenda"), # ('agended', "Agended"), # ('in_progress', "In progress"), # ('finish', "Finish"), # ('failed', "Failed")], "State Agenda") #technical = fields.Many2One('company.employee', "Technical") #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") maintenance_lines = fields.One2Many('optical_equipment.maintenance.line', 'maintenance', 'Lines') """ temperature_min = fields.Float("Temp Min") temperature_max = fields.Float("Temp Max") temperature_uom = fields.Many2One('product.uom', 'Temperature UOM', domain=[('category', '=', Id('optical_equipment', "uom_cat_temperature"))], states={'invisible' : If(Eval('temperature_min') == None, True)}, depends=['itemperature_min']) moisture_min = fields.Float("Moisture Min") moisture_max = fields.Float("Moisture Max") moisture_uom = fields.Many2One('product.uom', "Moisture UOM", domain=[('category', '=', Id('optical_equipment', 'uom_cat_relative_humedity'))], states={'invisible' : If(Eval('moisture_min') == None, True)}, depends=['moisture_min']) """ @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'])}, }) @staticmethod def default_company(): return Transaction().context.get('company') @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 def default_initial_operation(cls): return True @classmethod def default_check_equipment(cls): return True @classmethod def default_check_electric_system(cls): return True @classmethod def default_clean_int_ext(cls): return True @classmethod def default_clean_eyes(cls): return True @classmethod def default_optical(cls): return True @classmethod def default_check_calibration(cls): return True @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 @ModelView.button @Workflow.transition('in_progress') def in_progress(cls, maintenances): pass @classmethod @ModelView.button @Workflow.transition('finished') def finished(cls, maintenances): raise UserError(str("Esto es una prueba")) pass @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), }) ] 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 _create_contract_base(self, dates, subscription): pool = Pool() ContractBase = pool.get('optical_equipment.contract') a = self._subscription_start contractBase = ContractBase( state='draft', party=a['party'], invoice_address=a['invoice_address'], start_date=a['start_date'], end_date=a['end_date'], contact=a['contact'], equipments=a['equipments'] ) contractBase.save() 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,) 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 ) contract.save() 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 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' product = fields.Many2One('product.product', 'Product', ondelete='RESTRICT',domain=[ If(Eval('sale_state').in_(['draft']), ('maintenance_activity', '=', True), ()), ],) maintenance = fields.Many2One('optical_equipment.maintenance', 'Maintenance', ondelete='CASCADE', select=True) maintenance_activity = fields.Many2One('product.product', 'Maintenance activity') class Calibration(ModelSQL, ModelView): 'Calibration of Maintenance' __name__ = 'optical_equipment.maintenance.calibration' maintenance = fields.Many2One('optical_equipment.maintenance', "Maintenance", ondelete="CASCADE", select=True, required=True) samples = fields.One2Many('optical_equipment.maintenance.calibration_sample', 'maintenance', 'Samples') dev_std = fields.Function( fields.Float("Standart Desviation"),'get_standard_deviation' ) uncertain_type_A = fields.Function( fields.Float("Uncertain Type A"), 'get_uncertain_A' ) uncertain_pattern = fields.Function( fields.Float("Uncertain Pattern"), 'get_uncertain_pattern' ) k_c_calibration = fields.Function( fields.Float("K Crt Calibration"), 'get_k_certificated_calibration' ) uncertain_U_b1 = fields.Function( fields.Float("U_b1"), 'get_uncertain_U_b1' ) d_resolution = fields.Float("d_resolution") uncertain_U_b2_dig = fields.Function( fields.Float("U_b2"), 'get_uncertain_b2_digital' ) uncertain_U_b2_ana = fields.Function( fields.Float("U_b2"), 'get_uncertain_b2_analoga' ) uncertain_combinated = fields.Function( fields.Float("U_combinated"), 'get_uncertain_combinated' ) uncertain_eff = fields.Function( fields.Float("U eff"), 'get_uncertain_eff' ) average = fields.Float("Average") #total_samples total de muestras #average_pattern_equipment #Promedio de las muestras tomadas en el equipo suma(value_equipment)/total_samples #Desviacion estandar muestral != desviación estandar poblacional def get_standard_deviation(self): """ 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 sample) / (n_samples -1) dev_std = mt.sqrt(dev_std_square) return dev_std def get_uncertain_type_A(self): """ 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 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 #") value_patterns = fields.Many2One('optical_equipment.product_pattern', "Value Pattern", required=True, ondelete='RESTRICT') #value_pattern = fields.Float("Value in Pattern") value_equipment = fields.Float("Value in Equipment", required=True, states={'readonly': Eval('value_patterns') == None}) mistake = fields.Float("Mistake") mistake_rate = fields.Float("% Mistake", 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 self.mistake_rate = abs(self.mistake / self.value_patterns.pattern) * 100