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, Get from decimal import Decimal from trytond.modules.product import price_digits from trytond.transaction import Transaction from trytond.model import Workflow from trytond.modules.company.model import ( employee_field, set_employee, reset_employee) from trytond.exceptions import UserError from trytond.wizard import ( Button, StateAction, StateTransition, StateView, Wizard) class Sale(metaclass=PoolMeta): 'Sale' __name__ = 'sale.sale' agended = fields.Boolean("Scheduling") sale_type = fields.Selection([('maintenance', 'Maintenance'), ('equipments', 'Equipos'), ('replaces', 'Replaces')], "Sale Type", required=True) @classmethod @ModelView.button @Workflow.transition('confirmed') @set_employee('confirmed_by') def confirm(cls, sales): pool = Pool() Configuration = pool.get('sale.configuration') transaction = Transaction() context = transaction.context cls.set_sale_date(sales) cls.store_cache(sales) config = Configuration(1) MaintenanceService = pool.get('optical_equipment.maintenance.service') for sale in sales: for line in sale.lines: maintenanceService = MaintenanceService( maintenance_type='preventive', state_agended='no_agenda', propietary=cls.party, propietary_address=cls.shipment_address, state="draft" ) #raise UserError(str((maintenanceService))) maintenanceService.save() cls.agended = True sale.save() with transaction.set_context( queue_scheduled_at=config.sale_process_after, queue_batch=context.get('queue_batch', True)): cls.__queue__.process(sales) class SaleLine(metaclass=PoolMeta): 'SaleLine' __name__ = 'sale.line' product_equipment = fields.Boolean("Product Equipment") equipment = fields.Many2One('optical_equipment.equipment', "Equipment", domain=[('state', '=', 'registred'), ('product','=', Eval('product')) ], states={'invisible': If(~Eval('product_equipment'), True)},) equipment_serial = fields.Char('Serial',states={'readonly': True, 'invisible': If(~Eval('product_equipment'), True)}, depends=['product_equipment']) address_equipment = fields.Many2One('party.address', "Direccion") unit_digits = fields.Function(fields.Integer('Unit Digits'), 'on_change_with_unit_digits') @classmethod def __setup__(cls): super(SaleLine, cls).__setup__() cls.quantity.states['readonly'] = If(Eval('product_equipment') == True, True) #raise UserError(str(Eval('_parent_sale', {}).get('sale_type'))) if Eval('_parent_sale', {}).get('sale_type') == 'maintenance': cls.product.domain + [('type', '=', 'service'), ('maintenance_activity', '=', True)] @fields.depends('product_equipment','equipment') def get_serial_equipment(self): if self.product_equipment: return self.equipment.serial else: return None def on_change_with_unit_digits(self, name=None): if self.unit: return self.unit.digits return 2 @fields.depends('equipment', 'sale', 'quantity', '_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.equipment_serial = self.equipment.serial self.quantity = 1 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.equipment_serial = None self.on_change_product() @fields.depends('product_equipment', 'quantity', methods=['on_change_equipment']) def on_change_product_equipment(self): if self.product_equipment == False: self.equipment = None self.on_change_equipment() else: self.quantity = 1 @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 else: 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() if self.product.equipment: self.product_equipment = True def get_move(self, shipment_type): ''' Return moves for the sale line according to shipment_type ''' pool = Pool() Move = pool.get('stock.move') if self.type != 'line': return if not self.product: return if self.product.type not in Move.get_product_types(): return if (shipment_type == 'out') != (self.quantity >= 0): return quantity = (self._get_move_quantity(shipment_type) - self._get_shipped_quantity(shipment_type)) quantity = self.unit.round(quantity) if quantity <= 0: return if not self.sale.party.customer_location: raise PartyLocationError( gettext('sale.msg_sale_customer_location_required', sale=self.sale.rec_name, party=self.sale.party.rec_name)) move = Move() move.quantity = quantity move.uom = self.unit move.product = self.product move.from_location = self.from_location move.to_location = self.to_location move.state = 'draft' move.company = self.sale.company move.serial = self.equipment_serial if move.on_change_with_unit_price_required(): move.unit_price = self.unit_price move.currency = self.sale.currency move.planned_date = self.planned_shipping_date move.invoice_lines = self._get_move_invoice_lines(shipment_type) move.origin = self return move @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), })]