<s> from __future__ import unicode_literals <EOL> from functools import wraps <EOL> from django . conf import settings <EOL> from django . db import transaction <EOL> from django . forms . models import model_to_dict <EOL> from django . utils . encoding import smart_text <EOL> from prices import Price , FixedDiscount <EOL> from . . cart import Cart <EOL> from . . core import analytics <EOL> from . . discount . models import Voucher , NotApplicable <EOL> from . . order . models import Order <EOL> from . . shipping . models import ShippingMethodCountry <EOL> from . . userprofile . models import Address , User <EOL> STORAGE_SESSION_KEY = '<STR_LIT>' <EOL> class Checkout ( object ) : <EOL> VERSION = '<STR_LIT>' <EOL> modified = False <EOL> def __init__ ( self , cart , user , tracking_code ) : <EOL> self . cart = cart <EOL> self . storage = { '<STR_LIT:version>' : self . VERSION } <EOL> self . tracking_code = tracking_code <EOL> self . user = user <EOL> @ classmethod <EOL> def from_storage ( cls , storage_data , cart , user , tracking_code ) : <EOL> checkout = cls ( cart , user , tracking_code ) <EOL> checkout . storage = storage_data <EOL> try : <EOL> version = checkout . storage [ '<STR_LIT:version>' ] <EOL> except ( TypeError , KeyError ) : <EOL> version = None <EOL> if version != cls . VERSION : <EOL> checkout . storage = { '<STR_LIT:version>' : cls . VERSION } <EOL> return checkout <EOL> def for_storage ( self ) : <EOL> return self . storage <EOL> def clear_storage ( self ) : <EOL> self . storage = None <EOL> self . modified = True <EOL> def _get_address_from_storage ( self , key ) : <EOL> address_data = self . storage . get ( key ) <EOL> if address_data is not None and address_data . get ( '<STR_LIT:id>' ) : <EOL> try : <EOL> return Address . objects . get ( id = address_data [ '<STR_LIT:id>' ] ) <EOL> except Address . DoesNotExist : <EOL> return None <EOL> elif address_data : <EOL> return Address ( ** address_data ) <EOL> return None <EOL> @ property <EOL> def is_shipping_required ( self ) : <EOL> return self . cart . is_shipping_required ( ) <EOL> @ property <EOL> def deliveries ( self ) : <EOL> for partition in self . cart . partition ( ) : <EOL> if self . shipping_method and partition . is_shipping_required ( ) : <EOL> shipping_cost = self . shipping_method . get_total ( ) <EOL> else : <EOL> shipping_cost = Price ( <NUM_LIT:0> , currency = settings . DEFAULT_CURRENCY ) <EOL> total_with_shipping = partition . get_total ( ) + shipping_cost <EOL> yield partition , shipping_cost , total_with_shipping <EOL> @ property <EOL> def shipping_address ( self ) : <EOL> address = self . _get_address_from_storage ( '<STR_LIT>' ) <EOL> if address is None and self . user . is_authenticated ( ) : <EOL> return self . user . default_shipping_address <EOL> return address <EOL> @ shipping_address . setter <EOL> def shipping_address ( self , address ) : <EOL> address_data = model_to_dict ( address ) <EOL> address_data [ '<STR_LIT>' ] = smart_text ( address_data [ '<STR_LIT>' ] ) <EOL> self . storage [ '<STR_LIT>' ] = address_data <EOL> self . modified = True <EOL> @ property <EOL> def shipping_method ( self ) : <EOL> shipping_address = self . shipping_address <EOL> if shipping_address is not None : <EOL> shipping_method_country_id = self . storage . get ( '<STR_LIT>' ) <EOL> if shipping_method_country_id is not None : <EOL> try : <EOL> shipping_method_country = ShippingMethodCountry . objects . get ( <EOL> id = shipping_method_country_id ) <EOL> except ShippingMethodCountry . DoesNotExist : <EOL> return None <EOL> shipping_country_code = shipping_address . country . code <EOL> any_country = ShippingMethodCountry . ANY_COUNTRY <EOL> if ( shipping_method_country . country_code == any_country or <EOL> shipping_method_country . country_code == shipping_country_code ) : <EOL> return shipping_method_country <EOL> @ shipping_method . setter <EOL> def shipping_method ( self , shipping_method_country ) : <EOL> self . storage [ '<STR_LIT>' ] = shipping_method_country . id <EOL> self . modified = True <EOL> @ property <EOL> def email ( self ) : <EOL> return self . storage . get ( '<STR_LIT:email>' ) <EOL> @ email . setter <EOL> def email ( self , email ) : <EOL> self . storage [ '<STR_LIT:email>' ] = email <EOL> self . modified = True <EOL> @ property <EOL> def billing_address ( self ) : <EOL> address = self . _get_address_from_storage ( '<STR_LIT>' ) <EOL> if address is not None : <EOL> return address <EOL> elif self . user . is_authenticated ( ) and self . user . default_billing_address : <EOL> return self . user . default_billing_address <EOL> elif self . shipping_address : <EOL> return self . shipping_address <EOL> @ billing_address . setter <EOL> def billing_address ( self , address ) : <EOL> address_data = model_to_dict ( address ) <EOL> address_data [ '<STR_LIT>' ] = smart_text ( address_data [ '<STR_LIT>' ] ) <EOL> self . storage [ '<STR_LIT>' ] = address_data <EOL> self . modified = True <EOL> @ property <EOL> def discount ( self ) : <EOL> value = self . storage . get ( '<STR_LIT>' ) <EOL> currency = self . storage . get ( '<STR_LIT>' ) <EOL> name = self . storage . get ( '<STR_LIT>' ) <EOL> if value is not None and name is not None and currency is not None : <EOL> amount = Price ( value , currency = currency ) <EOL> return FixedDiscount ( amount , name ) <EOL> @ discount . setter <EOL> def discount ( self , discount ) : <EOL> amount = discount . amount <EOL> self . storage [ '<STR_LIT>' ] = smart_text ( amount . net ) <EOL> self . storage [ '<STR_LIT>' ] = amount . currency <EOL> self . storage [ '<STR_LIT>' ] = discount . name <EOL> self . modified = True <EOL> @ discount . deleter <EOL> def discount ( self ) : <EOL> if '<STR_LIT>' in self . storage : <EOL> del self . storage [ '<STR_LIT>' ] <EOL> self . modified = True <EOL> if '<STR_LIT>' in self . storage : <EOL> del self . storage [ '<STR_LIT>' ] <EOL> self . modified = True <EOL> if '<STR_LIT>' in self . storage : <EOL> del self . storage [ '<STR_LIT>' ] <EOL> self . modified = True <EOL> @ property <EOL> def voucher_code ( self ) : <EOL> return self . storage . get ( '<STR_LIT>' ) <EOL> @ voucher_code . setter <EOL> def voucher_code ( self , voucher_code ) : <EOL> self . storage [ '<STR_LIT>' ] = voucher_code <EOL> self . modified = True <EOL> @ voucher_code . deleter <EOL> def voucher_code ( self ) : <EOL> if '<STR_LIT>' in self . storage : <EOL> del self . storage [ '<STR_LIT>' ] <EOL> self . modified = True <EOL> @ property <EOL> def is_shipping_same_as_billing ( self ) : <EOL> return Address . objects . are_identical ( self . shipping_address , self . billing_address ) <EOL> def _save_address ( self , address , is_billing = False , is_shipping = False ) : <EOL> if self . user . is_authenticated ( ) and address . id is None : <EOL> address = User . objects . store_address ( <EOL> self . user , address , shipping = is_shipping , billing = is_billing ) <EOL> elif address . id is None : <EOL> address . save ( ) <EOL> return address <EOL> @ transaction . atomic <EOL> def create_order ( self ) : <EOL> if self . is_shipping_required : <EOL> shipping_address = self . _save_address ( <EOL> self . shipping_address , is_shipping = True ) <EOL> else : <EOL> shipping_address = None <EOL> billing_address = self . _save_address ( <EOL> self . billing_address , is_billing = True ) <EOL> order_data = { <EOL> '<STR_LIT>' : billing_address , <EOL> '<STR_LIT>' : shipping_address , <EOL> '<STR_LIT>' : self . tracking_code , <EOL> '<STR_LIT>' : self . get_total ( ) } <EOL> if self . user . is_authenticated ( ) : <EOL> order_data [ '<STR_LIT:user>' ] = self . user <EOL> else : <EOL> order_data [ '<STR_LIT>' ] = self . email <EOL> voucher = self . _get_voucher ( ) <EOL> if voucher is not None : <EOL> discount = self . discount <EOL> order_data [ '<STR_LIT>' ] = voucher <EOL> order_data [ '<STR_LIT>' ] = discount . amount <EOL> order_data [ '<STR_LIT>' ] = discount . name <EOL> order = Order . objects . create ( ** order_data ) <EOL> for partition in self . cart . partition ( ) : <EOL> shipping_required = partition . is_shipping_required ( ) <EOL> if shipping_required : <EOL> shipping_price = self . shipping_method . get_total ( ) <EOL> shipping_method_name = smart_text ( self . shipping_method ) <EOL> else : <EOL> shipping_price = <NUM_LIT:0> <EOL> shipping_method_name = None <EOL> group = order . groups . create ( <EOL> shipping_required = shipping_required , <EOL> shipping_price = shipping_price , <EOL> shipping_method_name = shipping_method_name ) <EOL> group . add_items_from_partition ( partition ) <EOL> if voucher is not None : <EOL> Voucher . objects . increase_usage ( voucher ) <EOL> return order <EOL> def _get_voucher ( self ) : <EOL> voucher_code = self . voucher_code <EOL> if voucher_code is not None : <EOL> try : <EOL> return Voucher . objects . get ( code = self . voucher_code ) <EOL> except Voucher . DoesNotExist : <EOL> return None <EOL> def recalculate_discount ( self ) : <EOL> voucher = self . _get_voucher ( ) <EOL> if voucher is not None : <EOL> try : <EOL> self . discount = voucher . get_discount_for_checkout ( self ) <EOL> except NotApplicable : <EOL> del self . discount <EOL> del self . voucher_code <EOL> else : <EOL> del self . discount <EOL> del self . voucher_code <EOL> def get_subtotal ( self ) : <EOL> zero = Price ( <NUM_LIT:0> , currency = settings . DEFAULT_CURRENCY ) <EOL> cost_iterator = ( <EOL> shipment . get_total ( ) <EOL> for shipment , shipping_cost , total in self . deliveries ) <EOL> total = sum ( cost_iterator , zero ) <EOL> return total <EOL> def get_total ( self ) : <EOL> zero = Price ( <NUM_LIT:0> , currency = settings . DEFAULT_CURRENCY ) <EOL> cost_iterator = ( <EOL> total <EOL> for shipment , shipping_cost , total in self . deliveries ) <EOL> total = sum ( cost_iterator , zero ) <EOL> return total if self . discount is None else self . discount . apply ( total ) <EOL> def get_total_shipping ( self ) : <EOL> zero = Price ( <NUM_LIT:0> , currency = settings . DEFAULT_CURRENCY ) <EOL> cost_iterator = ( <EOL> shipping_cost <EOL> for shipment , shipping_cost , total in self . deliveries ) <EOL> total = sum ( cost_iterator , zero ) <EOL> return total <EOL> def load_checkout ( view ) : <EOL> @ wraps ( view ) <EOL> def func ( request ) : <EOL> try : <EOL> session_data = request . session [ STORAGE_SESSION_KEY ] <EOL> except KeyError : <EOL> session_data = '<STR_LIT>' <EOL> tracking_code = analytics . get_client_id ( request ) <EOL> cart = Cart . for_session_cart ( <EOL> request . cart , discounts = request . discounts ) <EOL> checkout = Checkout . from_storage ( <EOL> session_data , cart , request . user , tracking_code ) <EOL> response = view ( request , checkout ) <EOL> if checkout . modified : <EOL> request . session [ STORAGE_SESSION_KEY ] = checkout . for_storage ( ) <EOL> return response <EOL> return func </s>
