def test_login(self): """Tests the login view. """ from lfs.checkout.views import login from lfs.checkout.settings import CHECKOUT_TYPE_ANON from lfs.tests.utils import create_request request = create_request() # Anonymous from django.contrib.auth.models import AnonymousUser request.user = AnonymousUser() result = login(request) self.assertEqual(result.status_code, 200) # Set checkout_type shop = get_default_shop() shop.checkout_type = CHECKOUT_TYPE_ANON shop.save() # Fake a new reuqest request.shop = shop result = login(request) self.assertEqual(result.status_code, 302) # Authenticated request.user = self.user result = login(request) self.assertEqual(result.status_code, 302)
def get_parent_for_portlets(self): """Returns the parent for parents. """ if self.id == 1: return get_default_shop() else: return lfs_get_object_or_404(Page, pk=1)
def main(request): """context processor for lfs """ shop = get_default_shop(request) return { "SHOP": shop, "ANON_ONLY": shop.checkout_type == CHECKOUT_TYPE_ANON, "LFS_DOCS": settings.LFS_DOCS, }
def __init__(self, *args, **kwargs): super(OnePageCheckoutForm, self).__init__(*args, **kwargs) shop = get_default_shop() self.fields["invoice_country"].choices = [(c.id, c.name) for c in shop.countries.all()] self.fields["shipping_country"].choices = [(c.id, c.name) for c in shop.countries.all()] year = datetime.now().year self.fields["credit_card_expiration_date_month"].choices = [(i, i) for i in range(1, 13)] self.fields["credit_card_expiration_date_year"].choices = [(i, i) for i in range(year, year+10)]
def cart_inline(request, template_name="lfs/cart/cart_inline.html"): """The actual content of the cart. This is factored out to be reused within 'normal' and ajax requests. """ cart = cart_utils.get_cart(request) shopping_url = lfs.cart.utils.get_go_on_shopping_url(request) if cart is None: return render_to_string(template_name, RequestContext(request, {"shopping_url": shopping_url})) shop = core_utils.get_default_shop() countries = shop.countries.all() selected_country = shipping_utils.get_selected_shipping_country(request) # Get default shipping method, so that we have a one in any case. selected_shipping_method = shipping_utils.get_selected_shipping_method(request) selected_payment_method = payment_utils.get_selected_payment_method(request) shipping_costs = shipping_utils.get_shipping_costs(request, selected_shipping_method) payment_costs = payment_utils.get_payment_costs(request, selected_payment_method) cart_costs = cart_utils.get_cart_costs(request, cart) cart_price = cart_costs["price"] + shipping_costs["price"] + payment_costs["price"] cart_tax = cart_costs["tax"] + shipping_costs["tax"] + payment_costs["tax"] max_delivery_time = cart_utils.get_cart_max_delivery_time(request, cart) # Calc delivery date for cart (which is the maximum of all cart items) max_delivery_date = cart_utils.get_cart_max_delivery_time(request, cart) return render_to_string( template_name, RequestContext( request, { "cart": cart, "max_delivery_date": max_delivery_date, "cart_price": cart_price, "cart_tax": cart_tax, "shipping_methods": shipping_utils.get_valid_shipping_methods(request), "selected_shipping_method": selected_shipping_method, "shipping_price": shipping_costs["price"], "payment_methods": payment_utils.get_valid_payment_methods(request), "selected_payment_method": selected_payment_method, "payment_price": payment_costs["price"], "countries": countries, "selected_country": selected_country, "max_delivery_time": max_delivery_time, "shopping_url": shopping_url, }, ), )
def cart_inline(request, template_name="lfs/cart/cart_inline.html"): """The actual content of the cart. This is factored out to be reused within 'normal' and ajax requests. """ cart = cart_utils.get_cart(request) shopping_url = lfs.cart.utils.get_go_on_shopping_url(request) if cart is None: return render_to_string(template_name, RequestContext(request, { "shopping_url" : shopping_url, })) shop = core_utils.get_default_shop() countries = shop.countries.all() selected_country = shipping_utils.get_selected_shipping_country(request) # Get default shipping method, so that we have a one in any case. selected_shipping_method = shipping_utils.get_selected_shipping_method(request) selected_payment_method = payment_utils.get_selected_payment_method(request) shipping_costs = shipping_utils.get_shipping_costs(request, selected_shipping_method) payment_costs = payment_utils.get_payment_costs(request, selected_payment_method) cart_costs = cart_utils.get_cart_costs(request, cart) cart_price = \ cart_costs["price"] + shipping_costs["price"] + payment_costs["price"] cart_tax = \ cart_costs["tax"] + shipping_costs["tax"] + payment_costs["tax"] max_delivery_time = cart_utils.get_cart_max_delivery_time(request, cart) # Calc delivery date for cart (which is the maximum of all cart items) max_delivery_date = cart_utils.get_cart_max_delivery_time(request, cart) return render_to_string(template_name, RequestContext(request, { "cart" : cart, "max_delivery_date" : max_delivery_date, "cart_price" : cart_price, "cart_tax" : cart_tax, "shipping_methods" : shipping_utils.get_valid_shipping_methods(request), "selected_shipping_method" : selected_shipping_method, "shipping_price" : shipping_costs["price"], "payment_methods" : payment_utils.get_valid_payment_methods(request), "selected_payment_method" : selected_payment_method, "payment_price" : payment_costs["price"], "countries" : countries, "selected_country" : selected_country, "max_delivery_time" : max_delivery_time, "shopping_url" : shopping_url, }))
def get_selected_shipping_country(request): """Returns the selected shipping country for the passed request. This could either be an explicitely selected country of the current user or the default country of the shop. """ customer = customer_utils.get_customer(request) if customer: if customer.selected_shipping_address: return customer.selected_shipping_address.country elif customer.selected_country: return customer.selected_country return get_default_shop().default_country
def migrate_to_07(self, application, version): from lfs.core.utils import get_default_shop from lfs.page.models import Page from lfs_order_numbers.models import OrderNumberGenerator # Pages print "Migrating to 0.7" db.add_column("page_page", "meta_title", models.CharField(_(u"Meta title"), blank=True, default="<title>", max_length=80)) db.add_column("page_page", "meta_keywords", models.TextField(_(u"Meta keywords"), null=True, blank=True)) db.add_column("page_page", "meta_description", models.TextField(_(u"Meta description"), null=True, blank=True)) for page in Page.objects.all(): page.meta_title = "<title>" page.meta_keywords = "" page.meta_description = "" page.save() # Copy the old page with id=1 and create a new one with id=1, which # will act as the root of all pages. try: page = Page.objects.get(pk=1) except Page.DoesNotExist: pass else: new_page = deepcopy(page) new_page.id = None new_page.save() page.delete() Page.objects.create(id=1, title="Root", slug="", active=1, exclude_from_navigation=1) # Shop db.add_column("core_shop", "meta_title", models.CharField(_(u"Meta title"), blank=True, default="<name>", max_length=80)) db.add_column("core_shop", "meta_keywords", models.TextField(_(u"Meta keywords"), null=True, blank=True)) db.add_column("core_shop", "meta_description", models.TextField(_(u"Meta description"), null=True, blank=True)) shop = get_default_shop() shop.meta_keywords = "" shop.meta_description = "" shop.save() # Order db.add_column("order_order", "number", models.CharField(max_length=30, unique=True)) OrderNumberGenerator.objects.create(pk="1", last=0) application.version = "0.7" application.save()
def migrate_to_07(self, application, version): from lfs.catalog.models import Product from lfs.catalog.settings import VARIANT from lfs.core.utils import get_default_shop from lfs.addresses.models import Address from lfs.page.models import Page from lfs.shipping.models import ShippingMethod from lfs_order_numbers.models import OrderNumberGenerator # Product from lfs.catalog.settings import QUANTITY_FIELD_INTEGER from lfs.catalog.settings import QUANTITY_FIELD_TYPES db.add_column( "catalog_product", "type_of_quantity_field", models.PositiveSmallIntegerField(_(u"Type of quantity field"), null=True, blank=True, choices=QUANTITY_FIELD_TYPES)) db.add_column( "catalog_product", "category_variant", models.SmallIntegerField(_(u"Category variant"), blank=True, null=True)) db.add_column( "catalog_product", "active_base_price", models.PositiveSmallIntegerField(_(u"Active base price"), default=0)) db.add_column( "catalog_product", "base_price_unit", models.CharField(_(u"Base price unit"), blank=True, null=True, max_length=30, choices=settings.LFS_BASE_PRICE_UNITS)) db.add_column( "catalog_product", "base_price_amount", models.FloatField(_(u"Base price amount"), default=0.0, blank=True, null=True)) if db.backend_name == "postgres": db.execute( 'ALTER TABLE catalog_product ALTER active_packing_unit TYPE smallint USING CASE WHEN active_packing_unit=FALSE THEN 0 ELSE 1 END;' ) else: db.alter_column( 'catalog_product', 'active_packing_unit', models.PositiveSmallIntegerField(_(u"Active packing"), default=0)) for product in Product.objects.all(): if product.active_packing_unit != 0: product.active_packing_unit = 1 product.save() # Pages print "Migrating to 0.7" db.add_column( "page_page", "meta_title", models.CharField(_(u"Meta title"), blank=True, default="<title>", max_length=80)) db.add_column( "page_page", "meta_keywords", models.TextField(_(u"Meta keywords"), null=True, blank=True)) db.add_column( "page_page", "meta_description", models.TextField(_(u"Meta description"), null=True, blank=True)) for page in Page.objects.all(): page.meta_title = "<title>" page.meta_keywords = "" page.meta_description = "" page.save() # Copy the old page with id=1 and create a new one with id=1, which # will act as the root of all pages. try: page = Page.objects.get(pk=1) except Page.DoesNotExist: pass else: new_page = deepcopy(page) new_page.id = None new_page.save() page.delete() Page.objects.create(id=1, title="Root", slug="", active=1, exclude_from_navigation=1) # Shop db.add_column( "core_shop", "meta_title", models.CharField(_(u"Meta title"), blank=True, default="<name>", max_length=80)) db.add_column( "core_shop", "meta_keywords", models.TextField(_(u"Meta keywords"), null=True, blank=True)) db.add_column( "core_shop", "meta_description", models.TextField(_(u"Meta description"), null=True, blank=True)) shop = get_default_shop() shop.meta_keywords = "" shop.meta_description = "" shop.save() # Order db.add_column("order_order", "number", models.CharField(max_length=30, unique=True, null=True)) OrderNumberGenerator.objects.create(pk="1", last=0) # Add new lines db.add_column("order_order", "invoice_company_name", models.CharField(null=True, blank=True, max_length=100)) db.add_column("order_order", "shipping_company_name", models.CharField(null=True, blank=True, max_length=100)) # Shipping Method db.add_column( "shipping_shippingmethod", "price_calculator", models.CharField( max_length=200, choices=settings.LFS_SHIPPING_METHOD_PRICE_CALCULATORS, default=settings.LFS_SHIPPING_METHOD_PRICE_CALCULATORS[0][0])) for shipping_method in ShippingMethod.objects.all(): shipping_method.price_calculator = settings.LFS_SHIPPING_METHOD_PRICE_CALCULATORS[ 0][0] shipping_method.save() # Static Block db.add_column( "catalog_staticblock", "position", models.PositiveSmallIntegerField(_(u"Position"), default=999)) # Addresses db.add_column( "customer_address", "line1", models.CharField(_("Line 1"), max_length=100, blank=True, null=True)) db.add_column( "customer_address", "line2", models.CharField(_("Line 2"), max_length=100, blank=True, null=True)) cursor = connection.cursor() cursor.execute("""SELECT id, street FROM customer_address""") for row in cursor.fetchall(): address = Address.objects.get(pk=row[0]) address.line1 = row[1] address.save() db.delete_column("customer_address", "street") application.version = "0.7" application.save()
def clean(self): """ """ msg = _(u"This field is required.") if self.data.get("is_anonymous") == "1" and \ getattr(settings, "LFS_INVOICE_EMAIL_REQUIRED") and \ self.cleaned_data.get("invoice_email") == "": self._errors["invoice_email"] = ErrorList([msg]) if not self.cleaned_data.get("no_shipping"): if self.cleaned_data.get("shipping_firstname") == "": self._errors["shipping_firstname"] = ErrorList([msg]) if self.cleaned_data.get("shipping_lastname") == "": self._errors["shipping_lastname"] = ErrorList([msg]) if getattr(settings, "LFS_SHIPPING_COMPANY_NAME_REQUIRED", False): if self.cleaned_data.get("shipping_company_name") == "": self._errors["shipping_company_name"] = ErrorList([msg]) if getattr(settings, "LFS_SHIPPING_PHONE_REQUIRED", False): if self.cleaned_data.get("shipping_phone") == "": self._errors["shipping_phone"] = ErrorList([msg]) if getattr(settings, "LFS_SHIPPING_EMAIL_REQUIRED", False): if self.cleaned_data.get("shipping_email") == "": self._errors["shipping_email"] = ErrorList([msg]) # check that shipping country is in the shops shipping countries list shop = get_default_shop() shipping_countries = shop.shipping_countries.all() shipping_country = None if not self.cleaned_data.get("no_shipping"): shipping_country_code = self.data.get("shipping-country", None) if shipping_country_code: shipping_country = Country.objects.get(code=shipping_country_code.lower()) if shipping_country: if shipping_country not in shipping_countries: msg = _(u"Invalid shipping country.") #self._errors["all"] = ErrorList([msg]) raise forms.ValidationError("Invalid Shipping Country") else: shipping_country_code = self.data.get("invoice-country", None) if shipping_country_code: shipping_country = Country.objects.get(code=shipping_country_code.lower()) # Check data of selected payment method payment_method_id = self.data.get("payment_method") payment_method = PaymentMethod.objects.get(pk=payment_method_id) if payment_method.type == lfs.payment.settings.PM_BANK: if self.cleaned_data.get("account_number", "") == "": self._errors["account_number"] = ErrorList([msg]) if self.cleaned_data.get("bank_identification_code", "") == "": self._errors["bank_identification_code"] = ErrorList([msg]) if self.cleaned_data.get("bank_name", "") == "": self._errors["bank_name"] = ErrorList([msg]) if self.cleaned_data.get("depositor", "") == "": self._errors["depositor"] = ErrorList([msg]) elif payment_method.type == lfs.payment.settings.PM_CREDIT_CARD: if self.cleaned_data.get("credit_card_owner", "") == "": self._errors["credit_card_owner"] = ErrorList([msg]) if self.cleaned_data.get("credit_card_number", "") == "": self._errors["credit_card_number"] = ErrorList([msg]) if self.cleaned_data.get("credit_card_verification", "") == "": self._errors["credit_card_verification"] = ErrorList([msg]) return self.cleaned_data
def setUp(self): """ """ ie = Country.objects.get(code="ie") us = Country.objects.get(code="us") shop = get_default_shop() for ic in Country.objects.all(): shop.invoice_countries.add(ic) shop.save() tax = Tax.objects.create(rate=19) shipping_method = ShippingMethod.objects.create(name="Standard", active=True, price=1.0, tax=tax) self.by_invoice = PaymentMethod.objects.get(pk=BY_INVOICE) address1 = Address.objects.create( firstname="John", lastname="Doe", company_name="Doe Ltd.", line1="Street 42", city="Gotham City", zip_code="2342", country=ie, ) address2 = Address.objects.create( firstname="Jane", lastname="Doe", company_name="Doe Ltd.", line1="Street 43", city="Smallville", zip_code="2443", country=us, ) address3 = Address.objects.create( firstname="John", lastname="Doe", company_name="Doe Ltd.", line1="Street 42", city="Gotham City", zip_code="2342", country=ie, ) address4 = Address.objects.create( firstname="Jane", lastname="Doe", company_name="Doe Ltd.", line1="Street 43", city="Smallville", zip_code="2443", country=us, ) self.username = '******' self.password = '******' new_user = User(username=self.username) new_user.set_password(self.password) new_user.save() self.customer = Customer.objects.create( user=new_user, selected_shipping_method=shipping_method, selected_payment_method=self.by_invoice, selected_shipping_address=address1, selected_invoice_address=address2, default_shipping_address=address3, default_invoice_address=address4) self.PRODUCT1_NAME = "Surfboard" p1 = Product.objects.create( name=self.PRODUCT1_NAME, slug="product-1", sku="sku-1", price=1.1, tax=tax, active=True, ) p2 = Product.objects.create( name="Product 2", slug="product-2", sku="sku-2", price=2.2, tax=tax, active=True, ) cart = Cart.objects.create(user=new_user) item = CartItem.objects.create( cart=cart, product=p1, amount=2, ) item = CartItem.objects.create( cart=cart, product=p2, amount=3, )
def cart_inline(request, template_name="lfs/cart/cart_inline.html"): """ The actual content of the cart. This is factored out to be reused within 'normal' and ajax requests. """ cart = cart_utils.get_cart(request) shopping_url = lfs.cart.utils.get_go_on_shopping_url(request) if cart is None: return render_to_string( template_name, RequestContext(request, { "shopping_url": shopping_url, })) shop = core_utils.get_default_shop(request) countries = shop.shipping_countries.all() selected_country = shipping_utils.get_selected_shipping_country(request) # Get default shipping method, so that we have a one in any case. selected_shipping_method = shipping_utils.get_selected_shipping_method( request) selected_payment_method = payment_utils.get_selected_payment_method( request) shipping_costs = shipping_utils.get_shipping_costs( request, selected_shipping_method) # Payment payment_costs = payment_utils.get_payment_costs(request, selected_payment_method) # Cart costs cart_price = cart.get_price_gross( request) + shipping_costs["price_gross"] + payment_costs["price"] cart_tax = cart.get_tax( request) + shipping_costs["tax"] + payment_costs["tax"] # Discounts discounts = lfs.discounts.utils.get_valid_discounts(request) for discount in discounts: cart_price = cart_price - discount["price_gross"] cart_tax = cart_tax - discount["tax"] # Voucher voucher_number = lfs.voucher.utils.get_current_voucher_number(request) try: voucher = Voucher.objects.get(number=voucher_number) except Voucher.DoesNotExist: display_voucher = False voucher_value = 0 voucher_tax = 0 voucher_message = MESSAGES[6] else: lfs.voucher.utils.set_current_voucher_number(request, voucher_number) is_voucher_effective, voucher_message = voucher.is_effective( request, cart) if is_voucher_effective: display_voucher = True voucher_value = voucher.get_price_gross(request, cart) cart_price = cart_price - voucher_value voucher_tax = voucher.get_tax(request, cart) cart_tax = cart_tax - voucher_tax else: display_voucher = False voucher_value = 0 voucher_tax = 0 # Calc delivery time for cart (which is the maximum of all cart items) max_delivery_time = cart.get_delivery_time(request) cart_items = [] for cart_item in cart.get_items(): product = cart_item.product quantity = product.get_clean_quantity(cart_item.amount) cart_items.append({ "obj": cart_item, "quantity": quantity, "product": product, "product_price_net": cart_item.get_price_net(request), "product_price_gross": cart_item.get_price_gross(request), "product_tax": cart_item.get_tax(request), }) return render_to_string( template_name, RequestContext( request, { "cart": cart, "cart_items": cart_items, "cart_price": cart_price, "cart_tax": cart_tax, "shipping_methods": shipping_utils.get_valid_shipping_methods(request), "selected_shipping_method": selected_shipping_method, "shipping_costs": shipping_costs, "payment_methods": payment_utils.get_valid_payment_methods(request), "selected_payment_method": selected_payment_method, "payment_price": payment_costs["price"], "countries": countries, "selected_country": selected_country, "max_delivery_time": max_delivery_time, "shopping_url": shopping_url, "discounts": discounts, "display_voucher": display_voucher, "voucher_number": voucher_number, "voucher_value": voucher_value, "voucher_tax": voucher_tax, "voucher_message": voucher_message, }))
def cart_inline(request, template_name="lfs/cart/cart_inline.html"): """ The actual content of the cart. This is factored out to be reused within 'normal' and ajax requests. """ cart = cart_utils.get_cart(request) shopping_url = lfs.cart.utils.get_go_on_shopping_url(request) if cart is None: return render_to_string(template_name, RequestContext(request, {"shopping_url": shopping_url})) shop = core_utils.get_default_shop(request) countries = shop.shipping_countries.all() selected_country = shipping_utils.get_selected_shipping_country(request) # Get default shipping method, so that we have a one in any case. selected_shipping_method = shipping_utils.get_selected_shipping_method(request) selected_payment_method = payment_utils.get_selected_payment_method(request) shipping_costs = shipping_utils.get_shipping_costs(request, selected_shipping_method) # Payment payment_costs = payment_utils.get_payment_costs(request, selected_payment_method) # Cart costs cart_price = cart.get_price_gross(request) + shipping_costs["price_gross"] + payment_costs["price"] cart_tax = cart.get_tax(request) + shipping_costs["tax"] + payment_costs["tax"] # Discounts discounts = lfs.discounts.utils.get_valid_discounts(request) for discount in discounts: cart_price = cart_price - discount["price_gross"] cart_tax = cart_tax - discount["tax"] # Voucher voucher_number = lfs.voucher.utils.get_current_voucher_number(request) try: voucher = Voucher.objects.get(number=voucher_number) except Voucher.DoesNotExist: display_voucher = False voucher_value = 0 voucher_tax = 0 voucher_message = MESSAGES[6] else: lfs.voucher.utils.set_current_voucher_number(request, voucher_number) is_voucher_effective, voucher_message = voucher.is_effective(request, cart) if is_voucher_effective: display_voucher = True voucher_value = voucher.get_price_gross(request, cart) cart_price = cart_price - voucher_value voucher_tax = voucher.get_tax(request, cart) cart_tax = cart_tax - voucher_tax else: display_voucher = False voucher_value = 0 voucher_tax = 0 # Calc delivery time for cart (which is the maximum of all cart items) max_delivery_time = cart.get_delivery_time(request) cart_items = [] for cart_item in cart.get_items(): product = cart_item.product quantity = product.get_clean_quantity(cart_item.amount) cart_items.append( { "obj": cart_item, "quantity": quantity, "product": product, "product_price_net": cart_item.get_price_net(request), "product_price_gross": cart_item.get_price_gross(request), "product_tax": cart_item.get_tax(request), } ) return render_to_string( template_name, RequestContext( request, { "cart": cart, "cart_items": cart_items, "cart_price": cart_price, "cart_tax": cart_tax, "shipping_methods": shipping_utils.get_valid_shipping_methods(request), "selected_shipping_method": selected_shipping_method, "shipping_costs": shipping_costs, "payment_methods": payment_utils.get_valid_payment_methods(request), "selected_payment_method": selected_payment_method, "payment_price": payment_costs["price"], "countries": countries, "selected_country": selected_country, "max_delivery_time": max_delivery_time, "shopping_url": shopping_url, "discounts": discounts, "display_voucher": display_voucher, "voucher_number": voucher_number, "voucher_value": voucher_value, "voucher_tax": voucher_tax, "voucher_message": voucher_message, }, ), )
def cart_inline(request, template_name="lfs/cart/cart_inline.html"): """ The actual content of the cart. This is factored out to be reused within 'normal' and ajax requests. """ cart = cart_utils.get_cart(request) shopping_url = lfs.cart.utils.get_go_on_shopping_url(request) if cart is None: return render_to_string(template_name, request=request, context={ "shopping_url": shopping_url, }) shop = core_utils.get_default_shop(request) countries = shop.shipping_countries.all() selected_country = shipping_utils.get_selected_shipping_country(request) # Get default shipping method, so that we have a one in any case. selected_shipping_method = shipping_utils.get_selected_shipping_method(request) selected_payment_method = payment_utils.get_selected_payment_method(request) shipping_costs = shipping_utils.get_shipping_costs(request, selected_shipping_method) # Payment payment_costs = payment_utils.get_payment_costs(request, selected_payment_method) # Cart costs cart_price = cart.get_price_gross(request) + shipping_costs["price_gross"] + payment_costs["price"] cart_tax = cart.get_tax(request) + shipping_costs["tax"] + payment_costs["tax"] # get voucher data (if voucher exists) voucher_data = lfs.voucher.utils.get_voucher_data(request, cart) # get discounts data discounts_data = lfs.discounts.utils.get_discounts_data(request) # calculate total value of discounts and voucher that sum up summed_up_value = discounts_data['summed_up_value'] if voucher_data['sums_up']: summed_up_value += voucher_data['voucher_value'] # initialize discounts with summed up discounts use_voucher = voucher_data['voucher'] is not None discounts = discounts_data['summed_up_discounts'] if voucher_data['voucher_value'] > summed_up_value or discounts_data['max_value'] > summed_up_value: # use not summed up value if voucher_data['voucher_value'] > discounts_data['max_value']: # use voucher only discounts = [] else: # use discount only discounts = discounts_data['max_discounts'] use_voucher = False for discount in discounts: cart_price -= discount["price_gross"] cart_tax -= discount["tax"] if use_voucher: cart_price -= voucher_data['voucher_value'] cart_tax -= voucher_data['voucher_tax'] cart_price = max(0, cart_price) cart_tax = max(0, cart_tax) # Calc delivery time for cart (which is the maximum of all cart items) max_delivery_time = cart.get_delivery_time(request) cart_items = [] for cart_item in cart.get_items(): product = cart_item.product quantity = product.get_clean_quantity(cart_item.amount) cart_items.append({ "obj": cart_item, "quantity": quantity, "product": product, "product_price_net": cart_item.get_price_net(request), "product_price_gross": cart_item.get_price_gross(request), "product_tax": cart_item.get_tax(request), }) return render_to_string(template_name, request=request, context={ "cart": cart, "cart_items": cart_items, "cart_price": cart_price, "cart_tax": cart_tax, "shipping_methods": shipping_utils.get_valid_shipping_methods(request), "selected_shipping_method": selected_shipping_method, "shipping_costs": shipping_costs, "payment_methods": payment_utils.get_valid_payment_methods(request), "selected_payment_method": selected_payment_method, "payment_price": payment_costs["price"], "countries": countries, "selected_country": selected_country, "max_delivery_time": max_delivery_time, "shopping_url": shopping_url, "discounts": discounts, "display_voucher": use_voucher, "voucher_number": voucher_data['voucher_number'], "voucher_value": voucher_data['voucher_value'], "voucher_tax": voucher_data['voucher_tax'], "voucher_message": voucher_data['voucher_message'], })
def migrate_to_06(self, application, version): from lfs.core.utils import get_default_shop print "Migrating to 0.6" # Vouchers ########################################################### db.add_column("voucher_voucher", "used_amount", models.PositiveSmallIntegerField(default=0)) db.add_column("voucher_voucher", "last_used_date", models.DateTimeField(blank=True, null=True)) db.add_column("voucher_voucher", "limit", models.PositiveSmallIntegerField(default=1)) for voucher in Voucher.objects.all(): voucher.limit = 1 voucher.save() # This mus be done with execute because the old fields are not there # anymore (and therefore can't be accessed via attribute) after the user # has upgraded to the latest version. db.execute("update voucher_voucher set used_amount = 1 where used = 1") db.execute("update voucher_voucher set used_amount = 0 where used = 0") db.execute("update voucher_voucher set last_used_date = used_date") db.delete_column('voucher_voucher', 'used') db.delete_column('voucher_voucher', 'used_date') # Price calculator ################################################### db.add_column("catalog_product", "price_calculator", models.CharField( null=True, blank=True, choices=lfs_settings.LFS_PRICE_CALCULATOR_DICTIONARY.items(), max_length=255)) db.add_column("core_shop", "price_calculator", models.CharField(choices=lfs_settings.LFS_PRICE_CALCULATOR_DICTIONARY.items(), default="lfs.gross_price.GrossPriceCalculator", max_length=255)) # Locale and currency settings ####################################### db.add_column("core_shop", "default_locale", models.CharField(_(u"Default Shop Locale"), max_length=20, default="en_US.UTF-8")) db.add_column("core_shop", "use_international_currency_code", models.BooleanField(_(u"Use international currency codes"), default=False)) db.delete_column('core_shop', 'default_currency') db.add_column("catalog_product", "supplier_id", models.IntegerField(_(u"Supplier"), blank=True, null=True)) # Invoice/Shipping countries shop = get_default_shop() db.create_table("core_shop_invoice_countries", ( ("id", models.AutoField(primary_key=True)), ("shop_id", models.IntegerField("shop_id")), ("country_id", models.IntegerField("country_id")), )) db.create_index("core_shop_invoice_countries", ("shop_id", )) db.create_index("core_shop_invoice_countries", ("country_id", )) db.create_unique("core_shop_invoice_countries", ("shop_id", "country_id")) db.create_table("core_shop_shipping_countries", ( ("id", models.AutoField(primary_key=True)), ("shop_id", models.IntegerField("shop_id")), ("country_id", models.IntegerField("country_id")), )) db.create_index("core_shop_shipping_countries", ("shop_id", )) db.create_index("core_shop_shipping_countries", ("country_id", )) db.create_unique("core_shop_shipping_countries", ("shop_id", "country_id")) cursor = connection.cursor() cursor.execute("""SELECT country_id FROM core_shop_countries""") for row in cursor.fetchall(): shop.invoice_countries.add(row[0]) shop.shipping_countries.add(row[0]) db.delete_table("core_shop_countries") # Orders ############################################################# # Add new lines db.add_column("order_order", "invoice_line1", models.CharField(null=True, blank=True, max_length=100)) db.add_column("order_order", "shipping_line1", models.CharField(null=True, blank=True, max_length=100)) db.add_column("order_order", "invoice_line2", models.CharField(null=True, blank=True, max_length=100)) db.add_column("order_order", "shipping_line2", models.CharField(null=True, blank=True, max_length=100)) db.add_column("order_order", "invoice_code", models.CharField(null=True, blank=True, max_length=100)) db.add_column("order_order", "shipping_code", models.CharField(null=True, blank=True, max_length=100)) # Migrate data cursor.execute("""SELECT id, invoice_zip_code, shipping_zip_code, invoice_street, shipping_street FROM order_order""") for row in cursor.fetchall(): order = Order.objects.get(pk=row[0]) order.invoice_code = row[1] order.shipping_code = row[2] order.invoice_line1 = row[3] order.shipping_line1 = row[4] order.invoice_line2 = "" order.shipping_line2 = "" order.save() # Remove old code fields db.delete_column('order_order', 'invoice_zip_code') db.delete_column('order_order', 'shipping_zip_code') db.delete_column('order_order', 'invoice_street') db.delete_column('order_order', 'shipping_street') application.version = "0.6" application.save()
def setUp(self): """ """ gb = Country.objects.get(code="gb") fr = Country.objects.get(code="fr") nl = Country.objects.get(code="nl") shop = get_default_shop() for ic in Country.objects.all(): shop.invoice_countries.add(ic) shop.shipping_countries.add(nl) shop.save() tax = Tax.objects.create(rate=19) shipping_method = ShippingMethod.objects.create( name="Standard", active=True, price=1.0, tax=tax ) self.by_invoice = PaymentMethod.objects.get(pk=BY_INVOICE) address1 = Address.objects.create( firstname="John", lastname="Doe", company_name="Doe Ltd.", line1="Street 42", city="2342", state="Gotham City", country=gb, ) address2 = Address.objects.create( firstname="Jane", lastname="Doe", company_name="Doe Ltd.", line1="Street 43", city="2443", state="Smallville", country=fr, ) self.username = '******' self.password = '******' new_user = User(username=self.username) new_user.set_password(self.password) new_user.save() self.user = new_user self.customer = Customer.objects.create( user=new_user, selected_shipping_method=shipping_method, selected_payment_method=self.by_invoice, selected_shipping_address=address1, selected_invoice_address=address2, default_shipping_address=address1, default_invoice_address=address2, ) self.PRODUCT1_NAME = "Surfboard" p1 = Product.objects.create( name=self.PRODUCT1_NAME, slug="product-1", sku="sku-1", price=1.1, tax=tax, stock_amount=100, active=True, ) p2 = Product.objects.create( name="Product 2", slug="product-2", sku="sku-2", price=2.2, tax=tax, stock_amount=50, active=True, ) cart = Cart.objects.create( user=new_user ) self.item1 = CartItem.objects.create( cart=cart, product=p1, amount=2, ) self.item2 = CartItem.objects.create( cart=cart, product=p2, amount=3, )
def migrate_to_07(self, application, version): from lfs.core.utils import get_default_shop from lfs.page.models import Page from lfs.shipping.models import ShippingMethod from lfs_order_numbers.models import OrderNumberGenerator # Product from lfs.catalog.settings import QUANTITY_FIELD_INTEGER from lfs.catalog.settings import QUANTITY_FIELD_TYPES db.add_column("catalog_product", "type_of_quantity_field", models.PositiveSmallIntegerField(_(u"Type of quantity field"), null=True, blank=True, choices=QUANTITY_FIELD_TYPES)) db.add_column("catalog_product", "category_variant", models.SmallIntegerField(_(u"Category variant"), blank=True, null=True)) db.add_column("catalog_product", "active_base_price", models.PositiveSmallIntegerField(_(u"Active base price"), default=0)) db.add_column("catalog_product", "base_price_unit", models.CharField(_(u"Base price unit"), blank=True, null=True, max_length=30, choices=settings.LFS_BASE_PRICE_UNITS)) db.add_column("catalog_product", "base_price_amount", models.FloatField(_(u"Base price amount"), default=0.0, blank=True, null=True)) db.alter_column('catalog_product', 'active_packing_unit', models.PositiveSmallIntegerField(_(u"Active packing"), default=0)) # Pages print "Migrating to 0.7" db.add_column("page_page", "meta_title", models.CharField(_(u"Meta title"), blank=True, default="<title>", max_length=80)) db.add_column("page_page", "meta_keywords", models.TextField(_(u"Meta keywords"), null=True, blank=True)) db.add_column("page_page", "meta_description", models.TextField(_(u"Meta description"), null=True, blank=True)) for page in Page.objects.all(): page.meta_title = "<title>" page.meta_keywords = "" page.meta_description = "" page.save() # Copy the old page with id=1 and create a new one with id=1, which # will act as the root of all pages. try: page = Page.objects.get(pk=1) except Page.DoesNotExist: pass else: new_page = deepcopy(page) new_page.id = None new_page.save() page.delete() Page.objects.create(id=1, title="Root", slug="", active=1, exclude_from_navigation=1) # Shop db.add_column("core_shop", "meta_title", models.CharField(_(u"Meta title"), blank=True, default="<name>", max_length=80)) db.add_column("core_shop", "meta_keywords", models.TextField(_(u"Meta keywords"), null=True, blank=True)) db.add_column("core_shop", "meta_description", models.TextField(_(u"Meta description"), null=True, blank=True)) shop = get_default_shop() shop.meta_keywords = "" shop.meta_description = "" shop.save() # Order db.add_column("order_order", "number", models.CharField(max_length=30, unique=True, null=True)) OrderNumberGenerator.objects.create(pk="1", last=0) # Add new lines db.add_column("order_order", "invoice_company_name", models.CharField(null=True, blank=True, max_length=100)) db.add_column("order_order", "shipping_company_name", models.CharField(null=True, blank=True, max_length=100)) # Shipping Method db.add_column("shipping_shippingmethod", "price_calculator", models.CharField(max_length=200, choices=settings.LFS_SHIPPING_PRICE_CALCULATORS, default=settings.LFS_SHIPPING_PRICE_CALCULATORS[0][0])) for shipping_method in ShippingMethod.objects.all(): shipping_method.price_calculator = settings.LFS_SHIPPING_PRICE_CALCULATORS[0][0] shipping_method.save() # Static Block db.add_column("catalog_staticblock", "position", models.PositiveSmallIntegerField(_(u"Position"), default=999)) application.version = "0.7" application.save()
def test_checkout_for_ireland(self): """ Ireland doesn't have zip_code """ ie = Country.objects.get(code="ie") shop = get_default_shop() shop.shipping_countries.add(ie) shop.save() # login as our customer logged_in = self.client.login(username=self.username, password=self.password) self.assertEqual(logged_in, True) # test that our Netherlands form has only 4 address line fields ie_form_class = form_factory("IE") ie_form = ie_form_class() self.assertEqual('zip_code' in ie_form.fields, False) self.assertEqual('city' in ie_form.fields, True) # check initial database quantities self.assertEquals(Address.objects.count(), 2) self.assertEquals(Customer.objects.count(), 1) self.assertEquals(Order.objects.count(), 0) # check we have no invoice or shipping phone or email prior to checkout our_customer = Customer.objects.all()[0] self.assertEqual(our_customer.selected_invoice_address.phone, None) self.assertEqual(our_customer.selected_invoice_address.email, None) self.assertEqual(our_customer.selected_shipping_address.phone, None) self.assertEqual(our_customer.selected_shipping_address.email, None) checkout_data = { 'invoice-firstname': 'bob', 'invoice-lastname': 'builder', 'invoice-line1': 'ie street', 'invoice-line2': 'ie area', 'invoice-city': 'ie city', 'invoice-state': 'carlow', 'invoice-country': "IE", 'invoice-email': '*****@*****.**', 'invoice-phone': '1234567', 'shipping-firstname': 'hans', 'shipping-lastname': 'schmidt', 'shipping-line1': 'orianenberger strasse', 'shipping-line2': 'ie area', 'shipping-city': 'ie city', 'shipping-state': 'carlow', 'shipping-country': "IE", 'shipping-email': '*****@*****.**', 'shipping-phone': '7654321', 'payment_method': self.by_invoice.id, } checkout_post_response = self.client.post(reverse('lfs_checkout'), checkout_data) self.assertRedirects( checkout_post_response, reverse('lfs_thank_you'), status_code=302, target_status_code=200, ) # check database quantities post-checkout self.assertEquals(Address.objects.count(), 4) self.assertEquals(Customer.objects.count(), 1) self.assertEquals(Order.objects.count(), 1) # check our customer details post checkout our_customer = Customer.objects.all()[0] self.assertEqual(our_customer.selected_invoice_address.phone, "1234567") self.assertEqual(our_customer.selected_invoice_address.email, "*****@*****.**") self.assertEqual(our_customer.selected_shipping_address.phone, '7654321') self.assertEqual(our_customer.selected_shipping_address.email, "*****@*****.**")
def setUp(self): """ """ ie = Country.objects.get(code="ie") gb = Country.objects.get(code="gb") de = Country.objects.get(code="de") us = Country.objects.get(code="us") shop = get_default_shop() for ic in Country.objects.all(): shop.invoice_countries.add(ic) shop.save() tax = Tax.objects.create(rate=19) shipping_method = ShippingMethod.objects.create(name="Standard", active=True, price=1.0, tax=tax) self.by_invoice = PaymentMethod.objects.get(pk=BY_INVOICE) address1 = Address.objects.create( firstname="John", lastname="Doe", company_name="Doe Ltd.", line1="Street 42", city="Gotham City", zip_code="2342", country=ie, ) address2 = Address.objects.create( firstname="Jane", lastname="Doe", company_name="Doe Ltd.", line1="Street 43", city="Smallville", zip_code="2443", country=us, ) self.username = "******" self.password = "******" new_user = User(username=self.username) new_user.set_password(self.password) new_user.save() self.customer = Customer.objects.create( user=new_user, selected_shipping_method=shipping_method, selected_payment_method=self.by_invoice, selected_shipping_address=address1, selected_invoice_address=address2, ) self.PRODUCT1_NAME = "Surfboard" p1 = Product.objects.create( name=self.PRODUCT1_NAME, slug="product-1", sku="sku-1", price=1.1, tax=tax, active=True ) p2 = Product.objects.create(name="Product 2", slug="product-2", sku="sku-2", price=2.2, tax=tax, active=True) cart = Cart.objects.create(user=new_user) item = CartItem.objects.create(cart=cart, product=p1, amount=2) item = CartItem.objects.create(cart=cart, product=p2, amount=3) self.c = Client()
def migrate_to_07(self, application, version): from lfs.catalog.models import Product from lfs.catalog.settings import VARIANT from lfs.core.utils import get_default_shop from lfs.addresses.models import Address from lfs.page.models import Page from lfs.shipping.models import ShippingMethod from lfs_order_numbers.models import OrderNumberGenerator # Product from lfs.catalog.settings import QUANTITY_FIELD_INTEGER from lfs.catalog.settings import QUANTITY_FIELD_TYPES db.add_column("catalog_product", "type_of_quantity_field", models.PositiveSmallIntegerField(_(u"Type of quantity field"), null=True, blank=True, choices=QUANTITY_FIELD_TYPES)) db.add_column("catalog_product", "category_variant", models.SmallIntegerField(_(u"Category variant"), blank=True, null=True)) db.add_column("catalog_product", "active_base_price", models.PositiveSmallIntegerField(_(u"Active base price"), default=0)) db.add_column("catalog_product", "base_price_unit", models.CharField(_(u"Base price unit"), blank=True, null=True, max_length=30, choices=settings.LFS_BASE_PRICE_UNITS)) db.add_column("catalog_product", "base_price_amount", models.FloatField(_(u"Base price amount"), default=0.0, blank=True, null=True)) if db.backend_name == "postgres": db.execute('ALTER TABLE catalog_product ALTER active_packing_unit TYPE smallint USING CASE WHEN active_packing_unit=FALSE THEN 0 ELSE 1 END;') else: db.alter_column('catalog_product', 'active_packing_unit', models.PositiveSmallIntegerField(_(u"Active packing"), default=0)) for product in Product.objects.all(): if product.active_packing_unit != 0: product.active_packing_unit = 1 product.save() # Pages print "Migrating to 0.7" db.add_column("page_page", "meta_title", models.CharField(_(u"Meta title"), blank=True, default="<title>", max_length=80)) db.add_column("page_page", "meta_keywords", models.TextField(_(u"Meta keywords"), null=True, blank=True)) db.add_column("page_page", "meta_description", models.TextField(_(u"Meta description"), null=True, blank=True)) for page in Page.objects.all(): page.meta_title = "<title>" page.meta_keywords = "" page.meta_description = "" page.save() # Copy the old page with id=1 and create a new one with id=1, which # will act as the root of all pages. try: page = Page.objects.get(pk=1) except Page.DoesNotExist: pass else: new_page = deepcopy(page) new_page.id = None new_page.save() page.delete() Page.objects.create(id=1, title="Root", slug="", active=1, exclude_from_navigation=1) # Shop db.add_column("core_shop", "meta_title", models.CharField(_(u"Meta title"), blank=True, default="<name>", max_length=80)) db.add_column("core_shop", "meta_keywords", models.TextField(_(u"Meta keywords"), null=True, blank=True)) db.add_column("core_shop", "meta_description", models.TextField(_(u"Meta description"), null=True, blank=True)) shop = get_default_shop() shop.meta_keywords = "" shop.meta_description = "" shop.save() # Order db.add_column("order_order", "number", models.CharField(max_length=30, unique=True, null=True)) OrderNumberGenerator.objects.create(pk="1", last=0) # Add new lines db.add_column("order_order", "invoice_company_name", models.CharField(null=True, blank=True, max_length=100)) db.add_column("order_order", "shipping_company_name", models.CharField(null=True, blank=True, max_length=100)) # Shipping Method db.add_column("shipping_shippingmethod", "price_calculator", models.CharField(max_length=200, choices=settings.LFS_SHIPPING_METHOD_PRICE_CALCULATORS, default=settings.LFS_SHIPPING_METHOD_PRICE_CALCULATORS[0][0])) for shipping_method in ShippingMethod.objects.all(): shipping_method.price_calculator = settings.LFS_SHIPPING_METHOD_PRICE_CALCULATORS[0][0] shipping_method.save() # Static Block db.add_column("catalog_staticblock", "position", models.PositiveSmallIntegerField(_(u"Position"), default=999)) # Addresses db.add_column("customer_address", "line1", models.CharField(_("Line 1"), max_length=100, blank=True, null=True)) db.add_column("customer_address", "line2", models.CharField(_("Line 2"), max_length=100, blank=True, null=True)) cursor = connection.cursor() cursor.execute("""SELECT id, street FROM customer_address""") for row in cursor.fetchall(): address = Address.objects.get(pk=row[0]) address.line1 = row[1] address.save() db.delete_column("customer_address", "street") application.version = "0.7" application.save()
def clean(self): """ """ msg = _(u"This field is required.") if self.data.get("is_anonymous") == "1" and \ getattr(settings, "LFS_INVOICE_EMAIL_REQUIRED") and \ self.cleaned_data.get("invoice_email") == "": self._errors["invoice_email"] = ErrorList([msg]) if not self.cleaned_data.get("no_shipping"): if self.cleaned_data.get("shipping_firstname") == "": self._errors["shipping_firstname"] = ErrorList([msg]) if self.cleaned_data.get("shipping_lastname") == "": self._errors["shipping_lastname"] = ErrorList([msg]) if getattr(settings, "LFS_SHIPPING_COMPANY_NAME_REQUIRED", False): if self.cleaned_data.get("shipping_company_name") == "": self._errors["shipping_company_name"] = ErrorList([msg]) if getattr(settings, "LFS_SHIPPING_PHONE_REQUIRED", False): if self.cleaned_data.get("shipping_phone") == "": self._errors["shipping_phone"] = ErrorList([msg]) if getattr(settings, "LFS_SHIPPING_EMAIL_REQUIRED", False): if self.cleaned_data.get("shipping_email") == "": self._errors["shipping_email"] = ErrorList([msg]) # check that shipping country is in the shops shipping countries list shop = get_default_shop() shipping_countries = shop.shipping_countries.all() shipping_country = None if not self.cleaned_data.get("no_shipping"): shipping_country_code = self.data.get("shipping-country", None) if shipping_country_code: shipping_country = Country.objects.get( code=shipping_country_code.lower()) if shipping_country: if shipping_country not in shipping_countries: msg = _(u"Invalid shipping country.") #self._errors["all"] = ErrorList([msg]) raise forms.ValidationError("Invalid Shipping Country") else: shipping_country_code = self.data.get("invoice-country", None) if shipping_country_code: shipping_country = Country.objects.get( code=shipping_country_code.lower()) # Check data of selected payment method payment_method_id = self.data.get("payment_method") payment_method = PaymentMethod.objects.get(pk=payment_method_id) if payment_method.type == lfs.payment.settings.PM_BANK: if self.cleaned_data.get("account_number", "") == "": self._errors["account_number"] = ErrorList([msg]) if self.cleaned_data.get("bank_identification_code", "") == "": self._errors["bank_identification_code"] = ErrorList([msg]) if self.cleaned_data.get("bank_name", "") == "": self._errors["bank_name"] = ErrorList([msg]) if self.cleaned_data.get("depositor", "") == "": self._errors["depositor"] = ErrorList([msg]) elif payment_method.type == lfs.payment.settings.PM_CREDIT_CARD: if self.cleaned_data.get("credit_card_owner", "") == "": self._errors["credit_card_owner"] = ErrorList([msg]) if self.cleaned_data.get("credit_card_number", "") == "": self._errors["credit_card_number"] = ErrorList([msg]) if self.cleaned_data.get("credit_card_verification", "") == "": self._errors["credit_card_verification"] = ErrorList([msg]) return self.cleaned_data
def transaction_view(request, tx_id): txn = get_object_or_404(CompropagoTransaction, pk=tx_id) if not txn.payment_type: return payment_selector_view(request, txn) if not txn.payment_status: shop = get_default_shop(request) api = CompropagoAPI(api_key = settings.LFS_COMPROPAGO_API_KEY) getcontext().prec=6 c = CompropagoCharge( order_id = str(txn.order.number), order_price = str(to_mxn_banxico(txn.order.price)), order_name = shop.name, customer_name = txn.order.user.get_full_name() or txn.order.user.email, customer_email = txn.order.user.email, payment_type = txn.payment_type ) r = api.charge(c) if r['api_version'] == '1.0': txn.payment_id = r['payment_id'] txn.short_payment_id = r['short_payment_id'] txn.payment_status = r['payment_status'] txn.creation_date = parse_date(r['creation_date'], ignoretz=True) txn.expiration_date = parse_date(r['expiration_date'], ignoretz=True) txn.updated_date = datetime.now() txn.product_information = json.dumps(r['product_information']) txn.payment_instructions = json.dumps(r['payment_instructions']) elif r['api_version'] == '1.1': txn.payment_id = r['id'] txn.short_payment_id = r['short_id'] txn.payment_status = r['status'].upper() txn.creation_date = datetime.fromtimestamp(int(r['created'])) txn.expiration_date = datetime.fromtimestamp(int(r['exp_date'])) txn.updated_date = datetime.now() order_info = r['order_info'] txn.product_information = json.dumps({ "product_id": order_info['order_id'], "product_name": order_info['order_name'], "product_price": order_info['order_price'], }) instr = r['instructions'] details = instr['details'] txn.payment_instructions = json.dumps({ "step_1": instr['step_1'], "step_2": instr['step_2'], "step_3": instr['step_3'], "note_confirmation": instr['note_confirmation'], "description": instr['description'], "note_expiration_date": instr['note_expiration_date'], "details": { "payment_store": details['store'], "payment_amount": details['amount'], "bank_name": details['bank_name'], "bank_account_number": details['bank_account_number'] }, "note_extra_comition": instr['note_extra_comition'], }) txn.save() if txn.payment_status in ['PENDING', 'charge.pending']: template_name ='compropago/payment_instructions.html' else: template_name ='compropago/transaction_state.html' template_vars = { 'payment_type_name': dict(txn.PAYMENT_TYPE_CHOICES)[txn.payment_type], 'logo_filename': '%s.png' % txn.payment_type.lower(), 'transaction': txn, 'instructions': json.loads(txn.payment_instructions), 'order': txn.order, } return render_to_response( template_name, RequestContext(request, template_vars) )