455 lines
14 KiB
Python
455 lines
14 KiB
Python
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.exceptions import UserError
|
|
from trytond.transaction import Transaction
|
|
from trytond.wizard import Button, StateAction, StateView, Wizard
|
|
|
|
from trytond.modules.currency.fields import Monetary
|
|
from trytond.modules.product import price_digits
|
|
|
|
import datetime
|
|
from datetime import timedelta, date
|
|
from trytond.i18n import gettext
|
|
|
|
|
|
class Cron(metaclass=PoolMeta):
|
|
__name__ = 'ir.cron'
|
|
|
|
@classmethod
|
|
def __setup__(cls):
|
|
super().__setup__()
|
|
cls.method.selection.append((
|
|
'optical_equipment.contract|contract_expiration',
|
|
'Contract Expiration'
|
|
))
|
|
|
|
|
|
class Contract(Workflow, ModelSQL, ModelView):
|
|
'Contracts'
|
|
__name__ = 'optical_equipment.contract'
|
|
_rec_name = 'number'
|
|
_order_name = 'number'
|
|
|
|
company = fields.Many2One(
|
|
'company.company',
|
|
'Company',
|
|
required=True,
|
|
states={
|
|
'readonly': (Eval('state') != 'draft') | Eval('party', True),
|
|
},
|
|
help='Make the subscription belong to the company.',
|
|
)
|
|
number = fields.Char(
|
|
'Number', readonly=True,
|
|
help='The main identification of the subscription.'
|
|
)
|
|
reference = fields.Char(
|
|
'Reference',
|
|
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.',
|
|
)
|
|
equipment = fields.Many2One('optical_equipment.equipment', 'Equipment')
|
|
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'},
|
|
)
|
|
|
|
current_equipments = fields.Many2Many(
|
|
'optical_equipment.contract-optical_equipment.equipment',
|
|
'contract',
|
|
'equipment',
|
|
'Current Equipments',
|
|
states={'readonly': Eval('state') != 'draft'},
|
|
)
|
|
history_equipments = fields.One2Many(
|
|
'optical_equipment.equipment',
|
|
'contract',
|
|
'Equipments',
|
|
states={'readonly': Eval('state') != 'draft'},
|
|
)
|
|
currency = fields.Many2One('currency.currency', 'Currency', required=True)
|
|
price_contract = Monetary(
|
|
'Price Contract',
|
|
digits=price_digits,
|
|
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'),
|
|
('cancelled', 'draft'),
|
|
}
|
|
cls._buttons.update(
|
|
{
|
|
'draft': {
|
|
'invisible':
|
|
Eval('state').in_(['draft', 'closed'])
|
|
},
|
|
'running': {
|
|
'invisible':
|
|
Eval('state').in_(['cancelled', 'running'])
|
|
},
|
|
'closed': {
|
|
'invisible':
|
|
Eval('state').in_(['draft', 'cancelled'])
|
|
},
|
|
'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 is not 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
|
|
def contract_expiration(cls):
|
|
contracts_to_expire = cls.search(
|
|
[('state', '=', 'running'), ('end_date', '<=', date.today())]
|
|
)
|
|
|
|
if contracts_to_expire != []:
|
|
for contract in contracts_to_expire:
|
|
cls.closed([contract])
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('draft')
|
|
def draft(cls, contracts):
|
|
contract = contracts[0]
|
|
for equipment in contract.current_equipments:
|
|
equipment.state = 'uncontrated'
|
|
equipment.contract_history += (contract.id,)
|
|
equipment.save()
|
|
contract.save()
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('closed')
|
|
def closed(cls, contracts):
|
|
contract = contracts[0]
|
|
for equipment in contract.current_equipments:
|
|
equipment.state = 'uncontrated'
|
|
equipment.save()
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('running')
|
|
def running(cls, contracts):
|
|
contract = contracts[0]
|
|
for equipment in contract.current_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):
|
|
contract = contracts[0]
|
|
for equipment in contract.current_equipments:
|
|
equipment.state = 'uncontrated'
|
|
equipment.save()
|
|
|
|
|
|
class ContractMaintenanceServices(ModelSQL):
|
|
'Contract - Maintenance Services'
|
|
__name__ = 'optical_equipment_maintenance.service-equipment.contract'
|
|
|
|
maintenance_services = fields.Many2One(
|
|
'optical_equipment_maintenance.service',
|
|
'Maintenance Service',
|
|
)
|
|
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',
|
|
)
|
|
contract = fields.Many2One(
|
|
'optical_equipment.contract',
|
|
'Contract',
|
|
)
|
|
|
|
|
|
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,
|
|
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', required=True
|
|
)
|
|
|
|
@staticmethod
|
|
def default_company():
|
|
return Transaction().context.get('company')
|
|
|
|
@staticmethod
|
|
def default_currency():
|
|
Company = Pool().get('company.company')
|
|
if Transaction().context.get('company'):
|
|
company = Company(Transaction().context['company'])
|
|
return company.currency.id
|
|
|
|
@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.customer_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')
|
|
|
|
def default_start(self, fields):
|
|
if self.record:
|
|
default = {
|
|
'party': self.record.propietary.id,
|
|
'invoice_address': self.record.propietary_address.id,
|
|
'unit_price': (
|
|
self.record.sale_origin.amount
|
|
if self.record.sale_origin.__name__ == 'sale.line'
|
|
else self.record.sale_origin.total_amount
|
|
),
|
|
}
|
|
return default
|
|
|
|
@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,
|
|
unit_price=self.start.unit_price,
|
|
)
|
|
|
|
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.history_equipments += tuple(equipments)
|
|
contract.current_equipments = equipments
|
|
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.state = 'draft'
|
|
contract.price_contract = dates['unit_price']
|
|
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,
|
|
current_equipments=equipments,
|
|
state='draft',
|
|
price_contract=dates['unit_price'],
|
|
)
|
|
contract.save()
|