add module equipments

This commit is contained in:
sinergia 2023-04-03 01:59:15 -05:00
parent 95e6ed60f3
commit 63f4f24f53
43 changed files with 3502 additions and 11 deletions

View File

@ -1,16 +1,30 @@
# 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.pool import Pool
from . import (party, product, purchase,
configuration, maintenance)
from . import (agended, calibration, configuration, contract, diary,
equipment, party, product, maintenance, purchase, sale)
__all__ = ['register']
def register():
Pool.register(
equipment.OpticalEquipment,
equipment.EquipmentMaintenance,
equipment.EquipmentContract,
equipment.EquipmentParty,
equipment.ChangePropietary,
equipment.ChangeEquipment,
agended.AgendedInitial,
agended.ReAgended,
agended.ServiceMaintenanceAgended,
calibration.Calibration,
calibration.CalibrationSample,
configuration.Configuration,
diary.Diary,
contract.Contract,
contract.ContractMaintenanceServices,
contract.ContractEquipment,
party.Address,
party.Party,
product.Template,
@ -20,10 +34,23 @@ def register():
product.Image,
purchase.Purchase,
purchase.Line,
sale.Sale,
sale.SaleLine,
maintenance.MaintenanceService,
maintenance.MaintenanceServiceLine,
maintenance.MaintenanceLine,
maintenance.MaintenanceActivity,
maintenance.ChangePropietaryMaintenance,
module='optical_equipment', type_='model')
Pool.register(
agended.AssingAgended,
agended.ReAssingAgended,
equipment.NewPropietary,
maintenance.NewPropietaryMaintenance,
module='optical_equipment', type_='wizard')
Pool.register(
calibration.CalibrationReport,
contract.ContractReport,
equipment.EquipmentReport,
maintenance.MaintenanceServiceReport,
module='optical_equipment', type_='report')

106
agended.py Normal file
View File

@ -0,0 +1,106 @@
# 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 ModelSQL, ModelView, fields
from trytond.wizard import (
Button, StateAction, StateTransition, StateView, Wizard)
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.current_agended = diary.id
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")

33
agended.xml Normal file
View File

@ -0,0 +1,33 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.ui.view" id="assing_agended_view_form">
<field name="model">optical_equipment_maintenance.agended</field>
<field name="type">form</field>
<field name="name">assing_agended_form</field>
</record>
<record model="ir.action.wizard" id="act_assing_agended">
<field name="name">Assing Agended</field>
<field name="wiz_name">optical_equipment_maintenance.assing_agended</field>
</record>
<record model="ir.ui.view" id="reassing_agended_view_form">
<field name="model">optical_equipment_maintenance.reagended</field>
<field name="type">form</field>
<field name="name">reassing_agended_form</field>
</record>
<record model="ir.action.wizard" id="act_reassing_agended">
<field name="name">ReAssing Agended</field>
<field name="wiz_name">optical_equipment_maintenance.reassing_agended</field>
</record>
<menuitem parent="menu_diary"
action="act_assing_agended"
sequence="30"
id="menu_assing_agended_form"/>
<menuitem parent="menu_diary"
action="act_reassing_agended"
sequence="40"
id="menu_reassing_agended_form"/>
</data>
</tryton>

93
calibration.py Normal file
View File

@ -0,0 +1,93 @@
# 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, sequence_ordered)
from trytond.pyson import Bool, Eval, If, Id, Equal
from trytond.pool import Pool
from trytond.modules.company import CompanyReport
_digits = (16, 2)
_states = {'readonly': If(Eval('state') != 'draft', True)}
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')
product = fields.Function(fields.Integer("Product ID"), 'on_change_with_product')
number_sample = fields.Float("Sample #", _digits)
value_patterns = fields.Many2One('optical_equipment.product_pattern', "Value Pattern", ondelete='RESTRICT', required=True,
domain=[('product', '=', Eval('product'))],
depends=['product'])
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('maintenance', '_parent_maintenance.equipment')
def on_change_with_product(self, name=None):
if self.maintenance:
return self.maintenance.equipment.product.template.id
@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 CalibrationReport(CompanyReport):
__name__ = 'optical_equipment.maintenance'
@classmethod
def execute(cls, ids, data):
with Transaction().set_context(address_with_party=True):
return super(CalibrationReport, 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

40
calibration.xml Normal file
View File

@ -0,0 +1,40 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.ui.view" id="maintenance_calibration_view_form">
<field name="model">optical_equipment.maintenance.calibration_sample</field>
<field name="type">form</field>
<field name="name">maintenance_sample_form</field>
</record>
<record model="ir.ui.view" id="maintenance_calibration_view_tree">
<field name="model">optical_equipment.maintenance.calibration_sample</field>
<field name="type">tree</field>
<field name="priority" eval="10"/>
<field name="name">maintenance_calibration_tree</field>
</record>
<record model="ir.ui.view" id="calibration_total_view_tree">
<field name="model">optical_equipment.maintenance.calibration</field>
<field name="type">tree</field>
<field name="name">calibration_total_tree</field>
</record>
<record model="ir.ui.view" id="calibration_total_view_form">
<field name="model">optical_equipment.maintenance.calibration</field>
<field name="type">form</field>
<field name="name">calibration_total_form</field>
</record>
<record model="ir.action.report" id="report_calibration">
<field name="name">Calibration</field>
<field name="model">optical_equipment.maintenance</field>
<field name="report_name">optical_equipment.maintenance</field>
<field name="report">optical_equipment/report/Calibration.fodt</field>
<field name="single" eval="True"/>
</record>
<record model="ir.action.keyword" id="report_calibration_keyword">
<field name="keyword">form_print</field>
<field name="model">optical_equipment.maintenance,-1</field>
<field name="action" ref="report_calibration"/>
</record>
</data>
</tryton>

View File

@ -4,6 +4,30 @@ from trytond.pyson import Id
from trytond.modules.company.model import (
CompanyMultiValueMixin, CompanyValueMixin)
class Configuration(ModelSingleton, ModelSQL, ModelView, CompanyMultiValueMixin):
'Equipment Configuration'
__name__='optical_equipment.configuration'
equipment_sequence = fields.Many2One('ir.sequence', "Equipment Sequence",
domain=[('sequence_type', '=', Id('optical_equipment', 'sequence_type_equipment'))])
maintenance_sequence = fields.Many2One('ir.sequence', "Maintenance Sequence",
domain=[('sequence_type', '=', Id('optical_equipment', 'sequence_type_maintenances'))])
agended_sequence = fields.Many2One('ir.sequence', "Agended Sequence",
domain=[('sequence_type', '=', Id('optical_equipment', 'sequence_type_agended'))])
contract_sequence = fields.Many2One('ir.sequence', "Contract Sequence",
domain=[('sequence_type', '=', Id('optical_equipment', 'sequence_type_contract'))])
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"))],
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'))],
depends={'moisture_min'})
sale_quote_number = fields.Many2One('ir.sequence', "Sale Quote Number",
domain=[
('sequence_type', '=', Id('sale','sequence_type_sale'))
])

View File

@ -7,6 +7,16 @@
<field name="name">Configuration</field>
<field name="res_model">optical_equipment.configuration</field>
</record>
<record model="ir.ui.view" id="optical_equipment_configuration_view_form">
<field name="model">optical_equipment.configuration</field>
<field name="type">form</field>
<field name="name">configuration_form</field>
</record>
<record model="ir.action.act_window.view" id="act_optical_equipment_configuration_form_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="optical_equipment_configuration_view_form"/>
<field name="act_window" ref="act_optical_equipment_configuration_form"/>
</record>
<menuitem
name="Configuration"
parent="menu_equipment"
@ -19,5 +29,53 @@
sequence="10"
id="menu_optical_equipment_configuration"
icon="tryton-list"/>
<record model="res.group" id="group_maintenance_admin">
<field name="name">Maintenance Administration</field>
</record>
<record model="res.user-res.group"
id="user_admin_group_maintenance_admin">
<field name="user" ref="res.user_admin"/>
<field name="group" ref="group_maintenance_admin"/>
</record>
<record model="ir.ui.menu-res.group"
id="menu_party_group_equipment_admin">
<field name="menu" ref="menu_equipment"/>
<field name="group" ref="group_equipment_admin"/>
</record>
<record model="ir.sequence.type" id="sequence_type_equipment">
<field name="name">Equipment</field>
</record>
<record model="ir.sequence.type-res.group"
id="sequence_type_equipment_group_admin">
<field name="sequence_type" ref="sequence_type_equipment"/>
<field name="group" ref="res.group_admin"/>
</record>
<record model="ir.sequence.type-res.group"
id="sequence_type_equipment_group_equipment_admin">
<field name="sequence_type" ref="sequence_type_equipment"/>
<field name="group" ref="group_equipment_admin"/>
</record>
<record model="ir.sequence" id="sequence_equipment">
<field name="name">Equipment</field>
<field name="sequence_type" ref="sequence_type_equipment"/>
</record>
<record model="ir.sequence.type" id="sequence_type_maintenances">
<field name="name">Maintenances</field>
</record>
<record model="ir.sequence.type-res.group"
id="sequence_type_maintenance_group_admin">
<field name="sequence_type" ref="sequence_type_maintenances"/>
<field name="group" ref="res.group_admin"/>
</record>
<record model="ir.sequence.type-res.group"
id="sequence_type_maintenance_group_maintenance_admin">
<field name="sequence_type" ref="sequence_type_maintenances"/>
<field name="group" ref="group_maintenance_admin"/>
</record>
<record model="ir.sequence" id="sequence_maintenances">
<field name="name">Maintenance</field>
<field name="sequence_type" ref="sequence_type_maintenances"/>
</record>
</data>
</tryton>

302
contract.py Normal file
View File

@ -0,0 +1,302 @@
from trytond.pool import Pool, PoolMeta
from trytond.model import (
ModelSQL, ModelView, Workflow, fields)
from trytond.modules.company import CompanyReport
from trytond.pyson import Eval, If, Bool
from trytond.modules.company.model import set_employee
from trytond.exceptions import UserError
from trytond.transaction import Transaction
from trytond.wizard import (
Button, StateAction, StateTransition, StateView, Wizard)
from trytond.modules.currency.fields import Monetary
from trytond.modules.product import price_digits
import datetime
from datetime import timedelta
class Contract(Workflow, ModelSQL, ModelView):
'Contracts'
__name__ = 'optical_equipment.contract'
_rec_name = 'number'
_order_name = 'number'
company = fields.Many2One(
'company.company', "Company", required=True, select=True,
states={
'readonly': (Eval('state') != 'draft') | Eval('party', True),
},help="Make the subscription belong to the company.")
number = fields.Char(
"Number", readonly=True, select=True,
help="The main identification of the subscription.")
reference = fields.Char(
"Reference", select=True,
help="The identification of an external origin.")
description = fields.Char("Description",
states={
'readonly': Eval('state') != 'draft',
})
party = fields.Many2One(
'party.party', "Party", required=True,
states={
'readonly': (Eval('state') != 'draft') | Eval('party', True),
},help="The party who subscribes.")
contact = fields.Many2One('party.contact_mechanism', "Contact", required=True)
invoice_address = fields.Many2One('party.address', 'Invoice Address',
required=True, domain=[('party', '=', Eval('party'))],
states={
'readonly': (Eval('state') != 'draft') | Eval('party', True),
})
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),
],
states={
'readonly': Eval('state') != 'draft',
})
maintenance_services = fields.Many2Many('optical_equipment_maintenance.service-equipment.contract',
'contract', 'maintenance_services', "Prorogues",
states={'readonly': Eval('state') != 'draft'})
equipments = fields.One2Many('optical_equipment.equipment', 'contract', "Equipments",
states={'readonly': Eval('state') != 'draft'})
price_contract = Monetary("Price Contract", digits=price_digits, currency='currency', required=True,
states={'readonly': Eval('state') != 'draft'})
state = fields.Selection([
('draft', "Draft"),
('running', "Running"),
('closed', "Closed"),
('cancelled', "Cancelled"),
], "State", readonly=True, required=False, sort=False,
help="The current state of the subscription.")
@classmethod
def __setup__(cls):
super(Contract, cls).__setup__()
cls._order = [
('number', 'DESC NULLS FIRST'),
('id', 'DESC'),
]
cls._transitions = ({
('draft', 'running'),
('running', 'draft'),
('running', 'closed'),
('running', 'cancelled'),
})
cls._buttons.update({
'draft': {'invisible': Eval('state').in_(['draft','closed'])},
'running': {'invisible': Eval('state').in_(['cancelled', 'running'])},
'cancelled': {'invisible': Eval('state').in_(['draft', 'cancelled'])}
})
@staticmethod
def default_company():
return Transaction().context.get('company')
@staticmethod
def default_state():
return 'draft'
@classmethod
def set_number(cls, contracts):
pool = Pool()
Config = pool.get('optical_equipment.configuration')
config = Config(4)
if config.contract_sequence != None:
if not contracts[0].number:
try:
contracts[0].number = config.contract_sequence.get()
cls.save(contracts)
except UserError:
raise UserError(str('Validation Error'))
else:
raise UserError(gettext('optical_equipment.msg_not_sequence_equipment'))
@classmethod
@ModelView.button
@Workflow.transition('draft')
def draft(cls, contracts):
contract = contracts[0]
for equipment in contract.equipments:
equipment.state = "uncontrated"
equipment.contract_history += (contract.id,)
equipment.save()
@classmethod
@ModelView.button
@Workflow.transition('running')
def running(cls, contracts):
contract = contracts[0]
for equipment in contract.equipments:
equipment.state = "contrated"
equipment.contract_history += (contract.id,)
equipment.save()
cls.set_number(contracts)
contract.state='running'
contract.save()
@classmethod
@ModelView.button
@Workflow.transition('cancelled')
def cancelled(cls, contracts):
pass
class ContractMaintenanceServices(ModelSQL):
'Contract - Maintenance Services'
__name__ = 'optical_equipment_maintenance.service-equipment.contract'
maintenance_services = fields.Many2One('optical_equipment_maintenance.service', "Maintenance Service", select=True)
contract = fields.Many2One('optical_equipment.contract', "Contract")
class ContractEquipment(ModelSQL):
'Optical Equipment - Contract'
__name__ = 'optical_equipment.contract-optical_equipment.equipment'
equipment = fields.Many2One('optical_equipment.equipment', 'Equipment', select=True)
contract = fields.Many2One('optical_equipment.contract', 'Contract', select=True)
class ContractReport(CompanyReport):
__name__ = 'optical_equipment.contract'
@classmethod
def execute(cls, ids, data):
with Transaction().set_context(address_with_party=True):
return super(ContractReport, 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
class CreateContractInitial(ModelView, ModelSQL):
'Create Contract Inicial'
__name__ = 'optical_equipment_create.contract'
currency = fields.Many2One('currency.currency', 'Currency', required=True)
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),
])
unit_price = Monetary(
"Unit Price", digits=price_digits, currency='currency')
@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=182)
else:
self.end_date = Date.today() + timedelta(days=365)
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()

153
contract.xml Normal file
View File

@ -0,0 +1,153 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.ui.view" id="contract_view_form">
<field name="model">optical_equipment.contract</field>
<field name="type">form</field>
<field name="name">contract_form</field>
</record>
<record model="ir.ui.view" id="contract_view_list">
<field name="model">optical_equipment.contract</field>
<field name="type">tree</field>
<field name="name">contract_list</field>
</record>
<record model="ir.action.act_window" id="act_contract_form">
<field name="name">Contracts</field>
<field name="res_model">optical_equipment.contract</field>
</record>
<record model="ir.action.act_window.view"
id="act_contract_form_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="contract_view_list"/>
<field name="act_window" ref="act_contract_form"/>
</record>
<record model="ir.action.act_window.view"
id="act_contract_form_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="contract_view_form"/>
<field name="act_window" ref="act_contract_form"/>
</record>
<record model="ir.action.act_window.domain"
id="act_contract_form_domain_draft">
<field name="name">Draft</field>
<field name="sequence" eval="10"/>
<field name="domain" eval="[('state', '=', 'draft')]" pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_contract_form"/>
</record>
<record model="ir.action.act_window.domain"
id="act_contract_form_domain_running">
<field name="name">Running</field>
<field name="sequence" eval="30"/>
<field name="domain" eval="[('state', '=', 'running')]" pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_contract_form"/>
</record>
<record model="ir.action.act_window.domain"
id="act_contract_form_domain_closed">
<field name="name">Closed</field>
<field name="sequence" eval="40"/>
<field name="domain" eval="[('state', '=', 'closed')]" pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_contract_form"/>
</record>
<record model="ir.action.act_window.domain"
id="act_contract_form_domain_all">
<field name="name">All</field>
<field name="sequence" eval="9999"/>
<field name="domain"></field>
<field name="act_window" ref="act_contract_form"/>
</record>
<record model="ir.model.button" id="draft_running_button">
<field name="name">draft</field>
<field name="string">Draft</field>
<field name="model" search="[('model', '=', 'optical_equipment.contract')]"/>
</record>
<record model="ir.model.button" id="contrac_running_button">
<field name="name">running</field>
<field name="string">Run</field>
<field name="model" search="[('model', '=', 'optical_equipment.contract')]"/>
</record>
<record model="ir.model.button" id="contract_cancelled_button">
<field name="name">cancelled</field>
<field name="string">Cancel</field>
<field name="model" search="[('model', '=', 'optical_equipment.contract')]"/>
</record>
<record model="res.group" id="group_contract_admin">
<field name="name">Contract Administration</field>
</record>
<record model="res.user-res.group"
id="user_admin_group_contract_admin">
<field name="user" ref="res.user_admin"/>
<field name="group" ref="group_contract_admin"/>
</record>
<record model="ir.sequence.type" id="sequence_type_contract">
<field name="name">Contract</field>
</record>
<record model="ir.sequence.type-res.group"
id="sequence_type_contract_group_admin">
<field name="sequence_type" ref="sequence_type_contract"/>
<field name="group" ref="res.group_admin"/>
</record>
<record model="ir.sequence.type-res.group"
id="sequence_type_contract_group_contract_admin">
<field name="sequence_type" ref="sequence_type_contract"/>
<field name="group" ref="group_contract_admin"/>
</record>
<record model="ir.sequence" id="sequence_contract">
<field name="name">Contract</field>
<field name="sequence_type" ref="sequence_type_contract"/>
</record>
<record model="ir.ui.view" id="create_contract_view_form">
<field name="model">optical_equipment_create.contract</field>
<field name="type">form</field>
<field name="name">create_contract_form</field>
</record>
<record model="ir.action.wizard" id="maintenance_create_contract">
<field name="name">Create Contract</field>
<field name="wiz_name">optical_equipment.maintenance.contract</field>
<field name="model">optical_equipment_maintenance.service</field>
</record>
<record model="ir.action.keyword" id="maintenance_create_contract_keyword">
<field name="keyword">form_action</field>
<field name="model">optical_equipment_maintenance.service,-1</field>
<field name="action" ref="maintenance_create_contract"/>
</record>
<record model="ir.action.report" id="report_contract">
<field name="name">Contract</field>
<field name="model">optical_equipment.contract</field>
<field name="report_name">optical_equipment.contract</field>
<field name="report">optical_equipment/report/Contract.fodt</field>
<field name="single" eval="True"/>
</record>
<record model="ir.action.keyword" id="report_contract_keyword">
<field name="keyword">form_print</field>
<field name="model">optical_equipment.contract,-1</field>
<field name="action" ref="report_contract"/>
</record>
<record model="ir.action.report" id="report_prorrogation">
<field name="name">Prorrogation</field>
<field name="model">optical_equipment.contract</field>
<field name="report_name">optical_equipment.contract</field>
<field name="report">optical_equipment/report/Prorrogation.fodt</field>
<field name="single" eval="True"/>
</record>
<record model="ir.action.keyword" id="report_prorrogation_keyword">
<field name="keyword">form_print</field>
<field name="model">optical_equipment.contract,-1</field>
<field name="action" ref="report_prorrogation"/>
</record>
<menuitem
parent="menu_equipment"
name="Contracts Management"
sequence="50"
id="menu_contracts"/>
<menuitem
parent="menu_contracts"
action="act_contract_form"
sequence="30"
id="menu_contract_form"/>
</data>
</tryton>

24
diary.py Normal file
View File

@ -0,0 +1,24 @@
from trytond.model import (
ModelSQL, ModelView, fields)
class Diary(ModelSQL, ModelView):
'Diary'
__name__ = 'optical_equipment_maintenance.diary'
_rec_name = 'code'
code = fields.Char("Code", select=True,states={'readonly': True })
date_expected = fields.DateTime("Expected Date", required=True)
date_estimated = fields.DateTime("Estimated Date")
date_end = fields.DateTime("Date End")
maintenance_service = fields.Many2One('optical_equipment_maintenance.service', 'Maintenance Service', required=True)
technical = fields.Many2One('company.employee', "Technical", required=True)
state = fields.Selection([('draft', "Draft"),
('agended', "Agended"),
('in_progress', "In Progress"),
('failed', "Failed"),
('finished', "Finished")
], "State", required=True, readonly=True, sort=True)
@classmethod
def default_state(self):
return 'draft'

106
diary.xml Normal file
View File

@ -0,0 +1,106 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
<record model="res.group" id="group_agended_admin">
<field name="name">Agended Administration</field>
</record>
<record model="res.user-res.group"
id="user_admin_group_agended_admin">
<field name="user" ref="res.user_admin"/>
<field name="group" ref="group_agended_admin"/>
</record>
<record model="ir.action.act_window" id="act_agended_list_form">
<field name="name">Agended</field>
<field name="res_model">optical_equipment_maintenance.diary</field>
<field name="search_value"></field>
</record>
<record model="ir.ui.view" id= "agended_list_view_tree">
<field name="model">optical_equipment_maintenance.diary</field>
<field name="type">tree</field>
<field name="name">diary_tree</field>
</record>
<record model="ir.ui.view" id="agended_list_view_form">
<field name="model">optical_equipment_maintenance.diary</field>
<field name="type">form</field>
<field name="name">diary_form</field>
</record>
<record model="ir.action.act_window.domain" id="act_agended_list_form_domain_draft">
<field name="name">Draft</field>
<field name="sequence" eval="10"/>
<field name="domain"
eval="[('state', '=', 'draft')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_agended_list_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_agended_list_form_domain_agended">
<field name="name">Agended</field>
<field name="sequence" eval="20"/>
<field name="domain"
eval="[('state', '=', 'agended')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_agended_list_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_agended_list_form_domain_in_progress">
<field name="name">In progress</field>
<field name="sequence" eval="30"/>
<field name="domain"
eval="[('state', '=', 'in_progress')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_agended_list_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_agended_list_form_domain_failed">
<field name="name">Failed</field>
<field name="sequence" eval="30"/>
<field name="domain"
eval="[('state', '=', 'failed')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_agended_list_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_agended_list_form_domain_finished">
<field name="name">Finished</field>
<field name="sequence" eval="40"/>
<field name="domain"
eval="[('state', '=', 'finished')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_agended_list_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_agended_list_form_domain_all">
<field name="name">All</field>
<field name="sequence" eval="9999"/>
<field name="domain"></field>
<field name="act_window" ref="act_agended_list_form"/>
</record>
<record model="ir.sequence.type" id="sequence_type_agended">
<field name="name">Agended</field>
</record>
<record model="ir.sequence.type-res.group"
id="sequence_type_agended_group_admin">
<field name="sequence_type" ref="sequence_type_agended"/>
<field name="group" ref="res.group_admin"/>
</record>
<record model="ir.sequence.type-res.group"
id="sequence_type_agended_group_agended_admin">
<field name="sequence_type" ref="sequence_type_agended"/>
<field name="group" ref="group_agended_admin"/>
</record>
<record model="ir.sequence" id="sequence_agended">
<field name="name">Agended</field>
<field name="sequence_type" ref="sequence_type_agended"/>
</record>
<menuitem parent="menu_equipment"
name="Diary"
sequence="10"
id="menu_diary"/>
<menuitem parent="menu_diary"
action="act_agended_list_form"
sequence="20"
id="menu_agended_list_form"/>
</data>
</tryton>

405
equipment.py Normal file
View File

@ -0,0 +1,405 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import datetime
from collections import defaultdict
from trytond.pool import Pool
from trytond.model import (
DeactivableMixin, Workflow, ModelSQL, ModelView, Unique, fields)
from trytond.pyson import Eval, If
from trytond.transaction import Transaction
from trytond.i18n import gettext
from trytond.exceptions import UserError
from trytond.model.exceptions import AccessError
from trytond.wizard import (
Button, StateAction, StateTransition, StateView, Wizard)
from trytond.modules.company import CompanyReport
_MAINTENANCE_FREQUENCY = [("none", ''),
("6", 'Seis Meses'),
("12", 'Doce Meses')]
class OpticalEquipment(DeactivableMixin, Workflow, ModelSQL, ModelView):
'Optical Equipment'
__name__ = 'optical_equipment.equipment'
_rec_name = 'rec_name'
_order_name = 'code'
_states={
'readonly': Eval('state') != 'draft',
}
_depends = ['state']
_states_serial={
'readonly': Eval('state') != 'draft',
}
code = fields.Char(
"Code", select=True,states={'readonly': True })
state = fields.Selection([('draft', "Draft"),
('registred', "Registred"),
('uncontrated', "UnContrated"),
('contrated', "Contrated")
], "State",
required=True, readonly=True, sort=False)
contract = fields.Many2One('optical_equipment.contract', "Contract", ondelete='CASCADE')
company = fields.Many2One('company.company', "Company", readonly=True)
location = fields.Many2One('stock.location', "Location",
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
)
propietarys = fields.Many2Many('optical_equipment.equipment-party.party', 'equipment', 'party', "Propietarys")
product = fields.Many2One('product.product', "Product",
domain=[('equipment', '=', True)],
states=_states,
depends=['equipment']
)
refurbish = fields.Boolean("Refurbish",
states=_states,)
equipment_type = fields.Char('type', states={'readonly': If('product', True)})
risk = fields.Char('Type risk',states={'readonly': If('product', True)})
use = fields.Char('Use', states={'readonly': If('product', True)})
biomedical_class = fields.Char('Biomedical Class', states={'readonly': If('product', True)})
main_tecnology = fields.Char('Main tecnology', states={'readonly': If('product', True)})
calibration = fields.Boolean("Apply calibration", states={'readonly': If('product', True)})
mark_category = fields.Many2One('product.category', 'Mark', required=True,
domain=[('parent', '=', None),
('accounting', '=', False)],
states=_states
)
model_category = fields.Many2One('product.category', "Model", required=True,
domain=[('parent', '=', Eval('mark_category')),
('accounting', '=', False)],
states=_states,)
reference_category = fields.Many2One('product.category', "Reference",
domain=[('parent', '=', Eval('model_category'))],
states=_states,
depends=['model_category']
)
origin_country = fields.Many2One('country.country',"Origin Country",
states=_states,)
software_version = fields.Char("Software version", size=None,
states=_states,)
useful_life = fields.Integer("Useful life",
states=_states,)
warranty = fields.Integer("Warranty",
states=_states,)
serial = fields.Char("Serial", size=None,
states=_states_serial,
depends=_depends)
health_register = fields.Char("Health Register", size=None,
states=_states,)
contract_history = fields.Many2Many('optical_equipment.contract-optical_equipment.equipment', 'equipment','contract', "Contracts", states={'readonly': True})
maintenance_history = fields.Function(
fields.Many2Many('optical_equipment.maintenance-optical_equipment.equipment',
'equipment', 'maintenance',"Maintenances"), 'get_maintenances_of_equipment')
software_version = fields.Char("Software version", size=None,
states=_states,)
maintenance_frequency = fields.Selection(_MAINTENANCE_FREQUENCY, "Maintenance Frequency",
depends=['propietary'])
purchase_origin = fields.Reference("Purchase Origin", selection='get_origin',select=True,
states={'readonly': True})
sale_destination = fields.Reference("Sale Destination", selection='get_destination',select=True,
states={'readonly': True})
shipment_destination = fields.Reference("Stock Move", selection='get_shipment', select=True,
states={'readonly': True})
rec_name = fields.Function(fields.Char("rec_name"), 'get_rec_name')
del _states_serial, _states, _depends
@fields.depends('product', 'serial', 'code')
def get_rec_name(self, name):
name = str(self.product.name) + '@' + str(self.serial) + '/' + str(self.code)
return name
@staticmethod
def _get_shipment():
'Return list of Model names for shipment Reference'
return [
'stock.shipment.in',
'stock.shipment.out',
'stock.shipment.out.return',
'stock.shipment.in.return',
'stock.shipment.internal',
]
@classmethod
def get_shipment(cls):
IrModel = Pool().get('ir.model')
get_name = IrModel.get_name
models = cls._get_shipment()
return [(None, '')] + [(m, get_name(m)) for m in models]
@classmethod
def _get_origin(cls):
'Return list of Model names for origin Reference'
pool = Pool()
Purchase = pool.get('purchase.line')
return [Purchase.__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_destination(cls):
'Return list of Model names for origin Reference'
pool = Pool()
Sale = pool.get('sale.line')
return [Sale.__name__]
@classmethod
def get_destination(cls):
Model = Pool().get('ir.model')
get_name = Model.get_name
models = cls._get_destination()
return [(None, '')] + [(m, get_name(m)) for m in models]
@classmethod
def __setup__(cls):
super(OpticalEquipment, cls).__setup__()
cls._transitions = ({
('draft', 'registred'),
('registred', 'draft'),
('registred', 'uncontrated'),
('uncontrated', 'contrated'),
})
cls._buttons.update({
'draft': {
'invisible': Eval('state') != 'registred'},
'registred': {
'invisible': Eval('state').in_(['registred', 'uncontrated', 'contrated'])}}
)
@classmethod
def set_code(cls, equipments):
pool = Pool()
Config = pool.get('optical_equipment.configuration')
config = Config(1)
for equipment in equipments:
if config.equipment_sequence != None:
if not equipment.code:
try:
equipment.code = config.equipment_sequence.get()
cls.save(equipments)
except UserError:
raise UserError(str('Validation Error'))
else:
raise UserError(gettext('optical_equipment.msg_not_sequence_equipment'))
def get_maintenances_of_equipment(self, records):
pool = Pool()
MaintenancesEquipment = pool.get('optical_equipment.maintenance')
maintenancesEquipment = set()
maintenancesEquipment = MaintenancesEquipment.search(['equipment', '=', self.id])
maintenances = []
for key in maintenancesEquipment:
maintenances.append(key.id)
return maintenances
@classmethod
def default_state(cls):
return 'draft'
@staticmethod
def default_company():
return Transaction().context.get('company')
@fields.depends('propietary', 'maintenance_frequency')
def on_change_propietary(self):
if self.propietary:
if self.propietary.client_type == 'ips':
self.maintenance_frequency = "6"
else:
self.maintenance_frequency = "12"
else:
self.maintenance_frequency = "none"
@fields.depends('product', 'equipment_type','use',
'biomedical_class', 'calibration',
'mark_category', 'model_category')
def on_change_product(self):
if self.product:
self.equipment_type=self.product.equipment_type
self.use=self.product.use
self.biomedical_class=self.product.biomedical_class
self.calibration=self.product.calibration
self.mark_category=self.product.mark_category
self.model_category=self.product.model_category
self.reference_category=self.product.reference_category
self.useful_life=self.product.useful_life if self.product.useful_life else int(0)
self.calibration=True if self.product.calibration else False
self.warranty=self.product.warranty if self.product.warranty else int(0)
self.risk=self.product.risk
self.origin_country=self.product.origin_country
self.use=self.product.use
self.biomedical_class=self.product.biomedical_class
else:
self.equipment_type=None
self.use=None
self.biomedical_class=None
self.calibration=None
self.mark_category=None
self.model_category=None
self.reference_category=None
self.useful_life=None
self.calibration=False
self.warranty=None
self.risk=None
self.origin_country=None
self.use=None
self.biomedical_class=None
self.refurbish=None
self.serial=None
self.health_register=None
self.software_version=None
@classmethod
def delete(cls, equipments):
for equipment in equipments:
if equipment.purchase_origin:
raise AccessError(
gettext('estos equipos no se pueden borrar'))
elif equipment.state != 'draft' and equipment.serial != None:
raise AccessError(
gettext('estos equipos no se pueden borrar'))
super(OpticalEquipment, cls).delete(equipments)
@classmethod
@ModelView.button
@Workflow.transition('draft')
def draft(cls, equipments):
pass
@classmethod
@ModelView.button
@Workflow.transition('registred')
def registred(cls, equipments):
for i in equipments:
if i.serial == None:
raise UserError(str("El Equipo no cuenta con un Serial"))
else:
cls.set_code(equipments)
class EquipmentMaintenance(ModelSQL, ModelView):
'Optical Equipment - Equipment - Maintenance'
__name__ ='optical_equipment.maintenance-optical_equipment.equipment'
equipment = fields.Many2One('optical_equipment.equipment', 'Equipment', select=True)
maintenance = fields.Many2One('optical_equipment.maintenance', 'Maintenances', select=True)
class EquipmentContract(ModelSQL, ModelView):
'Optical Equipment - Contracs Equipment'
__name__ = 'optical_equipment.contract-optical_equipment.equipment'
equipment = fields.Many2One('optical_equipment.equipment', 'Equipment', select=True)
contract = fields.Many2One('optical_equipment.contract', 'Contract', select=True)
class EquipmentParty(ModelSQL, ModelView):
'Optical Equipment - Party'
__name__ = 'optical_equipment.equipment-party.party'
equipment = fields.Many2One('optical_equipment.equipment', "Equipment", select=True)
party = fields.Many2One('party.party', "Party", select=True)
class ChangePropietary(ModelView):
'Change of Propietary Equipment'
__name__ = 'optical_equipment.change_propietary.form'
old_propietary = fields.Many2One('party.party', 'Old Propietary',
states={'required': True})
equipments = fields.Many2Many('optical_equipment.equipment', None, None, "Equipments",
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 NewPropietary(Wizard):
'Change Propietary'
__name__ = 'optical_equipment.change_propietary'
start = StateView('optical_equipment.change_propietary.form',
'optical_equipment.change_propietary_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):
old_propietary = self.start.old_propietary
equipments = self.start.equipments
new_propietary = self.start.new_propietary
new_address = self.start.new_address
for equipment in equipments:
equipment.propietarys += (equipment.propietary,)
equipment.propietary = new_propietary
equipment.propietary_address = new_address
equipment.maintenance_frequency = "6" if new_propietary.client_type == 'ips' else "12"
equipment.save()
class ChangeEquipment(ModelSQL):
'Change Equipment'
__name__ = 'optical_equipment.equipment-change_propietary.form'
maintenance_service = fields.Many2One('optical_equipment_maintenance.service', "Maintenance Service")
equipment = fields.Many2One('optical_equipment.equipment', 'Equipment')
change = fields.Many2One('optical_equipment.change_propietary.form', 'Change')
class EquipmentReport(CompanyReport):
__name__ = 'optical_equipment.equipment'
@classmethod
def execute(cls, ids, data):
with Transaction().set_context(address_with_party=True):
return super(EquipmentReport, 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

View File

@ -3,9 +3,169 @@
this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
<record model="res.group" id="group_equipment_admin">
<field name="name">Equipment Administration</field>
</record>
<record model="res.user-res.group"
id="user_admin_group_equipment_admin">
<field name="user" ref="res.user_admin"/>
<field name="group" ref="group_equipment_admin"/>
</record>
<menuitem
name="Equipment"
sequence="40"
id="menu_equipment"/>
<record model="ir.action.act_window" id="act_optical_equipment_form">
<field name="name">Equipments</field>
<field name="res_model">optical_equipment.equipment</field>
<field name="search_value"></field>
</record>
<record model="ir.ui.view" id="optical_equipment_view_tree">
<field name="model">optical_equipment.equipment</field>
<field name="type">tree</field>
<field name="name">optical_equipment_tree</field>
</record>
<record model="ir.ui.view" id="optical_equipment_view_form">
<field name="model">optical_equipment.equipment</field>
<field name="type">form</field>
<field name="name">optical_equipment_form</field>
</record>
<record model="ir.action.act_window.view" id="act_optical_equipment_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="optical_equipment_view_tree"/>
<field name="act_window" ref="act_optical_equipment_form"/>
</record>
<record model="ir.action.act_window.view" id="act_optical_equipment_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="optical_equipment_view_form"/>
<field name="act_window" ref="act_optical_equipment_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_optical_equipment_form_domain_draft">
<field name="name">Draft</field>
<field name="sequence" eval="10"/>
<field name="domain"
eval="[('state', '=', 'draft')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_optical_equipment_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_optical_equipment_form_domain_registred">
<field name="name">Registred</field>
<field name="sequence" eval="20"/>
<field name="domain"
eval="[('state', '=', 'registred')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_optical_equipment_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_optical_equipment_form_domain_uncontrated">
<field name="name">UnContrated</field>
<field name="sequence" eval="30"/>
<field name="domain"
eval="[('state', '=', 'uncontrated')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_optical_equipment_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_optical_equipment_form_domain_contrated">
<field name="name">Contrated</field>
<field name="sequence" eval="30"/>
<field name="domain"
eval="[('state', '=', 'contrated')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_optical_equipment_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_optical_equipment_form_domain_all">
<field name="name">All</field>
<field name="sequence" eval="9999"/>
<field name="domain"></field>
<field name="act_window" ref="act_optical_equipment_form"/>
</record>
<record model="ir.model.button" id="draft_equipment_button">
<field name="name">draft</field>
<field name="string">Draft</field>
<field name="model" search="[('model', '=', 'optical_equipment.equipment')]"/>
</record>
<record model="ir.model.button" id="registred_equipment_button">
<field name="name">registred</field>
<field name="string">Registred</field>
<field name="confirm">Are you sure you want to registred these equipments?</field>
<field name="model" search="[('model', '=', 'optical_equipment.equipment')]"/>
</record>
<menuitem parent="menu_equipment"
action="act_optical_equipment_form"
sequence="60"
id="menu_optical_equipment_form"/>
<record model="ir.action.act_window" id="act_optical_equipment_form1">
<field name="name">Serials</field>
<field name="res_model">optical_equipment.equipment</field>
<field name="search_value"></field>
</record>
<record model="ir.ui.view" id="optical_equipment_view_tree1">
<field name="model">optical_equipment.equipment</field>
<field name="type">tree</field>
<field name="name">optical_equipment_serial_tree</field>
</record>
<record model="ir.action.act_window.view" id="act_optical_equipment_view3">
<field name="sequence" eval="10"/>
<field name="view" ref="optical_equipment_view_tree1"/>
<field name="act_window" ref="act_optical_equipment_form1"/>
</record>
<record model="ir.action.act_window.domain" id="act_optical_equipment_serial_form_domain_draft">
<field name="name">Draft</field>
<field name="sequence" eval="10"/>
<field name="domain"
eval="[('state', '=', 'draft')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_optical_equipment_form1"/>
</record>
<menuitem
parent="menu_equipment"
action="act_optical_equipment_form1"
sequence="70"
id="menu_optical_equipment_serial_form"/>
<record model="ir.action.report" id="report_equipment">
<field name="name">Equipment</field>
<field name="model">optical_equipment.equipment</field>
<field name="report_name">optical_equipment.equipment</field>
<field name="report">optical_equipment/report/CV_Equipment.fodt</field>
<field name="single" eval="True"/>
</record>
<record model="ir.action.keyword" id="report_equipment_keyword">
<field name="keyword">form_print</field>
<field name="model">optical_equipment.equipment,-1</field>
<field name="action" ref="report_equipment"/>
</record>
<record model="ir.action.report" id="report_history_maintenance">
<field name="name">Maintenance History</field>
<field name="model">optical_equipment.equipment</field>
<field name="report_name">optical_equipment.equipment</field>
<field name="report">optical_equipment/report/Maintenance_History.fodt</field>
<field name="single" eval="True"/>
</record>
<record model="ir.action.keyword" id="report_history_maintenance_keyword">
<field name="keyword">form_print</field>
<field name="model">optical_equipment.equipment,-1</field>
<field name="action" ref="report_history_maintenance"/>
</record>
<record model="ir.ui.view" id="change_propietary_view_form">
<field name="model">optical_equipment.change_propietary.form</field>
<field name="type">form</field>
<field name="name">change_propietary_form</field>
</record>
<record model="ir.action.wizard" id="equipment_change_propietary">
<field name="name">Change Propietary</field>
<field name="wiz_name">optical_equipment.change_propietary</field>
<field name="model">optical_equipment.equipment</field>
</record>
<record model="ir.action.keyword" id="equipment_change_propietary_keyword">
<field name="keyword">form_action</field>
<field name="model">optical_equipment.equipment,-1</field>
<field name="action" ref="equipment_change_propietary"/>
</record>
</data>
</tryton>

View File

@ -15,21 +15,848 @@ import datetime
from datetime import timedelta
#from scipy.stats import t
#import matplotlib.pyplot as plt
#import numpy as np
#import math as mt
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([('initial','Initial'),
('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")
estimated_agended = fields.DateTime("Date Maintenance", states=_states)
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", 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')
temperature_min = fields.Float("Temp Min", states={
'readonly': If(Eval('state') == 'finished', True),
'required': If(Eval('state') == 'in_progress', True)})
temperature_max = fields.Float("Temp Max", states={
'readonly': If(Eval('state') == 'finished', True),
'required': If(Eval('state') == 'in_progress', True)})
temperature_uom = fields.Many2One('product.uom', 'Temperature UOM',
domain=[('category', '=', Id('optical_equipment', "uom_cat_temperature"))],
states={'invisible': If(Eval('temperature_min') == None, True),
'readonly' : (Eval('state') == 'finished'),
'required': If(Eval('state') == 'in_progress', True)},)
moisture_min = fields.Float("Moisture Min", states={
'readonly': If(Eval('state') == 'finished', True),
'required': If(Eval('state') == 'in_progress', True)})
moisture_max = fields.Float("Moisture Max", states={
'readonly': If(Eval('state') == 'finished', True),
'required': If(Eval('state') == 'in_progress', True)})
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),
'readonly': Eval('state') == 'finished',
'required': If(Eval('state') == 'in_progress', True)},)
@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')
@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)
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)
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 _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__]
class MaintenanceLine(Workflow, ModelSQL, ModelView):
'Equipment Maintenance'
@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):
for maintenance in maintenances:
maintenance.current_agended.state = 'in_progress'
maintenance.current_agended.save()
@classmethod
@ModelView.button
@Workflow.transition('finished')
def finished(cls, maintenances):
for maintenance in maintenances:
maintenance.current_agended.state = 'finished'
maintenance.current_agended.save()
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', select=True,
domain=[('state', 'in', ['draft','in_progress', 'finished']),
('propietary', '=', Eval('propietary'))],
states=_states)
code = fields.Char(
"Code", select=True,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']),
('propietary', '=', Eval('propietary')),
('propietary_address', '=', Eval('propietary_address'))],
states=_states,)
equipment_calibrate = fields.Boolean("Calibrate Equipment", states={'readonly': True})
#when the maintenance is in agended status
diary = fields.One2Many('optical_equipment_maintenance.diary', 'diary')
#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"))],
states={'invisible': If(Eval('temperature_min') == None, True),
'readonly' : (Eval('state') == 'finished')},)
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),
'readonly': Eval('state') == 'finished'},)
graph_calibration = fields.Binary('Graphs')
rec_name = fields.Function(fields.Char('rec_name'), 'get_rec_name')
@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'])},
'finished': {'invisible': (Eval('state').in_(['finished'])) |
((Eval('maintenance_type') == 'corrective') & (Eval('maintenance_lines') == ()))},
'samples': {'invisible': (Eval('state').in_(['finished'])) | (Eval('lines_calibration') != ())},
'calibrate': {'invisible': (Eval('lines_calibration') == ()) | (Eval('state').in_(['finished'])),
'depends': ['state'],}
})
@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('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
@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'
@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('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:
self.patterns_equipments = self.equipment.product.k_pattern
self.equipment_calibrate = self.equipment.product.calibration
self.initial_operation = self.equipment.product.initial_operation
self.check_equipment = self.equipment.product.check_equipment
self.check_electric_system = self.equipment.product.check_electric_system
self.clean_int_ext = self.equipment.product.clean_int_ext
self.clean_eyes = self.equipment.product.clean_eyes
self.check_calibration = self.equipment.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.client_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_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, 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)")
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]
else:
dates[line.value_patterns.pattern].append(line.value_equipment)
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
resolution = a_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
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 maintenance.equipment.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 maintenance.equipment.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()
equipment_risk = maintenance.equipment.product.risk
image = cls.get_create_graph(dates_mistake_pattern, patterns, resolution, equipment_risk)
maintenance.graph_calibration = image
maintenance.save()
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 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):
old_propietary = self.start.old_propietary
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

236
maintenance.xml Normal file
View File

@ -0,0 +1,236 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.action.act_window" id="act_maintenance_service_form">
<field name="name">Services Maintenance</field>
<field name="res_model">optical_equipment_maintenance.service</field>
<field name="search_value"></field>
</record>
<record model="ir.ui.view" id="maintenance_service_view_tree">
<field name="model">optical_equipment_maintenance.service</field>
<field name="type">tree</field>
<field name="name">maintenance_service_tree</field>
</record>
<record model="ir.ui.view" id="maintenance_service_view_form">
<field name="model">optical_equipment_maintenance.service</field>
<field name="type">form</field>
<field name="name">maintenance_service_form</field>
</record>
<record model="ir.action.act_window.view" id="act_maintenance_service_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="maintenance_service_view_tree"/>
<field name="act_window" ref="act_maintenance_service_form"/>
</record>
<record model="ir.action.act_window.view" id="act_maintenance_service_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="maintenance_service_view_form"/>
<field name="act_window" ref="act_maintenance_service_form"/>
</record>
<record model="ir.action.act_window" id="act_maintenance_form">
<field name="name">Maintenance Lines</field>
<field name="res_model">optical_equipment.maintenance</field>
<field name="search_value"></field>
</record>
<record model="ir.ui.view" id= "maintenance_view_tree">
<field name="model">optical_equipment.maintenance</field>
<field name="type">tree</field>
<field name="name">maintenance_tree</field>
</record>
<record model="ir.ui.view" id="maintenance_view_form">
<field name="model">optical_equipment.maintenance</field>
<field name="type">form</field>
<field name="name">maintenance_form</field>
</record>
<record model="ir.action.act_window.view" id="act_maintenance_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="maintenance_view_tree"/>
<field name="act_window" ref="act_maintenance_form"/>
</record>
<record model="ir.action.act_window.view" id="act_maintenance_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="maintenance_view_form"/>
<field name="act_window" ref="act_maintenance_form"/>
</record>
<record model="ir.ui.view" id="change_propietary_maintenance_view_form">
<field name="model">optical_equipment.change_propietary_maintenance.form</field>
<field name="type">form</field>
<field name="name">change_propietary_maintenance_form</field>
</record>
<record model="ir.ui.view" id= "maintenance_equipment_view_form">
<field name="model">optical_equipment.maintenance-optical_equipment.equipment</field>
<field name="inherit" ref="maintenance_view_form"/>
<field name="name">maintenance_equipment_form</field>
</record>
<record model="ir.ui.view" id="maintenance_activity_view_form">
<field name="model">optical_equipment_maintenance.activity</field>
<field name="type">form</field>
<field name="name">maintenance_activity_form</field>
</record>
<record model="ir.ui.view" id="maintenance_activity_view_tree">
<field name="model">optical_equipment_maintenance.activity</field>
<field name="type">tree</field>
<field name="priority" eval="10"/>
<field name="name">maintenance_activity_tree</field>
</record>
<record model="ir.action.act_window.domain" id="act_maintenance_form_domain_draft">
<field name="name">Draft</field>
<field name="sequence" eval="10"/>
<field name="domain"
eval="[('state', '=', 'draft')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_maintenance_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_maintenance_form_domain_finished">
<field name="name">Finished</field>
<field name="sequence" eval="40"/>
<field name="domain"
eval="[('state', '=', 'finished')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_maintenance_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_maintenance_form_domain_all">
<field name="name">All</field>
<field name="sequence" eval="9999"/>
<field name="domain"></field>
<field name="act_window" ref="act_maintenance_form"/>
</record>
<record model="ir.model.button" id="maintenance_service_draft_button">
<field name="name">draft</field>
<field name="string">Draft</field>
<field name="model" search="[('model', '=', 'optical_equipment_maintenance.service')]"/>
</record>
<record model="ir.model.button" id="maintenance_service_in_progress_button">
<field name="name">in_progress</field>
<field name="string">In progress</field>
<field name="model" search="[('model', '=', 'optical_equipment_maintenance.service')]"/>
</record>
<record model="ir.model.button" id="maintenance_service_finished_button">
<field name="name">finished</field>
<field name="string">Finished</field>
<field name="model" search="[('model', '=', 'optical_equipment_maintenance.service')]"/>
</record>
<record model="ir.model.button" id="maintenance_finished_button">
<field name="name">finished</field>
<field name="string">Finished</field>
<field name="model" search="[('model', '=', 'optical_equipment.maintenance')]"/>
</record>
<record model="ir.model.button" id="maintenance_samples_button">
<field name="name">samples</field>
<field name="string">Generate Samples</field>
<field name="model" search="[('model', '=', 'optical_equipment.maintenance')]"/>
</record>
<record model="ir.model.button" id="maintenance_calibrate_button">
<field name="name">calibrate</field>
<field name="string">Calibrate</field>
<field name="model" search="[('model', '=', 'optical_equipment.maintenance')]"/>
</record>
<record model="ir.action.act_window.domain" id="act_maintenance_service_form_domain_draft">
<field name="name">Draft</field>
<field name="sequence" eval="10"/>
<field name="domain"
eval="[('state', '=', 'draft')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_maintenance_service_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_maintenance_service_form_domain_agended">
<field name="name">Agended</field>
<field name="sequence" eval="20"/>
<field name="domain"
eval="[('state', '=', 'agended')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_maintenance_service_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_maintenance_service_form_domain_in_progress">
<field name="name">In progress</field>
<field name="sequence" eval="30"/>
<field name="domain"
eval="[('state', '=', 'in_progress')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_maintenance_service_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_maintenance_service_form_domain_failed">
<field name="name">Failed</field>
<field name="sequence" eval="30"/>
<field name="domain"
eval="[('state', '=', 'failed')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_maintenance_service_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_maintenance_service_form_domain_finished">
<field name="name">Finished</field>
<field name="sequence" eval="40"/>
<field name="domain"
eval="[('state', '=', 'finished')]"
pyson="1"/>
<field name="count" eval="True"/>
<field name="act_window" ref="act_maintenance_service_form"/>
</record>
<record model="ir.action.act_window.domain" id="act_maintenance_service_form_domain_all">
<field name="name">All</field>
<field name="sequence" eval="9999"/>
<field name="domain"></field>
<field name="act_window" ref="act_maintenance_service_form"/>
</record>
<record model="ir.ui.view" id="maintenance_line_view_form">
<field name="model">optical_equipment.maintenance.line</field>
<field name="type">form</field>
<field name="name">maintenance_line_form</field>
</record>
<record model="ir.ui.view" id="maintenance_line_view_tree">
<field name="model">optical_equipment.maintenance.line</field>
<field name="type">tree</field>
<field name="name">maintenance_line_tree</field>
</record>
<record model="ir.action.report" id="report_maintenance_service">
<field name="name">Maintenance Service</field>
<field name="model">optical_equipment.maintenance</field>
<field name="report_name">optical_equipment.maintenance</field>
<field name="report">optical_equipment/report/Maintenance_Service.fodt</field>
<field name="single" eval="True"/>
</record>
<record model="ir.action.keyword" id="report_maintenance_service_keyword">
<field name="keyword">form_print</field>
<field name="model">optical_equipment.maintenance,-1</field>
<field name="action" ref="report_maintenance_service"/>
</record>
<record model="ir.action.report" id="report_maintenance_timeline">
<field name="name">Time Line Maintenance Service</field>
<field name="model">optical_equipment_maintenance.service</field>
<field name="report_name">optical_equipment_maintenance.service</field>
<field name="report">optical_equipment/report/Maintenance_Timeline.fodt</field>
<field name="single" eval="True"/>
</record>
<record model="ir.action.keyword" id="report_maintenance_timeline_keyword">
<field name="keyword">form_print</field>
<field name="model">optical_equipment_maintenance.service,-1</field>
<field name="action" ref="report_maintenance_timeline"/>
</record>
<record model="ir.action.wizard" id="equipment_change_propietary_maintenance">
<field name="name">Change Propietary Maintenance</field>
<field name="wiz_name">optical_equipment.change_propietary_maintenance</field>
<field name="model">optical_equipment_maintenance.service</field>
</record>
<record model="ir.action.keyword" id="equipment_change_propietary_maintenance_keyword">
<field name="keyword">form_action</field>
<field name="model">optical_equipment_maintenance.service,-1</field>
<field name="action" ref="equipment_change_propietary_maintenance"/>
</record>
<menuitem parent="menu_equipment"
action="act_maintenance_service_form"
sequence="20"
id="menu_maintenance_service_form"/>
<menuitem parent="menu_maintenance_service_form"
action="act_maintenance_form"
sequence="30"
id="menu_maintenance_form"/>
</data>
</tryton>

View File

@ -24,7 +24,7 @@ this repository contains the full copyright notices and license terms. -->
<field name="model" search="[('model', '=', 'purchase.purchase')]"/>
</record>
<record model="ir.action.report" id="purchase.report_purchase">
<field name="active">False</field>
<field name="active" eval="False"/>
</record>
<record model="ir.action.report" id="report_purchase">
<field name="name">Purchase</field>

346
sale.py Normal file
View File

@ -0,0 +1,346 @@
from trytond.pool import Pool, PoolMeta
from trytond.model import ModelView, ModelSQL, fields
from trytond.modules.currency.fields import Monetary
from trytond.pyson import Eval, Bool, If, Get, Equal
from decimal import Decimal
from trytond.modules.product import price_digits
from trytond.transaction import Transaction
from trytond.model import Workflow
from trytond.modules.company.model import (
employee_field, set_employee, reset_employee)
from trytond.exceptions import UserError
from trytond.wizard import (
Button, StateAction, StateTransition, StateView, Wizard)
class Sale(metaclass=PoolMeta):
'Sale'
__name__ = 'sale.sale'
quote_number = fields.Char("Quote Number", readonly=True)
sale_type = fields.Selection([('maintenance', 'Maintenance'),
('equipments', 'Equipments'),
('replaces', 'Replaces')], "Sale Type", required=True,
states={'readonly': Eval('state') != 'draft'})
maintenance_type = fields.Selection([('', ""),
('preventive', 'Preventive'),
('corrective', 'Corrective')
], "Maintenance Type",
states={
'invisible': Eval('sale_type') != "maintenance",
'required': Eval('sale_type') == "maintenance",
'readonly': Eval('state') != 'draft'},
depends=['sale_type'])
#contract_ref = fields.Reference("Contract Base", selection='get_origin_contract',
#domain=[('party', '=', Eval('party')),
# ('state', '=', 'closed')],
# states={'invisible': (Eval('sale_type') != 'maintenance')},
# search_context={
# 'related_party': Eval('party'),
# },)
agended = fields.Boolean("Scheduling",states={
'invisible': (Eval('sale_type') != 'maintenance'),
'readonly': True})
@classmethod
def __setup__(cls):
super(Sale, cls).__setup__()
cls.contact.states['required']=True
cls.description.states['required']=True
cls.sale_date.states['required']=True
cls.payment_term.states['required']=True
cls._buttons.update({
'draft': {
'invisible': (Eval('state').in_(
['cancelled', 'draft'])) | (Eval('shipment_state') == 'sent')}})
cls._transitions |= set((
('draft', 'quotation'),
('quotation', 'confirmed'),
('confirmed', 'processing'),
('confirmed', 'draft'),
('processing', 'processing'),
('processing', 'done'),
('done', 'processing'),
('draft', 'cancelled'),
('quotation', 'cancelled'),
('quotation', 'draft'),
('cancelled', 'draft'),
('processing', 'draft')
))
@fields.depends('lines', 'sale_type', 'agended')
def on_chage_sale_type(self):
self.lines= []
if self.sale_type != "maintenance":
self.agended = False
@classmethod
def default_agended(self):
return False
# @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]
# def _get_shipment_sale(self, Shipment, key):
# values = {
# 'customer': self.shipment_party or self.party,
# 'delivery_address': self.shipment_address,
# 'company': self.company,
# 'sale_type': self.sale_type,
# 'service_maintenance_initial': True if self.sale_type != 'equipments' else False,
# }
# values.update(dict(key))
# return Shipment(**values)
@classmethod
def set_quote_number(cls, sales):
'''
Fill the number field with the sale sequence
'''
pool = Pool()
Config = pool.get('optical_equipment.configuration')
config = Config(1)
for sale in sales:
if config.equipment_sequence != None:
if not sale.quote_number:
try:
sale.quote_number = config.sale_quote_number.get()
cls.save(sales)
except UserError:
raise UserError(str('Validation Error'))
else:
raise UserError(gettext('optical_equipment.msg_not_sequence_quote'))
@classmethod
def copy(cls, sales, default=None):
if default is None:
default = {}
else:
default = default.copy()
default.setdefault('number', None)
default.setdefault('invoice_state', 'none')
default.setdefault('invoices_ignored', None)
default.setdefault('moves', None)
default.setdefault('shipment_state', 'none')
default.setdefault('quoted_by')
default.setdefault('confirmed_by')
return super(Sale, cls).copy(sales, default=default)
@classmethod
@ModelView.button
@Workflow.transition('quotation')
def quote(cls, sales):
pool = Pool()
AdvancePaymentCondition = pool.get('sale.advance_payment.condition')
for sale in sales:
sale.check_for_quotation()
cls.set_quote_number(sales)
for sale in sales:
sale.set_advance_payment_term()
cls.save(sales)
@classmethod
@ModelView.button
@Workflow.transition('confirmed')
@set_employee('confirmed_by')
def confirm(cls, sales):
pool = Pool()
Configuration = pool.get('sale.configuration')
transaction = Transaction()
context = transaction.context
cls.set_sale_date(sales)
cls.store_cache(sales)
config = Configuration(1)
MaintenanceService = pool.get('optical_equipment_maintenance.service')
for sale in sales:
if sale.sale_type == 'maintenance':
for line in sale.lines:
maintenanceService = MaintenanceService(
description=sale.description,
maintenance_type=sale.maintenance_type,
state_agended='no_agenda',
propietary=sale.party,
propietary_address=sale.shipment_address,
#contract_origin=sale.contract_ref if sale.contract_ref else None,
sale_origin=line,
sale_date=sale.sale_date,
state="draft"
)
maintenanceService.save()
sale.agended = True
sale.save()
cls.set_number(sales)
with transaction.set_context(
queue_scheduled_at=config.sale_process_after,
queue_batch=context.get('queue_batch', True)):
cls.__queue__.process(sales)
class SaleLine(metaclass=PoolMeta):
'SaleLine'
__name__ = 'sale.line'
product_equipment = fields.Boolean("Product Equipment")
#equipment = fields.Many2One('optical_equipment.equipment', "Equipment",
# domain=[('state', '=', 'registred'),
# ('product','=', Eval('product'))
# ],
# states={'invisible': If(~Eval('product_equipment'), True)},)
unit_digits = fields.Function(fields.Integer('Unit Digits'),
'on_change_with_unit_digits')
@classmethod
def __setup__(cls):
super(SaleLine, cls).__setup__()
cls.product.domain.append(
If(Eval('_parent_sale.sale_type') == 'maintenance',
[('type', '=', 'service'),
('maintenance_activity', '=', True)], []))
cls.product.domain.append(If(Eval('_parent_sale.sale_type') == 'replaces',
[('replacement', '=', True)], []))
def on_change_with_unit_digits(self, name=None):
if self.unit:
return self.unit.digits
return 2
@fields.depends('product', 'unit', 'quantity', 'sale',
'_parent_sale.party', '_parent_sale.sale_type', methods=['_get_tax_rule_pattern',
'_get_context_sale_price','on_change_with_amount'])
def on_change_product(self):
Product = Pool().get('product.product')
if not self.product:
self.product_equipment = False
self.unit = None
self.quantity = None
return
else:
party = None
if self.sale.sale_type == 'equipments':
self.quantity = 1
if self.sale and self.sale.party:
self.product_equipment = False
party = self.sale.party
# Set taxes before unit_price to have taxes in context of sale price
taxes = []
pattern = self._get_tax_rule_pattern()
for tax in self.product.customer_taxes_used:
if party and party.customer_tax_rule:
tax_ids = party.customer_tax_rule.apply(tax, pattern)
if tax_ids:
taxes.extend(tax_ids)
continue
taxes.append(tax.id)
if party and party.customer_tax_rule:
tax_ids = party.customer_tax_rule.apply(None, pattern)
if tax_ids:
taxes.extend(tax_ids)
self.taxes = taxes
category = self.product.sale_uom.category
if not self.unit or self.unit.category != category:
self.unit = self.product.sale_uom
self.unit_digits = self.product.sale_uom.digits
with Transaction().set_context(self._get_context_sale_price()):
self.unit_price = Product.get_sale_price([self.product],
self.quantity or 0)[self.product.id]
if self.unit_price:
self.unit_price = self.unit_price.quantize(
Decimal(1) / 10 ** self.__class__.unit_price.digits[1])
self.type = 'line'
self.amount = self.on_change_with_amount()
if self.product.equipment:
self.product_equipment = True
def get_move(self, shipment_type):
'''
Return moves for the sale line according to shipment_type
'''
pool = Pool()
Move = pool.get('stock.move')
if self.type != 'line':
return
if not self.product:
return
if self.product.type not in Move.get_product_types():
return
if (shipment_type == 'out') != (self.quantity >= 0):
return
quantity = (self._get_move_quantity(shipment_type)
- self._get_shipped_quantity(shipment_type))
quantity = self.unit.round(quantity)
if quantity <= 0:
return
if not self.sale.party.customer_location:
raise PartyLocationError(
gettext('sale.msg_sale_customer_location_required',
sale=self.sale.rec_name,
party=self.sale.party.rec_name))
move = Move()
move.quantity = quantity
move.uom = self.unit
move.product = self.product
move.from_location = self.from_location
move.to_location = self.to_location
move.state = 'draft'
move.company = self.sale.company
if move.on_change_with_unit_price_required():
move.unit_price = self.unit_price
move.currency = self.sale.currency
move.planned_date = self.planned_shipping_date
move.invoice_lines = self._get_move_invoice_lines(shipment_type)
move.origin = self
return move

51
sale.xml Normal file
View File

@ -0,0 +1,51 @@
<?xml version="1.0"?>
<!--This file file is part of Tryton. The COPYRIGHT file at the top level
of this repository contains the full copyright notices and license terms. -->
<tryton>
<record model="ir.ui.view" id="sale_view_tree">
<field name="model">sale.sale</field>
<field name="inherit" ref="sale.sale_view_tree"/>
<field name="name">sale_tree</field>
</record>
<record model="ir.ui.view" id="sale_view_form">
<field name="model">sale.sale</field>
<field name="inherit" ref="sale.sale_view_form"/>
<field name="name">sale_form</field>
</record>
<record model="ir.ui.view" id="product_view_list_sale_line">
<field name="model">product.product</field>
<field name="inherit" ref="sale.product_view_list_sale_line"/>
<field name="name">product_list_sale_line</field>
</record>
<record model="ir.sequence" id="sequence_quote_sale">
<field name="name">Sale Quote</field>
<field name="sequence_type" ref="sale.sequence_type_sale"/>
</record>
<record model="ir.action.report" id="sale.report_sale">
<field name="active" eval="False"/>
</record>
<record model="ir.action.report" id="report_sale">
<field name="name">Sale Equipments</field>
<field name="model">sale.sale</field>
<field name="report_name">sale.sale</field>
<field name="report">optical_equipment/report/Sale_Internal.fodt</field>
<field name="single" eval="True"/>
</record>
<record model="ir.action.keyword" id="report_sale_keyword">
<field name="keyword">form_print</field>
<field name="model">sale.sale,-1</field>
<field name="action" ref="report_sale"/>
</record>
<record model="ir.action.report" id="report_sale_internal">
<field name="name">Sale Equipments Internal</field>
<field name="model">sale.sale</field>
<field name="report_name">sale.sale</field>
<field name="report">optical_equipment/report/Sale.fodt</field>
<field name="single" eval="True"/>
</record>
<record model="ir.action.keyword" id="report_sale_internal_keyword">
<field name="keyword">form_print</field>
<field name="model">sale.sale,-1</field>
<field name="action" ref="report_sale_internal"/>
</record>
</tryton>

View File

@ -10,10 +10,17 @@ depends:
product_image
product_measurements
purchase
sale
xml:
equipment.xml
equipment.xml
calibration.xml
contract.xml
diary.xml
agended.xml
configuration.xml
maintenance.xml
party.xml
uom.xml
product.xml
purchase.xml
sale.xml

View File

@ -0,0 +1,16 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level
this repository contains the full copyright notices and license terms. -->
<form>
<label name="maintenance_service"/>
<field name="maintenance_service" colspan="3"/>
<newline/>
<label name="estimated_agended"/>
<field name="estimated_agended" colspan="3" widget="date"/>
<newline/>
<label name="estimated_agended" string="Hora:"/>
<field name="estimated_agended" colspan="3" widget="time"/>
<newline/>
<label name="technical"/>
<field name="technical" colspan="3"/>
</form>

View File

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tree>
<field name="diopter" expand="1"/>
<field name="dev_std" expand="1"/>
<field name="uncertain_type_A" expand="1"/>
<field name="uncertain_pattern" expand="1"/>
<field name="k_c_calibration" expand="1"/>
<field name="uncertain_U_b1" expand="1"/>
<field name="d_resolution" expand="1"/>
<field name="uncertain_U_b2_dig" expand="1"/>
<field name="uncertain_U_b2_ana" expand="1"/>
<field name="uncertain_combinated" expand="1"/>
<field name="uncertain_eff" expand="1"/>
<field name="t_student" expand="1"/>
<field name="uncertain_expanded" expand="1"/>
<field name="state" expand="1"/>
</tree>

View File

@ -0,0 +1,35 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form>
<label name="diopter"/>
<field name="diopter"/>
<label name="dev_std"/>
<field name="dev_std"/>
<label name="uncertain_type_A"/>
<field name="uncertain_type_A"/>
<label name="uncertain_pattern"/>
<field name="uncertain_pattern"/>
<label name="k_c_calibration"/>
<field name="k_c_calibration"/>
<label name="uncertain_U_b1"/>
<field name="uncertain_U_b1"/>
<label name="d_resolution"/>
<field name="d_resolution"/>
<label name="uncertain_U_b2_dig"/>
<field name="uncertain_U_b2_dig"/>
<label name="uncertain_U_b2_ana"/>
<field name="uncertain_U_b2_ana"/>
<label name="uncertain_combinated"/>
<field name="uncertain_combinated"/>
<label name="uncertain_eff"/>
<field name="uncertain_eff"/>
<label name="t_student"/>
<field name="t_student"/>
<label name="uncertain_expanded"/>
<field name="uncertain_expanded"/>
<label name="graph_dates"/>
<field name="graph_dates"/>
<label name="state"/>
<field name="state"/>
</form>

View File

@ -0,0 +1,16 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level
this repository contains the full copyright notices and license terms. -->
<form>
<label name="old_propietary"/>
<field name="old_propietary"/>
<newline/>
<field name="maintenance_service" colspan="3"/>
<newline/>
<label name="new_propietary"/>
<field name="new_propietary" colspan="3"/>
<label name="new_address"/>
<field name="new_address" colspan="3"/>
<label name="change_date"/>
<field name="change_date" colspan="3"/>
</form>

View File

@ -0,0 +1,44 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form>
<separator id="sequences" string="Sequences" colspan="4"/>
<newline/>
<label name="equipment_sequence"/>
<field name="equipment_sequence"/>
<newline/>
<label name="maintenance_sequence"/>
<field name="maintenance_sequence"/>
<newline/>
<label name="agended_sequence"/>
<field name="agended_sequence"/>
<newline/>
<label name="contract_sequence"/>
<field name="contract_sequence"/>
<newline/>
<label name="sale_quote_number"/>
<field name="sale_quote_number"/>
<newline/>
<separator id="separator_configuraton" colspan="4"/>
<separator id="environmental_conditions" string="Environmental Conditions" colspan="4"/>
<newline/>
<label name="temperature_min"/>
<field name="temperature_min"/>
<newline/>
<label name="temperature_max"/>
<field name="temperature_max"/>
<newline/>
<label name="temperature_uom"/>
<field name="temperature_uom"/>
<newline/>
<label name="moisture_min"/>
<field name="moisture_min"/>
<newline/>
<label name="moisture_max"/>
<field name="moisture_max"/>
<newline/>
<label name="moisture_uom"/>
<field name="moisture_uom"/>
<newline/>
</form>

24
view/diary_form.xml Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form col="6">
<label name="maintenance_service"/>
<field name="maintenance_service"/>
<label name="code"/>
<field name="code"/>
<newline/>
<notebook colspan="6">
<page string="Dates" id="dates_agended">
<label name="date_expected"/>
<field name="date_expected"/>
<label name="date_estimated"/>
<field name="date_estimated"/>
<label name="date_end"/>
<field name="date_end"/>
</page>
</notebook>
<label name="technical"/>
<field name="technical"/>
<label name="state"/>
<field name="state"/>
</form>

12
view/diary_tree.xml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tree>
<field name="code"/>
<field name="date_expected" widget="date"/>
<field name="date_expected" string="time" widget="time"/>
<field name="date_estimated" widget="date"/>
<field name="date_end" widget="date"/>
<field name="maintenance_service"/>
<field name="technical"/>
</tree>

View File

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form>
<label name="product"/>
<field name="product"/>
</form>

View File

@ -0,0 +1,6 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tree>
<field name="product"/>
</tree>

View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms.-->
<tree>
<field name="value_patterns" expand="1"/>
<field name="value_equipment" expand="1"/>
<field name="mistake" expand="1"/>
<field name="mistake_rate" expand="1"/>
</tree>

View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms.-->
<tree>
<field name="value_patterns" expand="1"/>
<field name="value_equipment" expand="1"/>
<field name="mistake" expand="1"/>
<field name="mistake_rate" expand="1"/>
</tree>

View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="/form/field[@name='maintenance_type']" position="after">
<label name="equipment"/>
<field name="equipment"/>
</xpath>
</data>

84
view/maintenance_form.xml Normal file
View File

@ -0,0 +1,84 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form>
<label name="company"/>
<field name="company"/>
<label name="code"/>
<field name="code"/>
<label name="propietary"/>
<field name="propietary"/>
<label name="propietary_address"/>
<field name="propietary_address"/>
<label name="maintenance_type"/>
<field name="maintenance_type"/>
<label name="equipment"/>
<field name="equipment"/>
<label name="service_maintenance"/>
<field name="service_maintenance"/>
<label name="equipment_calibrate"/>
<field name="equipment_calibrate" invisible="1"/>
<newline/>
<label name="description_activity"/>
<field name="description_activity" colspan="3"/>
<notebook colspan="6">
<page string="Preventive" id="preventive">
<label name="initial_operation"/>
<field name="initial_operation"/>
<label name="check_equipment"/>
<field name="check_equipment"/>
<label name="check_electric_system"/>
<field name="check_electric_system"/>
<label name="clean_int_ext"/>
<field name="clean_int_ext"/>
<label name="clean_eyes"/>
<field name="clean_eyes"/>
<label name="check_calibration"/>
<field name="check_calibration"/>
</page>
<page string="Corrective" id="corrective">
<field name="maintenance_lines"/>
</page>
<page string="Enviromental Conditions" id="enviromental_conditions_calibration">
<group col="4" colspan="4" id="conditions">
<label name="temperature_min"/>
<field name="temperature_min"/>
<newline/>
<label name="temperature_max"/>
<field name="temperature_max"/>
<label name="temperature_uom"/>
<field name="temperature_uom"/>
<newline/>
<label name="moisture_min"/>
<field name="moisture_min"/>
<newline/>
<label name="moisture_max"/>
<field name="moisture_max"/>
<label name="moisture_uom"/>
<field name="moisture_uom"/>
</group>
</page>
<page string="Calibration" id="calibration">
<label name="patterns_equipments"/>
<field name="patterns_equipments"/>
<newline/>
<group colspan="6" yexpand="1" id="lines_calibration">
<!-- <field name="lines_calibration"/> -->
<!-- <newline/> -->
<field name="calibration_total"/>
</group>
</page>
<page string="Graph" id="graph">
<field name="graph_calibration"/>
</page>
</notebook>
<newline/>
<label name="state"/>
<field name="state"/>
<group id="button">
<button name="in_progress"/>
<button name="finished"/>
<button name="samples"/>
<button name="calibrate"/>
</group>
</form>

View File

@ -0,0 +1,22 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form col="6">
<label name="line_replace"/>
<field name="line_replace"/>
<label name="line_maintenance_activity"/>
<field name="line_maintenance_activity"/>
<label name="maintenance"/>
<field name="maintenance"/>
<label name="replacement"/>
<field name="replacement"/>
<newline/>
<label name="maintenance_activity"/>
<field name="maintenance_activity"/>
<newline/>
<label name="unit"/>
<field name="unit"/>
<newline/>
<label name="quantity"/>
<field name="quantity"/>
</form>

View File

@ -0,0 +1,10 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms.-->
<tree>
<field name="line_replace" expand="1"/>
<field name="line_maintenance_activity" expand="1"/>
<field name="replacement" expand="1"/>
<field name="maintenance_activity" expand="1"/>
<field name="quantity"/>
</tree>

View File

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form>
<label name="number_sample"/>
<field name="number_sample"/>
<newline/>
<label name="value_patterns"/>
<field name="value_patterns"/>
<label name="value_equipment"/>
<field name="value_equipment"/>
<label name="mistake"/>
<field name="mistake"/>
<label name="mistake_rate"/>
<field name="mistake_rate"/>
<label name="product"/>
<field name="product" invisible="1"/>
<label name="maintenance" />
<field name="maintenance"/>
</form>

View File

@ -0,0 +1,68 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form col="6">
<label name="propietary"/>
<field name="propietary"/>
<label name="propietary_address"/>
<field name="propietary_address"/>
<label name="code"/>
<field name="code"/>
<label name="description"/>
<field name="description" colspan="3"/>
<label name="reference"/>
<field name="reference"/>
<label name="sale_origin"/>
<field name="sale_origin"/>
<label name="sale_date"/>
<field name="sale_date"/>
<label name="contract_origin"/>
<field name="contract_origin"/>
<label name="maintenance_type"/>
<field name="maintenance_type"/>
<newline/>
<label name="temperature_min"/>
<field name="temperature_min"/>
<label name="temperature_max"/>
<field name="temperature_max"/>
<label name="temperature_uom"/>
<field name="temperature_uom"/>
<label name="moisture_min"/>
<field name="moisture_min"/>
<label name="moisture_max"/>
<field name="moisture_max"/>
<label name="moisture_uom"/>
<field name="moisture_uom"/>
<notebook colspan="6">
<page string="General" id="general">
<label name="state_agended"/>
<field name="state_agended"/>
<label name="technical"/>
<field name="technical"/>
<label name="estimated_agended"/>
<field name="estimated_agended"/>
</page>
<page string="Lines Of Mantenaince" id="lines_maintenance">
<field name="lines"/>
</page>
<page string="Agendes" id="agendes">
<group col="-1" id="current_agended">
<label name="current_agended"/>
<field name="current_agended"/>
</group>
<newline/>
<field name="history_agended"/>
</page>
<page string="Other Info" id="other_info">
<label name="company"/>
<field name="company"/>
</page>
</notebook>
<newline/>
<label name="state"/>
<field name="state"/>
<group id="button">
<button name="in_progress"/>
<button name="finished"/>
</group>
</form>

View File

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms.-->
<tree>
<field name="code"/>
<field name="maintenance_type"/>
<field name="propietary"/>
<field name="propietary_address"/>
<field name="sale_origin"/>
<field name="sale_date"/>
<field name="technical"/>
<field name="lines" string="# Equipments"/>
</tree>

13
view/maintenance_tree.xml Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms.-->
<tree>
<field name="code"/>
<field name="maintenance_type" expand="0"/>
<field name="service_maintenance" expand="1"/>
<field name="propietary"/>
<field name="propietary_address"/>
<field name="equipment"/>
<field name="state"/>
<button name="finished"/>
</tree>

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="//field[@name='name']" position="after">
<field name="attributes_name" expand="1"/>
</xpath>
</data>

View File

@ -0,0 +1,16 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level
this repository contains the full copyright notices and license terms. -->
<form>
<label name="maintenance_service"/>
<field name="maintenance_service"/>
<newline/>
<label name="estimated_agended"/>
<field name="estimated_agended" colspan="3" widget="date"/>
<newline/>
<label name="estimated_agended" string="Hora:"/>
<field name="estimated_agended" colspan="3" widget="time"/>
<newline/>
<label name="technical"/>
<field name="technical"/>
</form>

20
view/sale_form.xml Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="//label[@name='number']" position="before">
<label name="quote_number"/>
<field name="quote_number"/>
</xpath>
<xpath expr="//field[@name='reference']" position="after">
<newline/>
<label name="sale_type"/>
<field name="sale_type"/>
<label name="maintenance_type"/>
<field name="maintenance_type"/>
<label name="agended"/>
<field name="agended"/>
<!-- <label name="contract_ref"/> -->
<!-- <field name="contract_ref"/> -->
</xpath>
</data>

11
view/sale_tree.xml Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="//field[@name='number']" position="before">
<field name="quote_number"/>
</xpath>
<xpath expr="//field[@name='number']" position="replace">
<field name="number"/>
</xpath>
</data>

View File

@ -3,10 +3,12 @@
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="/form/notebook/page[@id='general']/group[@id='checkboxes']" position="inside">
<newline/>
<label name="equipment"/>
<field name="equipment"/>
<label name="replacement"/>
<field name="replacement"/>
<newline/>
<label name="maintenance_activity"/>
<field name="maintenance_activity"/>
</xpath>