flask-galatea_cart-back/cart.py

873 lines
30 KiB
Python
Raw Normal View History

2014-12-04 11:18:06 +01:00
from flask import Blueprint, render_template, current_app, abort, g, url_for, \
2014-07-28 19:08:08 +02:00
flash, redirect, session, request, jsonify
2014-07-24 16:55:43 +02:00
from galatea.tryton import tryton
from galatea.csrf import csrf
2014-07-28 19:08:08 +02:00
from galatea.utils import thumbnail
2014-10-27 15:34:20 +01:00
from galatea.helpers import login_required
2015-02-04 15:00:03 +01:00
from flask.ext.babel import gettext as _, lazy_gettext, ngettext
2014-07-24 16:55:43 +02:00
from flask.ext.wtf import Form
from wtforms import TextField, SelectField, IntegerField, validators
from trytond.transaction import Transaction
2014-07-24 16:55:43 +02:00
from decimal import Decimal
from emailvalid import check_email
import vatnumber
cart = Blueprint('cart', __name__, template_folder='templates')
2014-12-04 11:18:06 +01:00
GALATEA_WEBSITE = current_app.config.get('TRYTON_GALATEA_SITE')
2014-07-25 09:29:38 +02:00
SHOP = current_app.config.get('TRYTON_SALE_SHOP')
SHOPS = current_app.config.get('TRYTON_SALE_SHOPS')
CART_CROSSSELLS = current_app.config.get('TRYTON_CART_CROSSSELLS', True)
LIMIT_CROSSELLS = current_app.config.get('TRYTON_CATALOG_LIMIT_CROSSSELLS', 10)
MINI_CART_CODE = current_app.config.get('TRYTON_CATALOG_MINI_CART_CODE', False)
2014-07-24 16:55:43 +02:00
2014-12-04 11:18:06 +01:00
Website = tryton.pool.get('galatea.website')
2014-07-24 16:55:43 +02:00
Cart = tryton.pool.get('sale.cart')
2014-07-25 09:29:38 +02:00
Template = tryton.pool.get('product.template')
2014-07-24 16:55:43 +02:00
Product = tryton.pool.get('product.product')
Shop = tryton.pool.get('sale.shop')
Carrier = tryton.pool.get('carrier')
Party = tryton.pool.get('party.party')
Address = tryton.pool.get('party.address')
Sale = tryton.pool.get('sale.sale')
SaleLine = tryton.pool.get('sale.line')
Country = tryton.pool.get('country.country')
Subdivision = tryton.pool.get('country.subdivision')
2014-07-24 16:55:43 +02:00
2014-12-16 10:19:01 +01:00
PRODUCT_TYPE_STOCK = ['goods', 'assets']
2014-07-24 16:55:43 +02:00
CART_ORDER = [
('cart_date', 'DESC'),
('id', 'DESC'),
]
VAT_COUNTRIES = [('', '')]
for country in vatnumber.countries():
VAT_COUNTRIES.append((country, country))
2014-07-28 12:53:54 +02:00
class ShipmentAddressForm(Form):
"Shipment Address form"
2014-10-29 09:44:14 +01:00
shipment_name = TextField(lazy_gettext('Name'), [validators.Required()])
shipment_street = TextField(lazy_gettext('Street'), [validators.Required()])
shipment_city = TextField(lazy_gettext('City'), [validators.Required()])
shipment_zip = TextField(lazy_gettext('Zip'), [validators.Required()])
shipment_country = SelectField(lazy_gettext('Country'), [validators.Required(), ], coerce=int)
shipment_subdivision = IntegerField(lazy_gettext('Subdivision'), [validators.Required()])
2014-10-29 10:01:17 +01:00
shipment_email = TextField(lazy_gettext('E-mail'), [validators.Required(), validators.Email()])
2014-10-29 09:44:14 +01:00
shipment_phone = TextField(lazy_gettext('Phone'))
vat_country = SelectField(lazy_gettext('VAT Country'), [validators.Required(), ])
vat_number = TextField(lazy_gettext('VAT Number'), [validators.Required()])
2014-07-24 16:55:43 +02:00
def __init__(self, *args, **kwargs):
Form.__init__(self, *args, **kwargs)
def validate(self):
rv = Form.validate(self)
if not rv:
return False
return True
@cart.route('/json/my-cart', methods=['GET', 'PUT'], endpoint="my-cart")
2014-07-28 19:08:08 +02:00
@tryton.transaction()
def my_cart(lang):
'''All Carts JSON'''
items = []
shop = Shop(SHOP)
domain = [
('state', '=', 'draft'),
2014-10-02 19:06:17 +02:00
('shop', '=', SHOP),
2014-07-28 19:08:08 +02:00
]
if session.get('user'): # login user
domain.append(['OR',
('sid', '=', session.sid),
('galatea_user', '=', session['user']),
])
else: # anonymous user
domain.append(
('sid', '=', session.sid),
)
2015-02-23 18:49:08 +01:00
carts = Cart.search(domain, order=CART_ORDER)
2014-07-28 19:08:08 +02:00
decimals = "%0."+str(shop.esale_currency.digits)+"f" # "%0.2f" euro
2014-07-28 19:08:08 +02:00
for cart in carts:
2015-02-23 18:49:08 +01:00
img = cart.product.template.esale_default_images
2014-07-28 19:08:08 +02:00
image = current_app.config.get('BASE_IMAGE')
if img.get('small'):
thumbname = img['small']['name']
filename = img['small']['digest']
image = thumbnail(filename, thumbname, '200x200')
items.append({
2015-02-23 18:49:08 +01:00
'id': cart.id,
'name': cart.product.code if MINI_CART_CODE else cart.product.rec_name,
2014-07-28 19:08:08 +02:00
'url': url_for('catalog.product_'+g.language, lang=g.language,
2015-02-23 18:49:08 +01:00
slug=cart.product.template.esale_slug),
'quantity': cart.quantity,
'unit_price': float(Decimal(decimals % cart.unit_price)),
'unit_price_w_tax': float(Decimal(decimals % cart.unit_price_w_tax)),
'untaxed_amount': float(Decimal(decimals % cart.untaxed_amount)),
'amount_w_tax': float(Decimal(decimals % cart.amount_w_tax)),
2014-07-28 19:08:08 +02:00
'image': image,
})
return jsonify(result={
'currency': shop.esale_currency.symbol,
'items': items,
})
2014-07-24 16:55:43 +02:00
@cart.route("/confirm/", methods=["POST"], endpoint="confirm")
@tryton.transaction()
def confirm(lang):
'''Convert carts to sale order
Return to Sale Details
'''
2014-07-25 09:29:38 +02:00
shop = Shop(SHOP)
2014-07-24 16:55:43 +02:00
data = request.form
party = session.get('customer')
shipment_address = data.get('shipment_address')
2014-07-28 12:53:54 +02:00
name = data.get('shipment_name')
email = data.get('shipment_email')
2014-07-24 16:55:43 +02:00
# Get all carts
domain = [
('state', '=', 'draft'),
2014-10-02 19:06:17 +02:00
('shop', '=', SHOP),
2014-07-24 16:55:43 +02:00
]
if session.get('user'): # login user
domain.append(['OR',
('sid', '=', session.sid),
('galatea_user', '=', session['user']),
])
else: # anonymous user
domain.append(
('sid', '=', session.sid),
)
carts = Cart.search(domain)
if not carts:
flash(_('There are not products in your cart.'), 'danger')
return redirect(url_for('.cart', lang=g.language))
# New party
if party:
party = Party(party)
else:
if not check_email(email):
2014-07-25 11:35:24 +02:00
flash(_('Email "{email}" is not valid.').format(
2014-07-24 16:55:43 +02:00
email=email), 'danger')
return redirect(url_for('.cart', lang=g.language))
2014-07-25 09:29:38 +02:00
party = Party.esale_create_party(shop, {
2014-07-24 16:55:43 +02:00
'name': name,
'esale_email': email,
'vat_country': data.get('vat_country', None),
'vat_number': data.get('vat_number', None),
})
session['customer'] = party.id
if shipment_address != 'new-address':
address = Address(shipment_address)
else:
country = None
2014-07-28 12:53:54 +02:00
if data.get('shipment_country'):
country = int(data.get('shipment_country'))
2014-07-24 16:55:43 +02:00
subdivision = None
2014-07-28 12:53:54 +02:00
if data.get('shipment_subdivision'):
subdivision = int(data.get('shipment_subdivision'))
2014-07-24 16:55:43 +02:00
values = {
'name': name,
2014-07-28 12:53:54 +02:00
'street': data.get('shipment_street'),
'city': data.get('shipment_city'),
'zip': data.get('shipment_zip'),
2014-07-24 16:55:43 +02:00
'country': country,
'subdivision': subdivision,
2014-07-28 12:53:54 +02:00
'phone': data.get('shipment_phone'),
2014-07-24 16:55:43 +02:00
'email': email,
'fax': None,
}
2014-07-25 09:29:38 +02:00
address = Address.esale_create_address(shop, party, values)
2014-07-24 16:55:43 +02:00
# Carts are same party to create a new sale
Cart.write(carts, {'party': party})
# Create new sale
values = {}
values['shipment_cost_method'] = 'order' # force shipment invoice on order
values['shipment_address'] = address
payment_type = data.get('payment_type')
if payment_type:
values['payment_type'] = int(payment_type)
carrier = data.get('carrier')
if carrier:
values['carrier'] = int(carrier)
comment = data.get('comment')
if comment:
values['comment'] = comment
2014-10-09 12:32:00 +02:00
sales, error = Cart.create_sale(carts, values)
if error:
if not session.get('logged_in') and session.get('customer'):
session.pop('customer', None)
2014-10-09 12:32:00 +02:00
current_app.logger.error('Sale. Error create sale from party (%s): %s' % (party.id, error))
2014-07-24 16:55:43 +02:00
if not sales:
2014-07-25 11:35:24 +02:00
flash(_('It has not been able to convert the cart into an order. ' \
'Try again or contact us.'), 'danger')
2014-07-24 16:55:43 +02:00
return redirect(url_for('.cart', lang=g.language))
sale, = sales
# Add shipment line
carrier_price = data.get('carrier-cost')
if carrier_price:
product = shop.esale_delivery_product
shipment_price = Decimal(carrier_price)
shipment_line = SaleLine.get_shipment_line(product, shipment_price, sale)
shipment_line.save()
2014-07-24 16:55:43 +02:00
# sale draft to quotation
2015-02-03 13:49:55 +01:00
try:
Sale.quote([sale])
except Exception as e:
current_app.logger.info(e)
2014-07-24 16:55:43 +02:00
if current_app.debug:
current_app.logger.info('Sale. Create sale %s' % sale.id)
2015-02-04 15:00:03 +01:00
flash(_('Successfully created Sale Order.'), 'success')
2014-07-24 16:55:43 +02:00
return redirect(url_for('sale.sale', lang=g.language, id=sale.id))
@csrf.exempt
2014-07-24 16:55:43 +02:00
@cart.route("/add/", methods=["POST"], endpoint="add")
@tryton.transaction()
def add(lang):
'''Add product item cart'''
websites = Website.search([
('id', '=', GALATEA_WEBSITE),
], limit=1)
if not websites:
abort(404)
website, = websites
2014-07-24 16:55:43 +02:00
to_create = []
to_update = []
to_remove = []
to_remove_products = [] # Products in older cart and don't sell
# Convert form values to dict values {'id': 'qty'}
values = {}
2014-10-08 19:27:22 +02:00
codes = []
2014-07-28 19:08:08 +02:00
# json request
if request.json:
for data in request.json:
if data.get('name'):
2014-11-13 11:46:14 +01:00
prod = data.get('name').split('-')
2014-07-28 19:08:08 +02:00
try:
2014-10-08 19:27:22 +02:00
qty = float(data.get('value'))
2014-07-28 19:08:08 +02:00
except:
2014-10-09 09:09:42 +02:00
qty = 1
2014-10-08 19:27:22 +02:00
try:
2014-11-13 11:46:14 +01:00
values[int(prod[1])] = qty
2014-10-08 19:27:22 +02:00
except:
2014-11-13 11:46:14 +01:00
values[prod[1]] = qty
codes.append(prod[1])
2014-10-08 19:27:22 +02:00
if not values:
return jsonify(result=False)
2014-07-28 19:08:08 +02:00
# post request
else:
for k, v in request.form.iteritems():
2014-11-13 11:46:14 +01:00
prod = k.split('-')
if prod[0] == 'product':
2014-07-28 19:08:08 +02:00
try:
2014-10-08 19:27:22 +02:00
qty = float(v)
2014-07-28 19:08:08 +02:00
except:
flash(_('You try to add no numeric quantity. ' \
'The request has been stopped.'))
return redirect(url_for('.cart', lang=g.language))
2014-10-08 19:27:22 +02:00
try:
2014-11-13 11:46:14 +01:00
values[int(prod[1])] = qty
2014-10-08 19:27:22 +02:00
except:
2014-11-13 11:46:14 +01:00
values[prod[1]] = qty
codes.append(prod[1])
2014-10-08 19:27:22 +02:00
# transform product code to id
if codes:
2015-02-23 18:49:08 +01:00
products = Product.search([('code', 'in', codes)])
2014-10-08 19:27:22 +02:00
# reset dict
vals = values.copy()
values = {}
2014-10-08 19:28:27 +02:00
2014-10-08 19:27:22 +02:00
for k, v in vals.items():
2014-11-13 11:46:14 +01:00
for prod in products:
2015-02-23 18:49:08 +01:00
if prod.code == k:
2014-11-13 11:46:14 +01:00
values[prod['id']] = v
2014-10-09 09:05:50 +02:00
break
2014-07-24 16:55:43 +02:00
# Remove items in cart
removes = request.form.getlist('remove')
# Products Current User Cart (products to send)
products_current_cart = [k for k,v in values.iteritems()]
# Search current cart by user or session
domain = [
('state', '=', 'draft'),
2014-10-02 19:06:17 +02:00
('shop', '=', SHOP),
2014-07-24 16:55:43 +02:00
('product.id', 'in', products_current_cart)
]
if session.get('user'): # login user
domain.append(['OR',
('sid', '=', session.sid),
('galatea_user', '=', session['user']),
])
else: # anonymous user
domain.append(
('sid', '=', session.sid),
)
carts = Cart.search(domain, order=[('cart_date', 'ASC')])
# Products Current Cart (products available in sale.cart)
products_in_cart = [c.product.id for c in carts]
# Get product data
products = Product.search([
2014-07-24 16:55:43 +02:00
('id', 'in', products_current_cart),
('template.esale_available', '=', True),
('template.esale_active', '=', True),
2014-11-06 00:08:00 +01:00
('template.esale_saleshops', 'in', [SHOP]),
])
2014-07-24 16:55:43 +02:00
# Delete products data
if removes:
for remove in removes:
for cart in carts:
try:
if cart.id == int(remove):
to_remove.append(cart)
break
except:
2014-07-25 11:35:24 +02:00
flash(_('You try to remove no numeric cart. ' \
'The request has been stopped.'))
2014-07-24 16:55:43 +02:00
return redirect(url_for('.cart', lang=g.language))
# Add/Update products data
for product_id, qty in values.iteritems():
2014-11-13 11:46:14 +01:00
product = None
for p in products:
if p.id == product_id:
product = p
2014-07-24 16:55:43 +02:00
break
2014-11-13 11:46:14 +01:00
if not product or not product.add_cart:
2014-09-19 14:34:35 +02:00
continue
# Add cart if have stock
if website.esale_stock:
if website.esale_stock_qty == 'forecast_quantity':
quantity = product.esale_forecast_quantity
else:
quantity = product.esale_quantity
if product.type in PRODUCT_TYPE_STOCK and not (quantity > 0 and qty <= quantity):
flash(_('Not enought stock for the product "{product}" (maximun: {quantity} units).').format(
product=product.rec_name, quantity=quantity), 'danger')
continue
2014-09-25 17:48:23 +02:00
cart = Cart()
cart.party = session.get('customer', None)
cart.quantity = qty
cart.product = product.id
cart.sid = session.sid
cart.galatea_user = session.get('user', None)
vals = cart.on_change_product()
2014-07-24 16:55:43 +02:00
# Create data
if product_id not in products_in_cart and qty > 0:
2014-09-25 17:48:23 +02:00
vals['party'] = session.get('customer', None)
vals['quantity'] = qty
vals['product'] = product.id
vals['sid'] = session.sid
vals['galatea_user'] = session.get('user', None)
to_create.append(vals)
2014-07-24 16:55:43 +02:00
# Update data
if product_id in products_in_cart:
for cart in carts:
if cart.product.id == product_id:
if qty > 0:
2014-09-25 17:48:23 +02:00
vals['quantity'] = qty
2014-07-24 16:55:43 +02:00
to_update.append({
'cart': cart,
2014-09-25 17:48:23 +02:00
'values': vals,
2014-07-24 16:55:43 +02:00
})
else: # Remove data when qty <= 0
to_remove.append(cart)
break
# Add to remove older products
if to_remove_products:
for remove in to_remove_products:
for cart in carts:
if cart.product.id == remove:
to_remove.append(cart)
break
# Add Cart
if to_create:
Cart.create(to_create)
2015-02-04 15:00:03 +01:00
flash(ngettext(
'%(num)s product has been added in your cart.',
'%(num)s products have been added in your cart.',
len(to_create)), 'success')
2014-07-24 16:55:43 +02:00
# Update Cart
if to_update:
for update in to_update:
Cart.write([update['cart']], update['values'])
total = len(to_update)
if to_remove:
total = total-len(to_remove)
2015-02-04 15:00:03 +01:00
flash(ngettext(
'%(num)s product has been updated in your cart.',
'%(num)s products have been updated in your cart.',
len(to_update)), 'success')
2014-07-24 16:55:43 +02:00
# Delete Cart
if to_remove:
Cart.delete(to_remove)
2015-02-04 15:00:03 +01:00
flash(ngettext(
'%(num)s product has been deleted in your cart.',
'%(num)s products have been deleted in your cart.',
len(to_remove)), 'success')
2014-07-24 16:55:43 +02:00
2014-07-28 19:08:08 +02:00
if request.json:
# Add JSON messages (success, warning)
success = []
warning = []
for f in session.get('_flashes', []):
if f[0] == 'success':
success.append(f[1])
else:
warning.append(f[1])
messages = {}
messages['success'] = ",".join(success)
messages['warning'] = ",".join(warning)
session.pop('_flashes', None)
return jsonify(result=True, messages=messages)
2014-07-28 19:08:08 +02:00
else:
return redirect(url_for('.cart', lang=g.language))
2014-07-24 16:55:43 +02:00
2014-07-28 12:53:54 +02:00
@cart.route("/checkout/", methods=["GET", "POST"], endpoint="checkout")
@tryton.transaction()
def checkout(lang):
'''Checkout user or session'''
2014-12-04 11:18:06 +01:00
websites = Website.search([
('id', '=', GALATEA_WEBSITE),
], limit=1)
if not websites:
abort(404)
website, = websites
2014-07-28 12:53:54 +02:00
values = {}
errors = []
shop = Shop(SHOP)
domain = [
('state', '=', 'draft'),
2014-10-02 19:06:17 +02:00
('shop', '=', SHOP),
2014-07-28 12:53:54 +02:00
]
if session.get('user'): # login user
domain.append(['OR',
('sid', '=', session.sid),
('galatea_user', '=', session['user']),
])
else: # anonymous user
domain.append(
('sid', '=', session.sid),
)
2015-02-04 10:23:59 +01:00
carts = Cart.search(domain, order=CART_ORDER)
2014-07-28 12:53:54 +02:00
if not carts:
flash(_('There are not products in your cart.'), 'danger')
return redirect(url_for('.cart', lang=g.language))
untaxed_amount = Decimal(0)
tax_amount = Decimal(0)
total_amount = Decimal(0)
for cart in carts:
2015-02-04 10:23:59 +01:00
untaxed_amount += cart.untaxed_amount
tax_amount += cart.amount_w_tax - cart.untaxed_amount
total_amount += cart.amount_w_tax
# checkout stock available
if website.esale_stock:
if cart.product.type not in PRODUCT_TYPE_STOCK:
continue
if website.esale_stock_qty == 'forecast_quantity':
quantity = cart.product.esale_forecast_quantity
else:
quantity = cart.product.esale_quantity
if not (cart.quantity > 0 and cart.quantity <= quantity):
flash(_('Not enought stock for the product "{product}" (maximun: {quantity} units).').format(
product=cart.product.rec_name, quantity=quantity), 'danger')
2015-02-04 10:23:59 +01:00
return redirect(url_for('.cart', lang=g.language))
party = None
if session.get('customer'):
party = Party(session.get('customer'))
2014-07-28 12:53:54 +02:00
# Shipment Address
2014-07-28 19:08:08 +02:00
#~ form_shipment_address = ShipmentAddressForm()
2014-07-28 12:53:54 +02:00
shipment_address = request.form.get('shipment_address')
if not shipment_address:
flash(_('Select a Shipment Address.'), 'danger')
return redirect(url_for('.cart', lang=g.language))
values['shipment_address'] = shipment_address
if shipment_address == 'new-address':
values['shipment_name'] = request.form.get('shipment_name')
values['shipment_street'] = request.form.get('shipment_street')
values['shipment_zip'] = request.form.get('shipment_zip')
values['shipment_city'] = request.form.get('shipment_city')
values['shipment_phone'] = request.form.get('shipment_phone')
if session.get('email'):
values['shipment_email'] = session['email']
else:
shipment_email = request.form.get('shipment_email')
if not check_email(shipment_email):
errors.append(_('Email not valid.'))
values['shipment_email'] = shipment_email
shipment_country = request.form.get('shipment_country')
if shipment_country:
values['shipment_country'] = shipment_country
country, = Country.browse([shipment_country])
values['shipment_country_name'] = country.name
shipment_subdivision = request.form.get('shipment_subdivision')
if shipment_subdivision:
values['shipment_subdivision'] = shipment_subdivision
subdivision, = Subdivision.browse([shipment_subdivision])
values['shipment_subdivision_name'] = subdivision.name
2014-07-28 12:53:54 +02:00
if not values['shipment_name'] or not values['shipment_street'] \
or not values['shipment_zip'] or not values['shipment_city'] \
or not values['shipment_email']:
errors.append(_('Error when validate Shipment Address. ' \
'Please, return to cart and complete Shipment Address'))
vat_country = request.form.get('vat_country')
vat_number = request.form.get('vat_number')
if vat_number:
values['vat_number'] = vat_number
if vat_country:
values['vat_country'] = vat_country
if vat_country and vat_number:
vat_number = '%s%s' % (vat_country.upper(), vat_number)
if not vatnumber.check_vat(vat_number):
errors.append(_('VAT not valid.'))
elif party:
2014-07-28 12:53:54 +02:00
addresses = Address.search([
('party', '=', party),
2014-07-28 12:53:54 +02:00
('id', '=', int(shipment_address)),
('active', '=', True),
], order=[('sequence', 'ASC'), ('id', 'ASC')])
if addresses:
address, = addresses
values['shipment_address_name'] = address.full_address
2014-07-28 12:53:54 +02:00
else:
errors.append(_('We can found address related yours address. ' \
'Please, select a new address in Shipment Address'))
else:
errors.append(_('You not select new address and not a customer. ' \
'Please, select a new address in Shipment Address'))
# Payment
payment = int(request.form.get('payment'))
payment_type = None
if party and hasattr(party, 'customer_payment_type'):
if party.customer_payment_type:
payment_type = party.customer_payment_type
values['payment'] = payment_type.id
values['payment_name'] = payment_type.rec_name
if not payment_type:
for p in shop.esale_payments:
if p.payment_type.id == payment:
payment_type = p.payment_type
values['payment'] = payment_type.id
values['payment_name'] = payment_type.rec_name
break
2014-07-28 12:53:54 +02:00
# Carrier
carrier_id = request.form.get('carrier')
if carrier_id:
carrier = Carrier(carrier_id)
# create a virtual sale
sale = Sale()
sale.untaxed_amount = untaxed_amount
sale.tax_amount = tax_amount
sale.total_amount = total_amount
sale.carrier = carrier
sale.payment_type = payment_type
context = {}
context['record'] = sale # Eval by "carrier formula" require "record"
context['carrier'] = carrier
with Transaction().set_context(context):
carrier_price = carrier.get_sale_price() # return price, currency
price = carrier_price[0]
price_w_tax = carrier.get_sale_price_w_tax(price)
values['carrier'] = carrier
values['carrier_name'] = carrier.rec_name
values['carrier_cost'] = price
values['carrier_cost_w_tax'] = price_w_tax
2014-07-28 12:53:54 +02:00
# Comment
values['comment'] = request.form.get('comment')
# Breadcumbs
breadcrumbs = [{
'slug': url_for('.cart', lang=g.language),
'name': _('Cart'),
}, {
'slug': url_for('.cart', lang=g.language),
2014-07-28 12:53:54 +02:00
'name': _('Checkout'),
}]
return render_template('checkout.html',
2014-12-04 11:18:06 +01:00
website=website,
2014-07-28 12:53:54 +02:00
breadcrumbs=breadcrumbs,
shop=shop,
carts=carts,
values=values,
errors=errors,
prices={
'untaxed_amount': untaxed_amount,
'tax_amount': tax_amount,
'total_amount': total_amount,
},
2014-07-28 12:53:54 +02:00
)
2014-07-24 16:55:43 +02:00
@cart.route("/", endpoint="cart")
@tryton.transaction()
def cart_list(lang):
'''Cart by user or session'''
2014-12-04 11:18:06 +01:00
websites = Website.search([
('id', '=', GALATEA_WEBSITE),
], limit=1)
if not websites:
abort(404)
website, = websites
2014-07-25 09:29:38 +02:00
shop = Shop(SHOP)
2014-07-24 16:55:43 +02:00
2014-07-28 12:53:54 +02:00
form_shipment_address = ShipmentAddressForm(
shipment_country=shop.esale_country.id,
2014-07-25 09:29:38 +02:00
vat_country=shop.esale_country.code)
countries = [(c.id, c.name) for c in shop.esale_countrys]
2014-07-28 12:53:54 +02:00
form_shipment_address.shipment_country.choices = countries
form_shipment_address.vat_country.choices = VAT_COUNTRIES
2014-07-24 16:55:43 +02:00
domain = [
('state', '=', 'draft'),
2014-10-02 19:06:17 +02:00
('shop', '=', SHOP),
2014-07-24 16:55:43 +02:00
]
if session.get('user'): # login user
domain.append(['OR',
('sid', '=', session.sid),
('galatea_user', '=', session['user']),
])
else: # anonymous user
domain.append(
('sid', '=', session.sid),
)
2015-02-23 18:49:08 +01:00
carts = Cart.search(domain, order=CART_ORDER)
products = []
untaxed_amount = Decimal(0)
tax_amount = Decimal(0)
total_amount = Decimal(0)
for cart in carts:
2015-02-23 18:49:08 +01:00
products.append(cart.product.id)
untaxed_amount += cart.untaxed_amount
tax_amount += cart.amount_w_tax - cart.untaxed_amount
total_amount += cart.amount_w_tax
2014-07-24 16:55:43 +02:00
party = None
addresses = []
delivery_addresses = []
invoice_addresses = []
2014-07-24 16:55:43 +02:00
if session.get('customer'):
party = Party(session.get('customer'))
for address in party.addresses:
addresses.append(address)
if address.delivery:
delivery_addresses.append(address)
if address.invoice:
invoice_addresses.append(address)
2014-07-24 16:55:43 +02:00
# Get payments. Shop payments or Party payment
payments = []
default_payment = None
if shop.esale_payments:
default_payment = shop.esale_payments[0].payment_type
if party:
if hasattr(party, 'customer_payment_type'):
if party.customer_payment_type:
payments = [party.customer_payment_type]
if not payments:
payments = [payment.payment_type for payment in shop.esale_payments]
# Get carriers. Shop carriers or Party carrier
stockable = Carrier.get_products_stockable(products)
2014-07-24 16:55:43 +02:00
carriers = []
if stockable:
# create a virtual sale
sale = Sale()
sale.untaxed_amount = untaxed_amount
sale.tax_amount = tax_amount
sale.total_amount = total_amount
sale.payment_type = default_payment
context = {}
context['record'] = sale # Eval by "carrier formula" require "record"
if party:
if hasattr(party, 'carrier'):
carrier = party.carrier
sale.carrier = carrier
if carrier:
context['carrier'] = carrier
with Transaction().set_context(context):
carrier_price = carrier.get_sale_price() # return price, currency
price = carrier_price[0]
price_w_tax = carrier.get_sale_price_w_tax(price)
carriers.append({
'id': party.carrier.id,
'name': party.carrier.rec_name,
'price': price,
'price_w_tax': price_w_tax,
})
if not carriers:
for c in shop.esale_carriers:
carrier = c.carrier
sale.carrier = carrier
context['carrier'] = carrier
with Transaction().set_context(context):
carrier_price = carrier.get_sale_price() # return price, currency
price = carrier_price[0]
price_w_tax = carrier.get_sale_price_w_tax(price)
carriers.append({
'id': carrier.id,
'name': carrier.rec_name,
'price': price,
'price_w_tax': price_w_tax,
})
2014-07-24 16:55:43 +02:00
2014-07-25 09:29:55 +02:00
# Cross Sells
crossells = []
if CART_CROSSSELLS:
2015-02-23 18:49:08 +01:00
template_ids = list({c.product.template.id for c in carts})
templates = Template.browse(template_ids)
crossells_ids = set()
2014-07-28 19:08:08 +02:00
for template in templates:
2015-02-23 18:49:08 +01:00
for crossell in template.esale_crosssells_by_shop:
crossells_ids.add(crossell.id)
2014-07-25 09:29:55 +02:00
if crossells_ids:
2015-02-23 18:49:08 +01:00
crossells = Template.browse(list(crossells_ids)[:LIMIT_CROSSELLS])
2014-07-25 09:29:55 +02:00
2014-07-28 12:53:54 +02:00
# Breadcumbs
2014-07-24 16:55:43 +02:00
breadcrumbs = [{
'slug': url_for('.cart', lang=g.language),
'name': _('Cart'),
}]
return render_template('cart.html',
2014-12-04 11:18:06 +01:00
website=website,
2014-07-24 16:55:43 +02:00
breadcrumbs=breadcrumbs,
2014-07-25 09:29:38 +02:00
shop=shop,
2014-07-24 16:55:43 +02:00
carts=carts,
2014-07-28 12:53:54 +02:00
form_shipment_address=form_shipment_address,
2014-07-24 16:55:43 +02:00
addresses=addresses,
delivery_addresses=delivery_addresses,
invoice_addresses=invoice_addresses,
2014-07-25 09:29:55 +02:00
crossells=crossells,
payments=payments,
2014-07-24 16:55:43 +02:00
carriers=sorted(carriers, key=lambda k: k['price']),
stockable=stockable,
prices={
'untaxed_amount': untaxed_amount,
'tax_amount': tax_amount,
'total_amount': total_amount,
},
2014-07-24 16:55:43 +02:00
)
2014-10-27 15:34:20 +01:00
@cart.route("/pending", endpoint="cart-pending")
@login_required
@tryton.transaction()
def cart_pending(lang):
'''Last cart pending'''
order = [
('cart_date', 'DESC'),
('id', 'DESC'),
]
domain = [
('state', 'in', ['draft', 'wait']),
('shop', '=', SHOP),
['OR',
('party', '=', session['customer']),
('galatea_user', '=', session['user']),
]
]
2015-02-23 18:49:08 +01:00
carts = Cart.search(domain, offset=0, limit=10, order=order)
2014-10-27 15:34:20 +01:00
breadcrumbs = [{
'slug': url_for('.cart', lang=g.language),
'name': _('Cart'),
}, {
'name': _('Pending'),
}]
return render_template('cart-pending.html',
carts=carts,
breadcrumbs=breadcrumbs,
)
@cart.route("/last-products", endpoint="cart-last-products")
@login_required
@tryton.transaction()
def cart_last_products(lang):
'''Last products'''
order = [
('cart_date', 'DESC'),
('id', 'DESC'),
]
domain = [
('state', '=', 'done'),
['OR',
('party', '=', session['customer']),
('galatea_user', '=', session['user']),
]
]
2015-02-23 18:49:08 +01:00
cart_products = Cart.search(domain, offset=0, limit=10, order=order)
last_products = set()
2014-10-27 15:34:20 +01:00
for cproduct in cart_products:
2015-02-23 18:49:08 +01:00
last_products.add(cproduct)
2014-10-27 15:34:20 +01:00
breadcrumbs = [{
'slug': url_for('.cart', lang=g.language),
'name': _('Cart'),
}, {
'name': _('Last Products'),
}]
return render_template('cart-last-products.html',
2015-02-23 18:49:08 +01:00
products=list(last_products),
2014-10-27 15:34:20 +01:00
breadcrumbs=breadcrumbs,
)