# 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, fields, ) from trytond.wizard import Button, StateAction, StateView, Wizard from trytond.modules.company import CompanyReport from trytond.transaction import Transaction from trytond.pyson import Bool, Eval, If, Id from trytond.pool import Pool from trytond.model.exceptions import ValidationError from datetime import timedelta from scipy.stats import t import matplotlib.pyplot as plt import math as mt from io import BytesIO from trytond.exceptions import UserError from trytond.i18n import gettext _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': (Eval('state') != 'draft')} code = fields.Char( 'Code', readonly=True, ) reference = fields.Char( 'Reference', help='The identification of an external origin.' ) description = fields.Char('Description', states=_states) sale_date = fields.Char('Sale Date') company = fields.Many2One('company.company', 'Company', readonly=True) maintenance_type = fields.Selection( [ ('initial', 'Initial'), ('preventive', 'Preventive'), ('corrective', 'Corrective'), ], 'Maintenance Type', states=_states, ) propietary = fields.Many2One( 'party.party', 'Propietary', required=True, states=_states ) contract_origin = fields.Many2One('optical_equipment.contract', "Contract") # contract_origin = fields.Reference( # 'Contract Base', # selection='get_origin_contract') sale_origin = fields.Reference( 'Sale Origin', selection='get_origin', states={'readonly': True}) 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' ) estimated_agended = fields.DateTime('Date Maintenance', readonly=True) current_agended = fields.Many2One( 'optical_equipment_maintenance.diary', 'Current Agended', 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', readonly=True, ) technical = fields.Many2One('company.employee', 'Technical', readonly=True) 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') 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')) ], ) 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')) ], ) technician_responsible = fields.Char('Technician Responsible') invima = fields.Char('Invima') technician_signature = fields.Binary('Technician Signature') @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._order = [('code', 'DESC'), ('id', 'DESC')] cls._transitions = { ('draft', 'agended'), ('agended', 'in_progress'), ('in_progress', 'finished'), } cls._buttons.update( { 'reassing_agended': { 'invisible': Eval('state') != 'failed' }, 'assing_agended': { 'invisible': Eval('state') != 'draft' }, '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') @staticmethod def default_temperature_min(): pool = Pool() Config = pool.get('optical_equipment.configuration') config = Config(1) temperature_min = config.temperature_min return temperature_min @staticmethod def default_temperature_max(): pool = Pool() Config = pool.get('optical_equipment.configuration') config = Config(1) temperature_max = config.temperature_max return temperature_max @staticmethod def default_moisture_min(): pool = Pool() Config = pool.get('optical_equipment.configuration') config = Config(1) moisture_min = config.moisture_min return moisture_min @staticmethod def default_temperature_uom(): pool = Pool() Config = pool.get('optical_equipment.configuration') config = Config(1) if config.temperature_uom: temperature_uom = config.temperature_uom.id return temperature_uom @staticmethod def default_moisture_uom(): pool = Pool() Config = pool.get('optical_equipment.configuration') config = Config(1) if config.moisture_uom: moisture_uom = config.moisture_uom.id return moisture_uom @staticmethod def default_moisture_max(): pool = Pool() Config = pool.get('optical_equipment.configuration') config = Config(1) moisture_max = config.moisture_max return moisture_max @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 default_technician_responsible(cls): pool = Pool() ConfigurationEquipment = pool.get('optical_equipment.configuration') config = ConfigurationEquipment(1) if config.technician_responsible: technician_responsible = config.technician_responsible return technician_responsible.party.name @classmethod def default_invima(cls): pool = Pool() ConfigurationEquipment = pool.get('optical_equipment.configuration') config = ConfigurationEquipment(1) if config.technician_responsible: return config.technician_responsible.invima @classmethod def default_technician_signature(cls): pool = Pool() ConfigurationEquipment = pool.get('optical_equipment.configuration') config = ConfigurationEquipment(1) if config.technician_signature: return config.technician_signature @classmethod def _get_origin(cls): 'Return list of Model names for origin Reference' pool = Pool() Sale = pool.get('sale.sale') SaleLine = pool.get('sale.line') return [Sale.__name__, SaleLine.__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 is not 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_action('optical_equipment.act_assing_agended') def assing_agended(cls, maintenances): pass @classmethod @ModelView.button_action('optical_equipment.act_reassing_agended') def reassing_agended(cls, maintenances): pass @classmethod @ModelView.button @Workflow.transition('in_progress') def in_progress(cls, maintenances): pass @classmethod @ModelView.button @Workflow.transition('finished') def finished(cls, maintenances): message = 'optical_equipment.msg_finished_mantenance_service' for maintenance in maintenances: for line in maintenance.lines: if line.state != 'finished': raise ValidationError(gettext(message)) class MaintenanceServiceLine(Workflow, ModelSQL, ModelView): 'Equipment Maintenance Line' __name__ = 'optical_equipment.maintenance' # _rec_name = 'rec_name' _states = {'required': True, 'readonly': Eval('state').in_(['finished'])} service_maintenance = fields.Many2One( 'optical_equipment_maintenance.service', 'Maintenance Service', ondelete='CASCADE', domain=[ ('state', 'in', ['draft', 'in_progress', 'finished']), ('propietary', '=', Eval('propietary')), ], states=_states, ) code = fields.Char('Code', states={'readonly': True}) maintenance_type = fields.Selection( [ ('initial', 'Initial'), ('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, ) propietary_address = fields.Many2One( 'party.address', 'Propietary Address', states=_states, domain=[('party', '=', Eval('propietary'))], ) equipment = fields.Many2One( 'optical_equipment.equipment', 'Equipment', domain=[ ('state', 'in', ['registred', 'uncontrated', 'contrated']), ('propietary', '=', Eval('propietary')), ('propietary_address', '=', Eval('propietary_address')), ], states=_states, ) equipment_calibrate = fields.Boolean( 'Calibrate Equipment', states={'readonly': True} ) # Preventive maintenance initial_operation = fields.Boolean( 'Verificació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') 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}, ) 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' ) 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')) ], ) 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')) ], ) graph_calibration = fields.Binary('Graphs') rec_name = fields.Function(fields.Char('rec_name'), 'get_rec_name') technician_responsible = fields.Char('Technician Responsible') invima = fields.Char('Invima') technician_signature = fields.Binary('Technician Signature') @classmethod def __setup__(cls): super(MaintenanceServiceLine, cls).__setup__() cls._transitions.update({('draft', 'finished')}) cls._buttons.update({ 'in_progress': { 'invisible': Eval('state').in_(['draft', 'in_progress', 'finished']) }, 'samples': { 'invisible': ( (Eval('state').in_(['finished'])) | ( Eval('lines_calibration', [0])) | ( ~Eval('equipment_calibrate'))) }, 'calibrate': { 'invisible': (Eval('lines_calibration', [0])) | ( Eval('state').in_(['finished'])), 'depends': ['state'], }, 'finished': { 'invisible': (Eval('state').in_(['finished']) | ( Eval('maintenance_type') == 'corrective') & ( Eval('maintenance_lines', [0])))}, }) @classmethod def default_technician_responsible(cls): pool = Pool() ConfigurationEquipment = pool.get('optical_equipment.configuration') config = ConfigurationEquipment(1) if config.technician_responsible: technician_responsible = config.technician_responsible return technician_responsible.party.name @classmethod def default_invima(cls): pool = Pool() ConfigurationEquipment = pool.get('optical_equipment.configuration') config = ConfigurationEquipment(1) if config.technician_responsible: return config.technician_responsible.invima @classmethod def default_technician_signature(cls): pool = Pool() ConfigurationEquipment = pool.get('optical_equipment.configuration') config = ConfigurationEquipment(1) if config.technician_signature: return config.technician_signature @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 view_attributes(cls): return super(MaintenanceServiceLine, cls).view_attributes() + [ ( "//page[@id='preventive']", 'states', { 'invisible': If(Eval('maintenance_type') == 'corrective', True), }, ), ( "//page[@id='corrective']", 'states', { 'invisible': If(Eval('maintenance_type') != 'corrective', True), }, ), ( "//page[@id='calibration']", 'states', { 'invisible': ~Eval('equipment_calibrate'), }, ), ( "//page[@id='graph']", 'states', { 'invisible': ~Eval('equipment_calibrate'), }, ), ] @fields.depends('temperature_min', 'temperature_uom') def on_change_temperature_min(self): if self.temperature_min: pool = Pool() Measurements = pool.get('product.uom') self.temperature_uom = Measurements.search( ['name', '=', 'Celsius'])[0].id @fields.depends('moisture_min', 'moisture_uom') def on_change_moisture_min(self): pool = Pool() Measurements = pool.get('product.uom') self.moisture_uom = Measurements.search( ['name', '=', 'Relative Humedity'] )[0].id @fields.depends('_parent_service_maintenance.propietary', '_parent_service_maintenance.propietary_address', '_parent_service_maintenance.temperature_min', '_parent_service_maintenance.temperature_max', '_parent_service_maintenance.temperature_uom', '_parent_service_maintenance.moisture_min', '_parent_service_maintenance.moisture_max', '_parent_service_maintenance.moisture_uom', 'service_maintenance') def on_change_service_maintenance(self): if self.service_maintenance: self.propietary = self.service_maintenance.propietary self.propietary_address =\ self.service_maintenance.propietary_address service = self.service_maintenance self.temperature_min = service.temperature_min self.temperature_max = service.temperature_max self.temperature_uom = service.temperature_uom self.moisture_min = service.moisture_min self.moisture_max = service.moisture_max self.moisture_uom = service.moisture_uom else: self.propietary = None self.propietary_address = None self.temperature_min = None self.temperature_max = None self.temperature_uom = None self.moisture_min = None self.moisture_max = None self.moisture_uom = None @fields.depends('equipment', 'patterns_equipments') def on_change_equipment(self): if self.equipment: product = self.equipment.product self.patterns_equipments = product.k_pattern self.equipment_calibrate = product.calibration self.initial_operation = product.initial_operation self.check_equipment = product.check_equipment self.check_electric_system = product.check_electric_system self.clean_int_ext = product.clean_int_ext self.clean_eyes = product.clean_eyes self.check_calibration = product.check_calibration else: self.patterns_equipments = None self.equipment_calibrate = False self.initial_operation = False self.check_equipment = False self.check_electric_system = False self.clean_int_ext = False self.clean_eyes = False self.check_calibration = False def get_next_maintenance(self, action): next_maintenance = None if self.service_maintenance.estimated_agended: if self.propietary.customer_type == 'ips': next_maintenance = ( self.service_maintenance.estimated_agended + timedelta(days=182) ) else: next_maintenance = ( self.service_maintenance.estimated_agended + timedelta(days=365) ) 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_create_graph(matrix, patterns, resolution, equipment_risk): image = BytesIO() errors = [] yerr = [] upresolution = resolution if resolution >= 0 else (resolution * -1) lowresolution = resolution if resolution < 0 else (resolution * -1) count = 0 for pattern in patterns: error = pattern - matrix[count][0] yerr.append(matrix[count][1]) errors.append(error) count += 1 labels = list(patterns) x = labels y = errors if equipment_risk == 'IIB': if sum(errors) == 0: top = 1.5 bottom = -1.5 else: top = 2 bottom = -2 else: top = 0.60 bottom = -0.60 ls = 'dotted' fig, ax1 = plt.subplots(nrows=1, ncols=1) # Límites del Eje Y ax1.set_ylim(bottom, top) # Límites del Eje X ax1.set_xlim((min(labels) - 1, max(labels) + 1)) ax1.yaxis.grid(True) ax1.xaxis.grid(True) ax1.set_title('Error[D]') ax1.set_xlabel('Patrones') ax1.set_ylabel('Valores Observados') ax1.set_yticks([lowresolution, 0.0, upresolution]) # ax1.set_xticks([-10.0,-5.0,0.0,5.0,10.0]) ax1.errorbar(x, y, yerr=yerr, marker='D', markersize=10, linestyle=ls) plt.savefig(image, format='png') plt.close() return image.getvalue() @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.equipment.product.calibration and 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 samples(cls, maintenances): pool = Pool() CalibrationSample = pool.get( 'optical_equipment.maintenance.calibration_sample') for maintenance in maintenances: patterns = maintenance.equipment.product.k_pattern_list for pattern in patterns: samples = [] calibrationSample = CalibrationSample( maintenance=maintenance.id, product=maintenance.equipment.product.template.id, value_patterns=pattern.id, value_equipment=pattern.pattern, mistake=0, mistake_rate=0, ) samples = [calibrationSample] * 5 maintenance.lines_calibration += tuple(samples) maintenance.save() @classmethod @ModelView.button def calibrate(cls, maintenances): pool = Pool() CalibrationLineTotal = pool.get( 'optical_equipment.maintenance.calibration') dates = {} dates_mistake_pattern = [] 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)' ) 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] else: dates[line.value_patterns.pattern].append( line.value_equipment) for pattern in patterns: product = maintenance.equipment.product samples = dates[pattern] mean = sum(samples) / len(samples) U_subi = product.Usubi uncertain_pattern = product.uncertainy_pattern MEP = 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 if product.resolution_type == 'analoga': a_resolution = product.analog_resolution resolution = a_resolution factor_a = 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 product.resolution_type == 'digital': d_resolution = product.d_resolution resolution = 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) dates_mistake_pattern.append([mean, uncertain_expanded]) if product.resolution_type == 'analoga': calibrationLineTotal = CalibrationLineTotal( 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 product.resolution_type == 'digital': calibrationLineTotal = CalibrationLineTotal( 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() image = cls.get_create_graph( dates_mistake_pattern, patterns, resolution, product.risk ) maintenance.graph_calibration = image maintenance.save() class MaintenanceLine(ModelSQL, ModelView): 'Maintenance Line' __name__ = 'optical_equipment.maintenance.line' line_replace = fields.Boolean( 'Replace', ) line_maintenance_activity = fields.Boolean( 'Maintenance Activity', ) maintenance = fields.Many2One( 'optical_equipment.maintenance', 'Maintenance', ondelete='CASCADE', ) replacement = fields.Many2One( 'product.product', 'Replacement', ondelete='RESTRICT', domain=[('replacement', '=', True)], depends={'line_replace'}, ) maintenance_activity = fields.Many2One( 'product.product', 'Maintenance activity', domain=[('maintenance_activity', '=', 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', ) description = fields.Text( 'Description', states={ 'readonly': Eval('_parent_maintenance.state') != 'draft', }, ) company = fields.Function( fields.Many2One('company.company', 'Company'), 'on_change_with_company' ) @fields.depends('replacement', 'maintenance_activity') def on_change_with_product_uom_category(self, name=None): if self.replacement: return self.replacement.defaul_uom_category.id if self.maintenance_activity: return self.maintenance_activity.default_uom_category.id @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 not self.line_replace: self.replacement = None @fields.depends('line_maintenance_activity', 'maintenance_activity') def on_change_line_maintenance_activity(self, name=None): if not self.line_maintenance_activity: self.maintenance_activity = None @fields.depends( 'replacement', 'unit') def on_change_replacement(self): if not self.replacement: self.unit = None return if not self.unit: 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: self.unit = self.maintenance_activity.sale_uom class MaintenanceActivity(ModelView, ModelSQL): 'Maintenance Activitys' __name__ = 'optical_equipment_maintenance.activity' maintenance = fields.Many2One( 'optical_equipment.maintenance', 'Maintenance') product = fields.Many2One( 'product.product', 'Product', domain=[ ('maintenance_activity', '=', True)] ) class ChangePropietaryMaintenance(ModelView): 'Change of Propietary Equipment' __name__ = 'optical_equipment.change_propietary_maintenance.form' old_propietary = fields.Many2One( 'party.party', 'Old Propietary', states={'required': True} ) maintenance_service = fields.Many2Many( 'optical_equipment_maintenance.service', None, None, 'Maintenance Service', domain=[('propietary', '=', Eval('old_propietary'))], depends=['old_propietary'], ) new_propietary = fields.Many2One( 'party.party', 'New Propietary', states={'required': True} ) new_address = fields.Many2One( 'party.address', 'New Address', required=True, domain=[('party', '=', Eval('new_propietary'))], states={'required': True}, ) change_date = fields.Date('Change Date', readonly=True) @classmethod def default_change_date(cls): pool = Pool() Date = pool.get('ir.date') return Date.today() class NewPropietaryMaintenance(Wizard): 'Change Propietary' __name__ = 'optical_equipment.change_propietary_maintenance' start = StateView( 'optical_equipment.change_propietary_maintenance.form', 'optical_equipment.change_propietary_maintenance_view_form', [ Button('Cancel', 'end', 'tryton-cancel'), Button('Create', 'change_propietary', 'tryton-ok', default=True), ], ) change_propietary = StateAction( 'optical_equipment.act_optical_equipment_form') def do_change_propietary(self, action): services = self.start.maintenance_service new_propietary = self.start.new_propietary new_address = self.start.new_address for service in services: service.propietary = new_propietary service.propietary_address = new_address service.save() for maintenance in service.lines: maintenance.propietary = new_propietary maintenance.propietary_address = new_address maintenance.save() class MaintenanceServiceReport(CompanyReport): __name__ = 'optical_equipment_maintenance.service' @classmethod def execute(cls, ids, data): with Transaction().set_context(address_with_party=True): return super(MaintenanceServiceReport, cls).execute(ids, data) @classmethod def get_context(cls, records, header, data): pool = Pool() Date = pool.get('ir.date') context = super().get_context(records, header, data) context['today'] = Date.today() return context