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 if contract[0].contract and contract[0].prorogues == (): 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(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)