<s> from __future__ import absolute_import , unicode_literals <EOL> from decimal import Decimal <EOL> import logging <EOL> import re <EOL> from django . conf import settings <EOL> from django . core . exceptions import ValidationError <EOL> from django . core . urlresolvers import get_callable <EOL> from django . db import models <EOL> from django . db . models import F , ObjectDoesNotExist , Sum <EOL> from django . utils import timezone <EOL> from django . utils . encoding import python_2_unicode_compatible <EOL> from django . utils . translation import ugettext_lazy as _ <EOL> from django_countries . fields import CountryField <EOL> import plata <EOL> from plata . fields import CurrencyField , JSONField <EOL> logger = logging . getLogger ( '<STR_LIT>' ) <EOL> @ python_2_unicode_compatible <EOL> class TaxClass ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> name = models . CharField ( _ ( '<STR_LIT:name>' ) , max_length = <NUM_LIT:100> ) <EOL> rate = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , max_digits = <NUM_LIT:10> , decimal_places = <NUM_LIT:2> , <EOL> help_text = _ ( '<STR_LIT>' ) ) <EOL> priority = models . PositiveIntegerField ( <EOL> _ ( '<STR_LIT>' ) , default = <NUM_LIT:0> , <EOL> help_text = _ ( <EOL> '<STR_LIT>' ) ) <EOL> class Meta : <EOL> ordering = [ '<STR_LIT>' ] <EOL> verbose_name = _ ( '<STR_LIT>' ) <EOL> verbose_name_plural = _ ( '<STR_LIT>' ) <EOL> def __str__ ( self ) : <EOL> return self . name <EOL> class BillingShippingAddress ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> ADDRESS_FIELDS = [ <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:address>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> billing_company = models . CharField ( <EOL> _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:100> , blank = True ) <EOL> billing_first_name = models . CharField ( _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:100> ) <EOL> billing_last_name = models . CharField ( _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:100> ) <EOL> billing_address = models . TextField ( _ ( '<STR_LIT:address>' ) ) <EOL> billing_zip_code = models . CharField ( <EOL> plata . settings . PLATA_ZIP_CODE_LABEL , max_length = <NUM_LIT:50> ) <EOL> billing_city = models . CharField ( _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:100> ) <EOL> billing_country = CountryField ( _ ( '<STR_LIT>' ) , blank = True ) <EOL> shipping_same_as_billing = models . BooleanField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> default = True ) <EOL> shipping_company = models . CharField ( <EOL> _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:100> , blank = True ) <EOL> shipping_first_name = models . CharField ( <EOL> _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:100> , blank = True ) <EOL> shipping_last_name = models . CharField ( <EOL> _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:100> , blank = True ) <EOL> shipping_address = models . TextField ( _ ( '<STR_LIT:address>' ) , blank = True ) <EOL> shipping_zip_code = models . CharField ( <EOL> plata . settings . PLATA_ZIP_CODE_LABEL , max_length = <NUM_LIT:50> , blank = True ) <EOL> shipping_city = models . CharField ( _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:100> , blank = True ) <EOL> shipping_country = CountryField ( _ ( '<STR_LIT>' ) , blank = True ) <EOL> class Meta : <EOL> abstract = True <EOL> def addresses ( self ) : <EOL> """<STR_LIT>""" <EOL> billing = dict ( <EOL> ( f , getattr ( self , '<STR_LIT>' % f ) ) for f in self . ADDRESS_FIELDS ) <EOL> if self . shipping_same_as_billing : <EOL> shipping = billing <EOL> else : <EOL> shipping = dict ( <EOL> ( f , getattr ( self , '<STR_LIT>' % f ) ) <EOL> for f in self . ADDRESS_FIELDS ) <EOL> return { '<STR_LIT>' : billing , '<STR_LIT>' : shipping } <EOL> @ classmethod <EOL> def address_fields ( cls , prefix = '<STR_LIT>' ) : <EOL> return [ '<STR_LIT>' % ( prefix , f ) for f in cls . ADDRESS_FIELDS ] <EOL> @ python_2_unicode_compatible <EOL> class Order ( BillingShippingAddress ) : <EOL> """<STR_LIT>""" <EOL> CART = <NUM_LIT:10> <EOL> CHECKOUT = <NUM_LIT:20> <EOL> CONFIRMED = <NUM_LIT:30> <EOL> PAID = <NUM_LIT> <EOL> COMPLETED = <NUM_LIT:50> <EOL> STATUS_CHOICES = ( <EOL> ( CART , _ ( '<STR_LIT>' ) ) , <EOL> ( CHECKOUT , _ ( '<STR_LIT>' ) ) , <EOL> ( CONFIRMED , _ ( '<STR_LIT>' ) ) , <EOL> ( PAID , _ ( '<STR_LIT>' ) ) , <EOL> ( COMPLETED , _ ( '<STR_LIT>' ) ) , <EOL> ) <EOL> created = models . DateTimeField ( _ ( '<STR_LIT>' ) , default = timezone . now ) <EOL> confirmed = models . DateTimeField ( _ ( '<STR_LIT>' ) , blank = True , null = True ) <EOL> user = models . ForeignKey ( <EOL> getattr ( settings , '<STR_LIT>' , '<STR_LIT>' ) , <EOL> blank = True , <EOL> null = True , <EOL> verbose_name = _ ( '<STR_LIT:user>' ) , <EOL> related_name = '<STR_LIT>' <EOL> ) <EOL> language_code = models . CharField ( <EOL> _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:10> , default = '<STR_LIT>' , blank = True ) <EOL> status = models . PositiveIntegerField ( <EOL> _ ( '<STR_LIT:status>' ) , choices = STATUS_CHOICES , default = CART ) <EOL> _order_id = models . CharField ( _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:20> , blank = True ) <EOL> email = models . EmailField ( _ ( '<STR_LIT>' ) ) <EOL> currency = CurrencyField ( ) <EOL> price_includes_tax = models . BooleanField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> default = plata . settings . PLATA_PRICE_INCLUDES_TAX ) <EOL> items_subtotal = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> , default = Decimal ( '<STR_LIT>' ) ) <EOL> items_discount = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> , default = Decimal ( '<STR_LIT>' ) ) <EOL> items_tax = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> , default = Decimal ( '<STR_LIT>' ) ) <EOL> shipping_method = models . CharField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_length = <NUM_LIT:100> , blank = True ) <EOL> shipping_cost = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> , blank = True , null = True ) <EOL> shipping_discount = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> , blank = True , null = True ) <EOL> shipping_tax = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> , default = Decimal ( '<STR_LIT>' ) ) <EOL> total = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> , default = Decimal ( '<STR_LIT>' ) ) <EOL> paid = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> , default = Decimal ( '<STR_LIT>' ) , <EOL> help_text = _ ( '<STR_LIT>' ) ) <EOL> notes = models . TextField ( _ ( '<STR_LIT>' ) , blank = True ) <EOL> data = JSONField ( <EOL> _ ( '<STR_LIT:data>' ) , blank = True , <EOL> help_text = _ ( '<STR_LIT>' ) ) <EOL> class Meta : <EOL> verbose_name = _ ( '<STR_LIT>' ) <EOL> verbose_name_plural = _ ( '<STR_LIT>' ) <EOL> def __str__ ( self ) : <EOL> return self . order_id <EOL> def save ( self , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> if not self . _order_id and self . status >= self . PAID : <EOL> try : <EOL> order = Order . objects . exclude ( _order_id = '<STR_LIT>' ) . order_by ( <EOL> '<STR_LIT>' ) [ <NUM_LIT:0> ] <EOL> latest = int ( re . sub ( r'<STR_LIT>' , '<STR_LIT>' , order . _order_id ) ) <EOL> except ( IndexError , ValueError ) : <EOL> latest = <NUM_LIT:0> <EOL> self . _order_id = '<STR_LIT>' % ( latest + <NUM_LIT:1> ) <EOL> super ( Order , self ) . save ( * args , ** kwargs ) <EOL> save . alters_data = True <EOL> @ property <EOL> def order_id ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . _order_id : <EOL> return self . _order_id <EOL> return u'<STR_LIT>' % self . id <EOL> def recalculate_total ( self , save = True ) : <EOL> """<STR_LIT>""" <EOL> items = list ( self . items . all ( ) ) <EOL> shared_state = { } <EOL> processor_classes = [ <EOL> get_callable ( processor ) <EOL> for processor in plata . settings . PLATA_ORDER_PROCESSORS ] <EOL> for p in ( cls ( shared_state ) for cls in processor_classes ) : <EOL> p . process ( self , items ) <EOL> if save : <EOL> self . save ( ) <EOL> [ item . save ( ) for item in items ] <EOL> @ property <EOL> def subtotal ( self ) : <EOL> """<STR_LIT>""" <EOL> return sum ( <EOL> ( item . subtotal for item in self . items . all ( ) ) , <EOL> Decimal ( '<STR_LIT>' ) ) . quantize ( Decimal ( '<STR_LIT>' ) ) <EOL> @ property <EOL> def discount ( self ) : <EOL> """<STR_LIT>""" <EOL> return ( <EOL> sum ( <EOL> ( item . subtotal for item in self . items . all ( ) ) , <EOL> Decimal ( '<STR_LIT>' ) <EOL> ) - sum ( <EOL> ( item . discounted_subtotal for item in self . items . all ( ) ) , <EOL> Decimal ( '<STR_LIT>' ) <EOL> ) <EOL> ) . quantize ( Decimal ( '<STR_LIT>' ) ) <EOL> @ property <EOL> def shipping ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . price_includes_tax : <EOL> if self . shipping_cost is None : <EOL> return None <EOL> return ( <EOL> self . shipping_cost <EOL> - self . shipping_discount <EOL> + self . shipping_tax ) <EOL> else : <EOL> logger . error ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> raise NotImplementedError <EOL> @ property <EOL> def tax ( self ) : <EOL> """<STR_LIT>""" <EOL> return ( self . items_tax + self . shipping_tax ) . quantize ( Decimal ( '<STR_LIT>' ) ) <EOL> @ property <EOL> def balance_remaining ( self ) : <EOL> """<STR_LIT>""" <EOL> return ( self . total - self . paid ) . quantize ( Decimal ( '<STR_LIT>' ) ) <EOL> def is_paid ( self ) : <EOL> import warnings <EOL> warnings . warn ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' , <EOL> DeprecationWarning , stacklevel = <NUM_LIT:2> ) <EOL> return self . balance_remaining <= <NUM_LIT:0> <EOL> VALIDATE_BASE = <NUM_LIT:10> <EOL> VALIDATE_CART = <NUM_LIT:20> <EOL> VALIDATE_ALL = <NUM_LIT:100> <EOL> VALIDATORS = { } <EOL> @ classmethod <EOL> def register_validator ( cls , validator , group ) : <EOL> """<STR_LIT>""" <EOL> cls . VALIDATORS . setdefault ( group , [ ] ) . append ( validator ) <EOL> def validate ( self , group ) : <EOL> """<STR_LIT>""" <EOL> for g in sorted ( g for g in self . VALIDATORS . keys ( ) if g <= group ) : <EOL> for validator in self . VALIDATORS [ g ] : <EOL> validator ( self ) <EOL> def is_confirmed ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . status >= self . CONFIRMED <EOL> def modify_item ( self , product , relative = None , absolute = None , <EOL> recalculate = True , data = None , item = None , force_new = False ) : <EOL> """<STR_LIT>""" <EOL> assert ( relative is None ) != ( absolute is None ) , '<STR_LIT>' <EOL> assert not ( force_new and item ) , '<STR_LIT>' <EOL> if self . is_confirmed ( ) : <EOL> raise ValidationError ( <EOL> _ ( '<STR_LIT>' ) , <EOL> code = '<STR_LIT>' ) <EOL> if item is None and not force_new : <EOL> try : <EOL> item = self . items . get ( product = product ) <EOL> except self . items . model . DoesNotExist : <EOL> pass <EOL> except self . items . model . MultipleObjectsReturned : <EOL> if not force_new : <EOL> raise ValidationError ( <EOL> _ ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) , <EOL> code = '<STR_LIT>' ) <EOL> if item is None : <EOL> item = self . items . model ( <EOL> order = self , <EOL> product = product , <EOL> quantity = <NUM_LIT:0> , <EOL> currency = self . currency , <EOL> ) <EOL> if relative is not None : <EOL> item . quantity += relative <EOL> else : <EOL> item . quantity = absolute <EOL> if item . quantity > <NUM_LIT:0> : <EOL> try : <EOL> price = product . get_price ( <EOL> currency = self . currency , <EOL> orderitem = item ) <EOL> except ObjectDoesNotExist : <EOL> logger . error ( <EOL> u'<STR_LIT>' % ( <EOL> product , self . currency ) ) <EOL> raise ValidationError ( <EOL> _ ( '<STR_LIT>' ) , <EOL> code = '<STR_LIT>' ) <EOL> if data is not None : <EOL> item . data = data <EOL> price . handle_order_item ( item ) <EOL> product . handle_order_item ( item ) <EOL> item . save ( ) <EOL> else : <EOL> if item . pk : <EOL> item . delete ( ) <EOL> item . pk = None <EOL> if recalculate : <EOL> self . recalculate_total ( ) <EOL> if item . pk : <EOL> item = self . items . get ( pk = item . pk ) <EOL> try : <EOL> self . validate ( self . VALIDATE_BASE ) <EOL> except ValidationError : <EOL> if item . pk : <EOL> item . delete ( ) <EOL> raise <EOL> return item <EOL> @ property <EOL> def discount_remaining ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . applied_discounts . remaining ( ) <EOL> def update_status ( self , status , notes ) : <EOL> """<STR_LIT>""" <EOL> if status >= Order . CHECKOUT : <EOL> if not self . items . count ( ) : <EOL> raise ValidationError ( <EOL> _ ( '<STR_LIT>' ) , <EOL> code = '<STR_LIT>' ) <EOL> logger . info ( '<STR_LIT>' % ( self , status ) ) <EOL> instance = OrderStatus ( <EOL> order = self , <EOL> status = status , <EOL> notes = notes ) <EOL> instance . save ( ) <EOL> def reload ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . __class__ . _default_manager . get ( pk = self . id ) <EOL> def items_in_order ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . items . aggregate ( q = Sum ( '<STR_LIT>' ) ) [ '<STR_LIT:q>' ] or <NUM_LIT:0> <EOL> def validate_order_currencies ( order ) : <EOL> """<STR_LIT>""" <EOL> currencies = set ( order . items . values_list ( '<STR_LIT>' , flat = True ) ) <EOL> if ( currencies <EOL> and ( len ( currencies ) > <NUM_LIT:1> or order . currency not in currencies ) ) : <EOL> raise ValidationError ( <EOL> _ ( '<STR_LIT>' ) , <EOL> code = '<STR_LIT>' ) <EOL> Order . register_validator ( validate_order_currencies , Order . VALIDATE_BASE ) <EOL> @ python_2_unicode_compatible <EOL> class OrderItem ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> order = models . ForeignKey ( Order , related_name = '<STR_LIT>' ) <EOL> product = models . ForeignKey ( <EOL> plata . settings . PLATA_SHOP_PRODUCT , <EOL> verbose_name = _ ( '<STR_LIT>' ) , <EOL> blank = True , null = True , on_delete = models . SET_NULL ) <EOL> name = models . CharField ( _ ( '<STR_LIT:name>' ) , max_length = <NUM_LIT:100> , blank = True ) <EOL> sku = models . CharField ( _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:100> , blank = True ) <EOL> quantity = models . IntegerField ( _ ( '<STR_LIT>' ) ) <EOL> currency = CurrencyField ( ) <EOL> _unit_price = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> , <EOL> help_text = _ ( '<STR_LIT>' ) ) <EOL> _unit_tax = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> ) <EOL> tax_rate = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT:10> , decimal_places = <NUM_LIT:2> ) <EOL> tax_class = models . ForeignKey ( <EOL> TaxClass , verbose_name = _ ( '<STR_LIT>' ) , <EOL> blank = True , null = True , on_delete = models . SET_NULL ) <EOL> is_sale = models . BooleanField ( _ ( '<STR_LIT>' ) ) <EOL> _line_item_price = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> , default = <NUM_LIT:0> , <EOL> help_text = _ ( '<STR_LIT>' ) ) <EOL> _line_item_discount = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> , <EOL> blank = True , null = True , <EOL> help_text = _ ( '<STR_LIT>' ) ) <EOL> _line_item_tax = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> , default = <NUM_LIT:0> ) <EOL> data = JSONField ( <EOL> _ ( '<STR_LIT:data>' ) , blank = True , <EOL> help_text = _ ( '<STR_LIT>' ) ) <EOL> class Meta : <EOL> ordering = ( '<STR_LIT>' , ) <EOL> verbose_name = _ ( '<STR_LIT>' ) <EOL> verbose_name_plural = _ ( '<STR_LIT>' ) <EOL> def __str__ ( self ) : <EOL> return _ ( '<STR_LIT>' ) % { <EOL> '<STR_LIT>' : self . quantity , <EOL> '<STR_LIT:name>' : self . name , <EOL> } <EOL> @ property <EOL> def unit_price ( self ) : <EOL> if self . order . price_includes_tax : <EOL> return self . _unit_price + self . _unit_tax <EOL> return self . _unit_price <EOL> @ property <EOL> def line_item_discount_excl_tax ( self ) : <EOL> return self . _line_item_discount or <NUM_LIT:0> <EOL> @ property <EOL> def line_item_discount_incl_tax ( self ) : <EOL> return self . line_item_discount_excl_tax * ( <NUM_LIT:1> + self . tax_rate / <NUM_LIT:100> ) <EOL> @ property <EOL> def line_item_discount ( self ) : <EOL> if self . order . price_includes_tax : <EOL> return self . line_item_discount_incl_tax <EOL> else : <EOL> return self . line_item_discount_excl_tax <EOL> @ property <EOL> def subtotal ( self ) : <EOL> return self . unit_price * self . quantity <EOL> @ property <EOL> def discounted_subtotal_excl_tax ( self ) : <EOL> return self . _line_item_price - ( self . _line_item_discount or <NUM_LIT:0> ) <EOL> @ property <EOL> def discounted_subtotal_incl_tax ( self ) : <EOL> return self . discounted_subtotal_excl_tax + self . _line_item_tax <EOL> @ property <EOL> def discounted_subtotal ( self ) : <EOL> if self . order . price_includes_tax : <EOL> return self . discounted_subtotal_incl_tax <EOL> else : <EOL> return self . discounted_subtotal_excl_tax <EOL> @ python_2_unicode_compatible <EOL> class OrderStatus ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> order = models . ForeignKey ( Order , related_name = '<STR_LIT>' ) <EOL> created = models . DateTimeField ( _ ( '<STR_LIT>' ) , default = timezone . now ) <EOL> status = models . PositiveIntegerField ( <EOL> _ ( '<STR_LIT:status>' ) , max_length = <NUM_LIT:20> , choices = Order . STATUS_CHOICES ) <EOL> notes = models . TextField ( _ ( '<STR_LIT>' ) , blank = True ) <EOL> class Meta : <EOL> ordering = ( '<STR_LIT>' , '<STR_LIT:id>' ) <EOL> verbose_name = _ ( '<STR_LIT>' ) <EOL> verbose_name_plural = _ ( '<STR_LIT>' ) <EOL> def __str__ ( self ) : <EOL> return _ ( '<STR_LIT>' ) % { <EOL> '<STR_LIT:status>' : self . get_status_display ( ) , <EOL> '<STR_LIT>' : self . order , <EOL> } <EOL> def save ( self , * args , ** kwargs ) : <EOL> super ( OrderStatus , self ) . save ( * args , ** kwargs ) <EOL> self . order . status = self . status <EOL> if self . status == Order . CONFIRMED : <EOL> self . order . confirmed = timezone . now ( ) <EOL> elif self . status > Order . CONFIRMED and not self . order . confirmed : <EOL> self . order . confirmed = timezone . now ( ) <EOL> elif self . status < Order . CONFIRMED : <EOL> self . order . confirmed = None <EOL> self . order . save ( ) <EOL> save . alters_data = True <EOL> class OrderPaymentManager ( models . Manager ) : <EOL> def pending ( self ) : <EOL> return self . filter ( status = self . model . PENDING ) <EOL> def authorized ( self ) : <EOL> return self . filter ( authorized__isnull = False ) <EOL> @ python_2_unicode_compatible <EOL> class OrderPayment ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> PENDING = <NUM_LIT:10> <EOL> PROCESSED = <NUM_LIT:20> <EOL> AUTHORIZED = <NUM_LIT:30> <EOL> STATUS_CHOICES = ( <EOL> ( PENDING , _ ( '<STR_LIT>' ) ) , <EOL> ( PROCESSED , _ ( '<STR_LIT>' ) ) , <EOL> ( AUTHORIZED , _ ( '<STR_LIT>' ) ) , <EOL> ) <EOL> order = models . ForeignKey ( <EOL> Order , verbose_name = _ ( '<STR_LIT>' ) , related_name = '<STR_LIT>' ) <EOL> timestamp = models . DateTimeField ( _ ( '<STR_LIT>' ) , default = timezone . now ) <EOL> status = models . PositiveIntegerField ( <EOL> _ ( '<STR_LIT:status>' ) , choices = STATUS_CHOICES , default = PENDING ) <EOL> currency = CurrencyField ( ) <EOL> amount = models . DecimalField ( _ ( '<STR_LIT>' ) , max_digits = <NUM_LIT:10> , decimal_places = <NUM_LIT:2> ) <EOL> payment_module_key = models . CharField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_length = <NUM_LIT:20> , <EOL> help_text = _ ( <EOL> '<STR_LIT>' ) ) <EOL> payment_module = models . CharField ( <EOL> _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:50> , <EOL> blank = True , <EOL> help_text = _ ( '<STR_LIT>' ) ) <EOL> payment_method = models . CharField ( <EOL> _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:50> , <EOL> blank = True , <EOL> help_text = _ ( <EOL> '<STR_LIT>' ) ) <EOL> transaction_id = models . CharField ( <EOL> _ ( '<STR_LIT>' ) , max_length = <NUM_LIT:50> , <EOL> blank = True , <EOL> help_text = _ ( <EOL> '<STR_LIT>' ) ) <EOL> authorized = models . DateTimeField ( <EOL> _ ( '<STR_LIT>' ) , blank = True , null = True , <EOL> help_text = _ ( '<STR_LIT>' ) ) <EOL> notes = models . TextField ( _ ( '<STR_LIT>' ) , blank = True ) <EOL> data = JSONField ( <EOL> _ ( '<STR_LIT:data>' ) , blank = True , <EOL> help_text = _ ( '<STR_LIT>' ) ) <EOL> class Meta : <EOL> ordering = ( '<STR_LIT>' , ) <EOL> verbose_name = _ ( '<STR_LIT>' ) <EOL> verbose_name_plural = _ ( '<STR_LIT>' ) <EOL> objects = OrderPaymentManager ( ) <EOL> def __str__ ( self ) : <EOL> return _ ( <EOL> '<STR_LIT>' <EOL> ) % { <EOL> '<STR_LIT>' : ( <EOL> self . authorized and _ ( '<STR_LIT>' ) or _ ( '<STR_LIT>' ) ) , <EOL> '<STR_LIT>' : self . currency , <EOL> '<STR_LIT>' : self . amount , <EOL> '<STR_LIT>' : self . order , <EOL> } <EOL> def _recalculate_paid ( self ) : <EOL> paid = OrderPayment . objects . authorized ( ) . filter ( <EOL> order = self . order_id , <EOL> currency = F ( '<STR_LIT>' ) , <EOL> ) . aggregate ( total = Sum ( '<STR_LIT>' ) ) [ '<STR_LIT>' ] or <NUM_LIT:0> <EOL> Order . objects . filter ( id = self . order_id ) . update ( paid = paid ) <EOL> def save ( self , * args , ** kwargs ) : <EOL> super ( OrderPayment , self ) . save ( * args , ** kwargs ) <EOL> self . _recalculate_paid ( ) <EOL> if self . currency != self . order . currency : <EOL> self . order . notes += ( <EOL> u'<STR_LIT:\n>' + _ ( '<STR_LIT>' ) % self ) <EOL> self . order . save ( ) <EOL> save . alters_data = True <EOL> def delete ( self , * args , ** kwargs ) : <EOL> super ( OrderPayment , self ) . delete ( * args , ** kwargs ) <EOL> self . _recalculate_paid ( ) <EOL> delete . alters_data = True <EOL> @ python_2_unicode_compatible <EOL> class PriceBase ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> class Meta : <EOL> abstract = True <EOL> ordering = [ '<STR_LIT>' ] <EOL> verbose_name = _ ( '<STR_LIT>' ) <EOL> verbose_name_plural = _ ( '<STR_LIT>' ) <EOL> currency = CurrencyField ( ) <EOL> _unit_price = models . DecimalField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> max_digits = <NUM_LIT> , decimal_places = <NUM_LIT:10> ) <EOL> tax_included = models . BooleanField ( <EOL> _ ( '<STR_LIT>' ) , <EOL> help_text = _ ( '<STR_LIT>' ) , <EOL> default = plata . settings . PLATA_PRICE_INCLUDES_TAX ) <EOL> tax_class = models . ForeignKey ( <EOL> TaxClass , verbose_name = _ ( '<STR_LIT>' ) , related_name = '<STR_LIT:+>' ) <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % ( self . currency , self . unit_price ) <EOL> def __cmp__ ( self , other ) : <EOL> return int ( <EOL> ( self . unit_price_excl_tax - other . unit_price_excl_tax ) * <NUM_LIT:100> ) <EOL> def __hash__ ( self ) : <EOL> return int ( self . unit_price_excl_tax * <NUM_LIT:100> ) <EOL> def handle_order_item ( self , item ) : <EOL> """<STR_LIT>""" <EOL> item . _unit_price = self . unit_price_excl_tax <EOL> item . _unit_tax = self . unit_tax <EOL> item . tax_rate = self . tax_class . rate <EOL> item . tax_class = self . tax_class <EOL> item . is_sale = False <EOL> @ property <EOL> def unit_tax ( self ) : <EOL> return self . unit_price_excl_tax * ( self . tax_class . rate / <NUM_LIT:100> ) <EOL> @ property <EOL> def unit_price_incl_tax ( self ) : <EOL> if self . tax_included : <EOL> return self . _unit_price <EOL> return self . _unit_price * ( <NUM_LIT:1> + self . tax_class . rate / <NUM_LIT:100> ) <EOL> @ property <EOL> def unit_price_excl_tax ( self ) : <EOL> if not self . tax_included : <EOL> return self . _unit_price <EOL> return self . _unit_price / ( <NUM_LIT:1> + self . tax_class . rate / <NUM_LIT:100> ) <EOL> @ property <EOL> def unit_price ( self ) : <EOL> return self . unit_price_incl_tax </s>
