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 class Contract(ModelSQL, ModelView): 'Contracts' __name__ = 'sale.subscription.contract' 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, help="The party who subscribes.") contact = fields.Many2One( 'party.contact_mechanism', "Contact") 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) start_date = fields.Date( "Start Date", required=False,) 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', } ) state = fields.Selection([ ('draft', "Draft"), ('quotation', "Quotation"), ('running', "Running"), ('closed', "Closed"), ('cancelled', "Cancelled"), ], "State", readonly=False, required=False, sort=False, help="The current state of the subscription.") contract = fields.Many2One('sale.subscription', "Contract") prorogues = fields.Many2Many('sale.subscription-sale.subscription.contract', 'contract', 'subscription', 'Prorrogation') equipments = fields.Many2Many('sale.subscription-optical_equipment.equipment', 'subscription', 'equipment', "Equipments") @staticmethod def default_company(): return Transaction().context.get('company') class CreateNextProrogue(ModelView): 'Create Next Prorogue' __name__ = 'sale.create.prorogue.next' initial_contract = fields.Many2One('sale.subscription.contract', "Initial Contract") party = fields.Many2One('party.party', "Party", required=True, help="The party who subscribes.") contact = fields.Many2One( 'party.contact_mechanism', "Contact") 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) 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), ]) invoice_start_date = fields.Date("Invoice Start Date", required=True, help='Billing start date') equipments = fields.Many2Many('sale.subscription-optical_equipment.equipment', 'subscription', 'equipment', "Equipments", required=True, domain=[['OR', ('state', '=', 'registred'), ('state', '=', 'uncontrated')] ]) @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.invoice_recurrence = contract.invoice_recurrence.id self.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 = [] class CreateProrogue(Wizard): 'Create Prorogue' __name__ = 'sale.create.prorogue' start = StateView('sale.create.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('sale.create.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='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, ) subscription.save() self.initial_contract.prorogues.append(subscription.id) self.initial_contract.save() class CreateInitialContract(ModelView): 'Create Initial Contract' __name__ = 'sale.create.contract.initial' 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) start_date = fields.Date("Start Date", required=True) end_date = fields.Date("End Date", required=True) 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')] ]) @classmethod def default_start_date(cls): pool = Pool() Date = pool.get('ir.date') return Date.today() @classmethod @fields.depends(methods=['default_start_date']) def default_invoice_start_date(self): invoice_start_date = self.default_start_date() return invoice_start_date class CreateContract(Wizard): 'Create Contract' __name__ = 'sale.create.contract' start = StateView('sale.create.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('sale.create.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('sale.subscription.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, ) subscription.save() self._create_contract_base(a, subscription.id) 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') ), }) 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 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-sale.subscription.contract' contract = fields.Many2One('sale.subscription.contract', 'Contract', select=True) subscription = fields.Many2One('sale.subscription', 'Subscription', select=True)