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 from decimal import Decimal from trytond.modules.product import price_digits from trytond.transaction import Transaction from trytond.exceptions import UserError from trytond.wizard import ( Button, StateAction, StateTransition, StateView, Wizard) class CreateSubscriptionStart(ModelView): 'Create Subscription Start' __name__ = 'sale.create.subscription.start' 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", help='Billing start date') service = fields.Many2One('sale.subscription.service', "Service") quantity = fields.Float("Quantity", digits='unit') unit_price = Monetary("Unit Price", currency='currency', digits=price_digits, ) @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 CreateSubscription(Wizard): 'Create Subscription' __name__ = 'sale.create.subscription' start = StateView('sale.create.subscription.start', 'optical_equipment.create_subscription_view_form',[ Button('Cancel', 'end', 'tryton-cancel'), Button('Create', 'create_subscription', 'tryton-ok', default=True), ]) create_subscription = StateAction('sale_subscription.act_subscription_form') done_ = StateView('sale.create.subscription.start', 'optical_equipment.create_subscription_view_form',[ Button('Done', 'end', 'tryton-cancel'), ]) @property def _subscription_start(self): return dict(start_date=self.start.start_date, end_date=self.start.end_date, 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) def _equipments_to_subscription(self): sale = self.records[0] equipments_to_subscription = [] for line in sale.lines: if line.product_equipment: equipments_to_subscription.append(line.equipment) return equipments_to_subscription def do_create_subscription(self, action): pool = Pool() Subscription = pool.get('sale.subscription') SubscriptionLine = pool.get('sale.subscription.line') sale = self.records[0] a = self._subscription_start equipments_to_subscription=self._equipments_to_subscription() 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( start_date=a['start_date'], end_date=a['end_date'], invoice_recurrence=a['invoice_recurrence'], invoice_start_date=a['invoice_start_date'], party=sale.party.id, contact=sale.contact.id if sale.contact else None, invoice_party=sale.invoice_party.id if sale.invoice_party else None, invoice_address=sale.invoice_address.id, payment_term=sale.payment_term.id if sale.payment_term else None, lines=subscription_lines, equipments=equipments_to_subscription, ) subscription.save() return 'done_' class SaleLine(metaclass=PoolMeta): 'SaleLine' __name__ = 'sale.line' product_equipment = fields.Boolean("Product Equipment") equipment = fields.Many2One('optical_equipment.equipment', "Equipment", domain=[('state', '=', 'registred'), (Eval('product'), '=', Eval('_parent_sale.line.product'))], states={'invisible': If(~Eval('product_equipment'), True)},) address_equipment = fields.Many2One('party.address', "Direccion") unit_digits = fields.Function(fields.Integer('Unit Digits'), 'on_change_with_unit_digits') def on_change_with_unit_digits(self, name=None): if self.unit: return self.unit.digits return 2 @fields.depends('equipment', 'sale', '_parent_sale.shipment_address', methods=['on_change_product']) def on_change_equipment(self): if self.equipment: self.product = self.equipment.product.id self.address_equipment = self.sale.shipment_address.id self.on_change_product() else: self.address_equipment = None self.product = None self.unit= None self.quantity = None self.unit_price = None self.amount = None self.on_change_product() @fields.depends('product_equipment', methods=['on_change_equipment']) def on_change_product_equipment(self): if self.product_equipment == False: self.equipment = None self.on_change_equipment() @fields.depends('product', 'unit', 'quantity', 'sale', '_parent_sale.party',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 return party = None 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() self.product_equipment = True @classmethod @ModelView.button def process(cls, sales): states = {'confirmed', 'processing', 'done'} sales = [s for s in sales if s.state in states] cls.lock(sales) cls._process_invoice(sales) cls._process_shipment(sales) cls._process_invoice_shipment_states(sales) cls._process_state(sales) @classmethod def view_attributes(cls): return super(SaleLine, cls).view_attributes() + [ ('//page[@id="equipment"]', 'states', { 'invisible': ~Eval('product_equipment', True), })]