trytondo-optical_equipment/subscription.py

629 lines
25 KiB
Python

from trytond.pool import Pool, PoolMeta
from trytond.model import (
ModelSQL, ModelView, Workflow, fields)
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(ModelSQL, ModelView):
'Contracts'
__name__ = 'optical_equipment.contract'
company = fields.Many2One(
'company.company', "Company", readonly=True, required=True, select=True,
states={
'readonly': (Eval('state') != 'draft') | Eval('party', True),
},help="Make the subscription belong to the company.")
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", readonly=True, required=True,
help="The party who subscribes.")
contact = fields.Many2One('party.contact_mechanism', "Contact", readonly=True)
invoice_address = fields.Many2One('party.address', 'Invoice Address', readonly=True,
required=True, domain=[('party', '=', Eval('party'))])
invoice_recurrence = fields.Many2One(
'sale.subscription.recurrence.rule.set', "Invoice Recurrence", readonly=True,
required=True)
start_date = fields.Date("Start Date", readonly=True, required=False,)
end_date = fields.Date(
"End Date", readonly=True,
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',
}
)
state = fields.Selection([
('draft', "Draft"),
('quotation', "Quotation"),
('running', "Running"),
('closed', "Closed"),
('cancelled', "Cancelled"),
], "State", readonly=True, required=False, sort=False,
help="The current state of the subscription.")
contract = fields.Many2One('sale.subscription', "Contract", readonly=True)
prorogues = fields.Many2Many('sale.subscription-optical_equipment.contract', 'contract',
'subscription', 'Prorrogation')
equipments = fields.Many2Many('optical_equipment.contract-optical_equipment.equipment', 'contract', 'equipment',
"Equipments", readonly=True,
domain=[['OR',
('state', '=', 'registred'),
('state', '=', 'uncontrated')]
])
@classmethod
def __setup__(cls):
super(Contract, cls).__setup__()
cls._buttons.update({
'quotation': {'invisible': Eval('state').in_(['quotation', 'running', 'closed', 'cancelled'])},
'run': {'invisible': Eval('state').in_(['draft', 'running', 'closed', 'cancelled'])}
})
@staticmethod
def default_company():
return Transaction().context.get('company')
@staticmethod
def default_state():
return 'draft'
@classmethod
@ModelView.button
def quotation(self, contract):
#raise UserError(str(self))
pool = Pool()
Subscription = pool.get('sale.subscription')
#raise UserError(str((subscription[0].equipments)))
for equipment in contract[0].equipments:
if equipment.state == "contrated":
raise UserError(str("El equipo"+str(equipment.number) +
"No puede pertencer a este contrato porque ya se encuentra en un contrato"))
else:
continue
#raise UserError(str((contract[0].prorogues)))
if contract[0].contract and contract[0].prorogues == ():
#raise UserError(str(contract[0].contract))
Subscription.quote([contract[0].contract])
Subscription.run([contract[0].contract])
else:
IdProrogues = set()
for ide in contract[0].prorogues:
IdProrogues.add(ide.id)
subscription = Subscription.search([('state', '=', 'draft'),
('id', 'in', IdProrogues)])
raise UserError(str(subscription))
#raise UserError(str(list(contract[0].prorogues)))
raise UserError(str(list(contract[0].prorogues).find(['state', '=', 'draft'])))
@classmethod
@ModelView.button
def run(cls, subscription):
pool = Pool()
Subscription = pool.get('sale.subscription')
if subscription.state == 'quotation':
Subscription.run(subscription)
elif subscription.state == 'draft':
for equipment in cls.equipments:
if equipment.state == "contrated":
raise UserError(str("El equipo"+str(equipment.number) +
"No puede pertencer a este contrato porque ya se encuentra en un contrato"))
else:
continue
Subscription.quotation(subscription)
Subscription.run(subscription)
Subscription.quotation(subscription)
class CreateInitialContract(ModelView):
'Create Initial Contract'
__name__ = 'optical_equipment_contract.initial'
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),
])
invoice_recurrence = fields.Many2One('sale.subscription.recurrence.rule.set',
"Invoice Recurrence",required=True)
invoice_start_date = fields.Date("Invoice Start Date", required=True,
help='Billing start date')
service = fields.Many2One('sale.subscription.service', "Service", required=True)
quantity = fields.Float("Quantity", digits='unit', required=True)
unit_price = Monetary("Unit Price", currency='currency',
digits=price_digits,required=True
)
equipments = fields.Many2Many('sale.subscription-optical_equipment.equipment', 'subscription',
'equipment', "Equipments", required=True,
domain=[['OR',
('state', '=', 'registred'),
('state', '=', 'uncontrated')],
('propietary', '=', Eval('party'))
])
@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()
@classmethod
def default_quantity(self):
return 1
@fields.depends('invoice_recurrence')
def on_change_invoice_recurrence(self):
if self.invoice_recurrence.rules[0].freq == "yearly":
pool = Pool()
Date = pool.get('ir.date')
self.end_date = Date.today() + timedelta(days=365)
elif self.invoice_recurrence == None:
self.end_date = None
@classmethod
@fields.depends(methods=['default_start_date'])
def default_invoice_start_date(self):
invoice_start_date = self.default_start_date()
return invoice_start_date
@fields.depends('party')
def on_change_party(self):
if self.party:
self.invoice_address = self.party.address_get(type='invoice')
class CreateContract(Wizard):
'Create Contract'
__name__ = 'sale.create.contract'
start = StateView('optical_equipment_contract.initial',
'optical_equipment.create_contract_view_form',[
Button('Cancel', 'end', 'tryton-cancel'),
Button('Create', 'create_contract', 'tryton-ok', default=True),
])
create_contract = StateAction('sale_subscription.act_subscription_form')
done_ = StateView('optical_equipment_contract.initial',
'optical_equipment.create_contract_view_form',[
Button('Done', 'end', 'tryton-cancel'),
])
@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,
payment_term=self.start.payment_term,
invoice_address=self.start.invoice_address,
invoice_recurrence=self.start.invoice_recurrence,
invoice_start_date=self.start.invoice_start_date,
service=self.start.service,
quantity=self.start.quantity,
unit_price=self.start.unit_price,
equipments=self.start.equipments)
def _create_contract_base(self,dates, subscription):
pool = Pool()
ContractBase = pool.get('optical_equipment.contract')
a = self._subscription_start
contractBase = ContractBase(
state='draft',
party=a['party'],
invoice_address=a['invoice_address'],
start_date=a['start_date'],
end_date=a['end_date'],
invoice_recurrence=a['invoice_recurrence'],
contact=a['contact'],
contract=subscription,
equipments=a['equipments']
)
contractBase.save()
def do_create_contract(self, action):
pool = Pool()
Subscription = pool.get('sale.subscription')
SubscriptionLine = pool.get('sale.subscription.line')
a = self._subscription_start
equipments_to_subscription=self.start.equipments
subscription_lines = [SubscriptionLine(
start_date=a['start_date'],
end_date=a['end_date'],
consumption_recurrence=a['invoice_recurrence'],
service=a['service'],
unit=a['service'].product.default_uom,
quantity=a['quantity'],
unit_price=a['unit_price']
)]
subscription = Subscription(
state='draft',
type='contract',
party=a['party'],
invoice_address=a['invoice_address'],
payment_term=a['payment_term'],
start_date=a['start_date'],
end_date=a['end_date'],
invoice_recurrence=a['invoice_recurrence'],
invoice_start_date=a['invoice_start_date'],
contact=a['contact'],
invoice_party=a['party'],
lines=subscription_lines,
equipments=equipments_to_subscription,
)
antes = subscription.id
subscription.save()
despues = subscription.id
andes = str(antes) + str(despues)
self._create_contract_base(a, subscription)
class CreateNextProrogue(ModelView):
'Create Next Prorogue'
__name__ = 'optical_equipment_prorogue.next'
party = fields.Many2One('party.party', "Party", required=True,
help="The party who subscribes.")
initial_contract = fields.Many2One('optical_equipment.contract', "Initial Contract", required=True,
domain=[('party', '=', Eval('party')),
('state', '=', "closed")],
depends=['party'])
contact = fields.Many2One('party.contact_mechanism', "Contact", required=True,
domain=[('party', '=', Eval('party'))])
invoice_address = fields.Many2One('party.address', 'Invoice Address',
required=True, domain=[('party', '=', Eval('party'))])
invoice_recurrence = fields.Many2One('sale.subscription.recurrence.rule.set', "Invoice Recurrence",
required=True)
payment_term = fields.Many2One(
'account.invoice.payment_term', "Payment Term")
start_date = fields.Date("Start Date", required=True,)
end_date = fields.Date("End Date", required=True,
domain=['OR',
('end_date', '>=', If(
Bool(Eval('start_date')),
Eval('start_date', datetime.date.min),
datetime.date.min)),
('end_date', '=', None),
],
depends=['invoice_start_date'])
invoice_start_date = fields.Date("Invoice Start Date", required=True,
help='Billing start date',
depends=['start_date'])
service = fields.Many2One('sale.subscription.service', "Service", required=True)
quantity = fields.Float("Quantity", digits='unit', required=True)
unit_price = Monetary("Unit Price", currency='currency',
digits=price_digits,required=True
)
equipments = fields.Many2Many('optical_equipment.contract-optical_equipment.equipment', 'contract',
'equipment', "Equipments", required=True,
domain=[['OR',
('state', '=', 'registred'),
('state', '=', 'uncontrated')],
('propietary', '=', Eval('party'))
])
@fields.depends('party', 'contact')
def on_change_party(self):
self.contact = None
self.initial_contract = None
@fields.depends('initial_contract', 'party', 'contact', 'invoice_address',
'invoice_recurrence', 'start_date', 'end_date',
'equipments')
def on_change_initial_contract(self):
if self.initial_contract:
contract = self.initial_contract
self.party = contract.party.id
self.contact = contract.contact.id
self.invoice_address = contract.invoice_address.id
self.start_date = contract.end_date
self.invoice_start_date = contract.end_date
self.equipments = contract.equipments
else:
self.party = None
self.contact = None
self.invoice_address = None
self.invoice_recurrence = None
self.start_date = None
self.equipments = []
@fields.depends('invoice_recurrence', 'start_date')
def on_change_invoice_recurrence(self):
if self.invoice_recurrence and self.invoice_recurrence.rules[0].freq == "yearly":
#pool = Pool()
#Date = pool.get('ir.date')
self.end_date = self.start_date + timedelta(days=365)
#self.end_date = Date.today() + timedelta(days=365)
elif self.invoice_recurrence == None:
self.end_date = None
@fields.depends('invoice_start_date', 'start_date')
def on_change_start_date(self):
self.invoice_start_date = self.start_date
@classmethod
def default_quantity(self):
return 1
class CreateProrogue(Wizard):
'Create Prorogue'
__name__ = 'optical_equipment.prorogue'
start = StateView('optical_equipment_prorogue.next',
'optical_equipment.create_prorogue_view_form',
[Button('Cancel', 'end', 'tryton-cancel'),
Button('Create', 'create_prorogue', 'tryton-ok', default=True),
])
create_prorogue = StateAction('sale_subscription.act_subscription_form')
done_ = StateView('optical_equipment_prorogue.next',
'optical_equipment.create_prorogue_view_form',[
Button('Done', 'end', 'tryton-cancel'),
])
@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,
payment_term=self.start.payment_term,
invoice_address=self.start.invoice_address,
invoice_recurrence=self.start.invoice_recurrence,
invoice_start_date=self.start.invoice_start_date,
service=self.start.service,
quantity=self.start.quantity,
unit_price=self.start.unit_price,
equipments=self.start.equipments)
def do_create_prorogue(self, action):
pool = Pool()
Subscription = pool.get('sale.subscription')
SubscriptionLine = pool.get('sale.subscription.line')
a = self._subscription_start
equipments_to_subscription=self.start.equipments
subscription_lines = [SubscriptionLine(
start_date=a['start_date'],
end_date=a['end_date'],
consumption_recurrence=a['invoice_recurrence'],
service=a['service'],
unit=a['service'].product.default_uom,
quantity=a['quantity'],
unit_price=a['unit_price']
)]
subscription = Subscription(
state='draft',
type='prorrogation',
party=a['party'],
invoice_address=a['invoice_address'],
payment_term=a['payment_term'],
start_date=a['start_date'],
end_date=a['end_date'],
invoice_recurrence=a['invoice_recurrence'],
invoice_start_date=a['invoice_start_date'],
contact=a['contact'],
invoice_party=a['party'],
lines=subscription_lines,
equipments=equipments_to_subscription,
)
subscription.save()
IdInitialContract = self.start.initial_contract.id
pool = Pool()
Contract = pool.get('optical_equipment.contract')
contract = Contract.search(['id', '=', IdInitialContract])[0]
contract.start_date = a['start_date']
contract.end_date = a['end_date']
contract.invoice_address = a['invoice_address']
contract.contact = a['contact']
contract.invoice_recurrence = a['invoice_recurrence']
contract.state = subscription.state
#raise UserError(str(contract.id))
contract.prorogues += (subscription.id,)
contract.equipments = equipments_to_subscription
contract.save()
class Subscription(metaclass=PoolMeta):
__name__ = 'sale.subscription'
type = fields.Selection([
('contract', "Main"),
('prorrogation', "Extension"),
], "Type", select=True, required=True,
states={
'readonly': ((Eval('state') != 'draft')
| Eval('context', {}).get('type')
),
})
prorogues = fields.Many2Many('sale.subscription-optical_equipment.contract', 'contract','subscription',
'Prorrogation')
equipments = fields.Many2Many('sale.subscription-optical_equipment.equipment', 'subscription',
'equipment', "Equipments",
domain=[['OR',
('state', '=', 'registred'),
('state', '=', 'uncontrated')]
])
@classmethod
@ModelView.button
@Workflow.transition('running')
@set_employee('run_by')
def run(cls, subscriptions):
pool = Pool()
Line = pool.get('sale.subscription.line')
lines = []
pool = Pool()
Equipments = pool.get('optical_equipment.equipment')
for subscription in subscriptions:
if not subscription.next_invoice_date:
subscription.next_invoice_date = (
subscription.compute_next_invoice_date())
for line in subscription.lines:
if (line.next_consumption_date is None
and not line.consumed_until):
line.next_consumption_date = (
line.compute_next_consumption_date())
lines.extend(subscription.lines)
for equipment in subscription.equipments:
equipment.state = "contrated"
equipment.save()
Line.save(lines)
cls.save(subscriptions)
class CreateSubscriptionInvoice(Wizard):
"Create Subscription Invoice"
__name__ = 'sale.subscription.create_invoice'
start = StateView(
'sale.subscription.create_invoice.start',
'sale_subscription.create_invoice_start_view_form', [
Button("Cancel", 'end', 'tryton-cancel'),
Button("Create", 'create_', 'tryton-ok', default=True),
])
create_ = StateTransition()
def generate_invoice(self, date=None):
pool = Pool()
Date = pool.get('ir.date')
Configuration = pool.get('account.configuration')
Config = Configuration(1)
Journals = pool.get('account.journal')
Invoice = pool.get('account.invoice')
InvoiceLine = pool.get('account.invoice.line')
invoice_lines = []
if date is None:
date = Date.today()
for subscription in self.records:
for line in subscription.lines:
invoice_lines.append(
InvoiceLine(
origin=line,
product=line.service,
account=line.service.product.account_revenue_used,
quantity=line.quantity,
unit=line.unit,
unit_price=line.unit_price,
)
)
invoice = Invoice(
type='out',
journal=Journals.search(['type', '=', 'revenue'])[0],
account=Config.default_account_receivable,
party=subscription.party,
invoice_date=date,
invoice_address=subscription.invoice_address,
lines=invoice_lines,
)
invoice.save()
def transition_create_(self):
pool = Pool()
Subscription = pool.get('sale.subscription')
self.generate_invoice(date=self.start.date)
return 'end'
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 SubscriptionEquipment(ModelSQL):
'Optical Equipment - Subscription'
__name__ = 'sale.subscription-optical_equipment.equipment'
subscription = fields.Many2One('sale.subscription', 'Subscription', select=True)
equipment = fields.Many2One('optical_equipment.equipment', 'Equipment', select=True)
class ContractSupscription(ModelSQL):
'Prorrogation to the Contract'
__name__='sale.subscription-optical_equipment.contract'
contract = fields.Many2One('optical_equipment.contract', 'Contract', select=True)
subscription = fields.Many2One('sale.subscription', 'Subscription', select=True)