[webshop] Place Order - submits Quotation, creates Customer if required, creates and submits Sales Order

This commit is contained in:
Anand Doshi 2013-07-10 20:49:44 +05:30
parent afad0efca3
commit 2ac0a83bd8
19 changed files with 382 additions and 173 deletions

View File

@ -134,7 +134,8 @@
}, },
"profile": { "profile": {
"no_cache": true, "no_cache": true,
"template": "app/website/templates/pages/profile" "template": "app/website/templates/pages/profile",
"args_method": "startup.webutils.get_profile_args"
}, },
"cart": { "cart": {
"no_cache": true, "no_cache": true,

View File

@ -95,6 +95,8 @@ $(document).ready(function() {
$("#user-full-name").text(full_name); $("#user-full-name").text(full_name);
} }
wn.cart.set_cart_count();
$("#user-tools a").tooltip({"placement":"bottom"}); $("#user-tools a").tooltip({"placement":"bottom"});
$("#user-tools-post-login a").tooltip({"placement":"bottom"}); $("#user-tools-post-login a").tooltip({"placement":"bottom"});
}); });
@ -212,8 +214,16 @@ $.extend(wn.cart, {
callback: function(r) { callback: function(r) {
if(opts.callback) if(opts.callback)
opts.callback(r); opts.callback(r);
wn.cart.set_cart_count();
} }
}); });
} }
}, },
set_cart_count: function() {
var cart_count = getCookie("cart_count");
if(cart_count)
$(".cart-count").html("( "+ cart_count +" )")
}
}); });

View File

@ -132,8 +132,15 @@ class DocType(TransactionBase):
self.doc.name, raise_exception=1) self.doc.name, raise_exception=1)
def delete_customer_address(self): def delete_customer_address(self):
for rec in sql("select * from `tabAddress` where customer=%s", (self.doc.name,), as_dict=1): addresses = webnotes.conn.sql("""select name, lead from `tabAddress`
sql("delete from `tabAddress` where name=%s", (rec['name'])) where customer=%s""", (self.doc.name,))
for name, lead in addresses:
if lead:
webnotes.conn.sql("""update `tabAddress` set customer=null, customer_name=null
where name=%s""", name)
else:
webnotes.conn.sql("""delete from `tabAddress` where name=%s""", name)
def delete_customer_contact(self): def delete_customer_contact(self):
for rec in sql("select * from `tabContact` where customer=%s", (self.doc.name,), as_dict=1): for rec in sql("select * from `tabContact` where customer=%s", (self.doc.name,), as_dict=1):

View File

@ -99,6 +99,9 @@ class DocType(SellingController):
@webnotes.whitelist() @webnotes.whitelist()
def make_customer(source_name, target_doclist=None): def make_customer(source_name, target_doclist=None):
_make_customer(source_name, target_doclist)
def _make_customer(source_name, target_doclist=None, ignore_permissions=False):
from webnotes.model.mapper import get_mapped_doclist from webnotes.model.mapper import get_mapped_doclist
def set_missing_values(source, target): def set_missing_values(source, target):
@ -120,7 +123,7 @@ def make_customer(source_name, target_doclist=None):
"contact_no": "phone_1", "contact_no": "phone_1",
"fax": "fax_1" "fax": "fax_1"
} }
}}, target_doclist, set_missing_values) }}, target_doclist, set_missing_values, ignore_permissions=ignore_permissions)
return [d.fields for d in doclist] return [d.fields for d in doclist]

View File

@ -230,8 +230,18 @@ class DocType(SellingController):
@webnotes.whitelist() @webnotes.whitelist()
def make_sales_order(source_name, target_doclist=None): def make_sales_order(source_name, target_doclist=None):
return _make_sales_order(source_name, target_doclist)
def _make_sales_order(source_name, target_doclist=None, ignore_permissions=False):
from webnotes.model.mapper import get_mapped_doclist from webnotes.model.mapper import get_mapped_doclist
customer = _make_customer(source_name, ignore_permissions)
def set_missing_values(source, target):
if customer:
target[0].customer = customer.doc.name
target[0].customer_name = customer.doc.customer_name
doclist = get_mapped_doclist("Quotation", source_name, { doclist = get_mapped_doclist("Quotation", source_name, {
"Quotation": { "Quotation": {
"doctype": "Sales Order", "doctype": "Sales Order",
@ -255,8 +265,34 @@ def make_sales_order(source_name, target_doclist=None):
"Sales Team": { "Sales Team": {
"doctype": "Sales Team", "doctype": "Sales Team",
} }
}, target_doclist) }, target_doclist, set_missing_values, ignore_permissions=ignore_permissions)
# postprocess: fetch shipping address, set missing values # postprocess: fetch shipping address, set missing values
return [d.fields for d in doclist] return [d.fields for d in doclist]
def _make_customer(source_name, ignore_permissions=False):
quotation = webnotes.conn.get_value("Quotation", source_name, ["lead", "order_type"])
if quotation and quotation[0]:
lead_name = quotation[0]
customer_name = webnotes.conn.get_value("Customer", {"lead_name": lead_name})
if not customer_name:
from selling.doctype.lead.lead import _make_customer
customer_doclist = _make_customer(lead_name, ignore_permissions=ignore_permissions)
customer = webnotes.bean(customer_doclist)
customer.ignore_permissions = ignore_permissions
if quotation[1] == "Shopping Cart":
customer.doc.customer_group = webnotes.conn.get_value("Shopping Cart Settings", None,
"default_customer_group")
try:
customer.insert()
return customer
except NameError, e:
if webnotes.defaults.get_global_default('cust_master_name') == "Customer Name":
customer.run_method("autoname")
customer.doc.name += "-" + lead_name
customer.insert()
return customer
else:
raise e

View File

@ -334,6 +334,7 @@ def get_orders():
from `tabSales Order Item` from `tabSales Order Item`
where parent=%s where parent=%s
order by idx""", order.name, as_dict=1) order by idx""", order.name, as_dict=1)
return orders return orders
else: else:
return [] return []

View File

@ -6,7 +6,6 @@ from __future__ import unicode_literals
import webnotes import webnotes
import home import home
def on_login_post_session(login_manager): def on_login_post_session(login_manager):
""" """
called after login called after login
@ -31,6 +30,13 @@ def on_login_post_session(login_manager):
login_manager.user=='Administrator' and '#8CA2B3' or '#1B750D') login_manager.user=='Administrator' and '#8CA2B3' or '#1B750D')
webnotes.conn.commit() webnotes.conn.commit()
if webnotes.cookies.get("full_name"):
from website.helpers.cart import set_cart_count
set_cart_count()
def on_logout(login_manager):
webnotes.add_cookies["cart_count"] = ""
def check_if_expired(): def check_if_expired():
"""check if account is expired. If expired, do not allow login""" """check if account is expired. If expired, do not allow login"""
import conf import conf

View File

@ -62,6 +62,30 @@ def update_template_args(page_name, args):
args.url = quote(str(get_request_site_address(full_address=True)), str("")) args.url = quote(str(get_request_site_address(full_address=True)), str(""))
args.encoded_title = quote(encode(args.title or ""), str("")) args.encoded_title = quote(encode(args.title or ""), str(""))
args.shopping_cart_enabled = cint(webnotes.conn.get_default("shopping_cart_enabled"))
return args return args
@webnotes.whitelist()
def update_profile(fullname, password=None, company_name=None, mobile_no=None, phone=None):
from website.helpers.cart import update_party
update_party(fullname, company_name, mobile_no, phone)
from core.doctype.profile import profile
return profile.update_profile(fullname, password)
def get_profile_args():
from website.helpers.cart import get_lead_or_customer
party = get_lead_or_customer()
if party.doctype == "Lead":
mobile_no = party.mobile_no
phone = party.phone
else:
mobile_no, phone = webnotes.conn.get_value("Contact", {"email_id": webnotes.session.user,
"customer": party.name})
return {
"company_name": party.customer_name if party.doctype == "Customer" else party.company_name,
"mobile_no": mobile_no,
"phone": phone
}

View File

@ -664,11 +664,15 @@ class DocType(StockController):
return result and result[0] or {} return result and result[0] or {}
def get_cust_addr(self): def get_cust_addr(self):
from utilities.transaction_base import get_default_address, get_address_display
res = sql("select customer_name from `tabCustomer` where name = '%s'"%self.doc.customer) res = sql("select customer_name from `tabCustomer` where name = '%s'"%self.doc.customer)
addr = self.get_address_text(customer = self.doc.customer) address_display = None
customer_address = get_default_address("customer", self.doc.customer)
if customer_address:
address_display = get_address_display(customer_address)
ret = { ret = {
'customer_name' : res and res[0][0] or '', 'customer_name' : res and res[0][0] or '',
'customer_address' : addr and addr[0] or ''} 'customer_address' : address_display}
return ret return ret
@ -681,12 +685,17 @@ class DocType(StockController):
return result and result[0] or {} return result and result[0] or {}
def get_supp_addr(self): def get_supp_addr(self):
from utilities.transaction_base import get_default_address, get_address_display
res = sql("""select supplier_name from `tabSupplier` res = sql("""select supplier_name from `tabSupplier`
where name=%s""", self.doc.supplier) where name=%s""", self.doc.supplier)
addr = self.get_address_text(supplier = self.doc.supplier) address_display = None
supplier_address = get_default_address("customer", self.doc.customer)
if supplier_address:
address_display = get_address_display(supplier_address)
ret = { ret = {
'supplier_name' : res and res[0][0] or '', 'supplier_name' : res and res[0][0] or '',
'supplier_address' : addr and addr[0] or ''} 'supplier_address' : address_display }
return ret return ret
def validate_with_material_request(self): def validate_with_material_request(self):

View File

@ -32,6 +32,41 @@ class TransactionBase(StatusUpdater):
return get_default_address_and_contact(party_field, party_name, return get_default_address_and_contact(party_field, party_name,
fetch_shipping_address=True if self.meta.get_field("shipping_address_name") else False) fetch_shipping_address=True if self.meta.get_field("shipping_address_name") else False)
def set_address_fields(self):
party_type, party_name = self.get_party_type_and_name()
if party_type in ("Customer", "Lead"):
if self.doc.customer_address:
self.doc.address_display = get_address_display(self.doc.customer_address)
if self.doc.shipping_address_name:
self.doc.shipping_address = get_address_display(self.doc.shipping_address_name)
elif self.doc.supplier_address:
self.doc.address_display = get_address_display(self.doc.supplier_address)
def set_contact_fields(self):
party_type, party_name = self.get_party_type_and_name()
if party_type == "Lead":
contact_dict = map_lead_contact_details(party_name)
else:
contact_dict = map_party_contact_details(self.doc.contact_person, party_type, party_name)
for fieldname, value in contact_dict.items():
if self.meta.get_field(fieldname):
self.doc.fields[fieldname] = value
def get_party_type_and_name(self):
if not hasattr(self, "_party_type_and_name"):
for party_type in ("Lead", "Customer", "Supplier"):
party_field = party_type.lower()
if self.meta.get_field(party_field) and self.doc.fields.get(party_field):
self._party_type_and_name = (party_type, self.doc.fields.get(party_field))
break
return self._party_type_and_name
def get_customer_defaults(self): def get_customer_defaults(self):
out = self.get_default_address_and_contact("customer") out = self.get_default_address_and_contact("customer")
@ -54,11 +89,6 @@ class TransactionBase(StatusUpdater):
""" """
customer_defaults = self.get_customer_defaults() customer_defaults = self.get_customer_defaults()
# hack! TODO - add shipping_address_field in Delivery Note
if self.doc.doctype == "Delivery Note":
customer_defaults["customer_address"] = customer_defaults["shipping_address_name"]
customer_defaults["address_display"] = customer_defaults["shipping_address"]
customer_defaults["price_list"] = customer_defaults["price_list"] or \ customer_defaults["price_list"] = customer_defaults["price_list"] or \
webnotes.conn.get_value("Customer Group", self.doc.customer_group, "default_price_list") or \ webnotes.conn.get_value("Customer Group", self.doc.customer_group, "default_price_list") or \
self.doc.price_list self.doc.price_list
@ -110,91 +140,35 @@ class TransactionBase(StatusUpdater):
# ----------------------- # -----------------------
def get_customer_address(self, args): def get_customer_address(self, args):
args = load_json(args) args = load_json(args)
address_text, address_name = self.get_address_text(address_name=args['address'])
ret = { ret = {
'customer_address' : address_name, 'customer_address' : args["address"],
'address_display' : address_text, 'address_display' : get_address_display(args["address"]),
} }
ret.update(self.get_contact_text(contact_name=args['contact'])) ret.update(map_party_contact_details(args['contact']))
return ret return ret
# Get Address Text
# -----------------------
def get_address_text(self, customer=None, address_name=None, supplier=None, is_shipping_address=None):
if customer:
cond = customer and 'customer="%s"' % customer or 'name="%s"' % address_name
elif supplier:
cond = supplier and 'supplier="%s"' % supplier or 'name="%s"' % address_name
else:
cond = 'name="%s"' % address_name
if is_shipping_address:
details = webnotes.conn.sql("select name, address_line1, address_line2, city, country, pincode, state, phone, fax from `tabAddress` where %s and docstatus != 2 order by is_shipping_address desc, is_primary_address desc limit 1" % cond, as_dict = 1)
else:
details = webnotes.conn.sql("select name, address_line1, address_line2, city, country, pincode, state, phone, fax from `tabAddress` where %s and docstatus != 2 order by is_primary_address desc limit 1" % cond, as_dict = 1)
address_display = ""
if details:
address_display = get_address_display(details[0])
address_name = details and details[0]['name'] or ''
return address_display, address_name
# Get Contact Text
# -----------------------
def get_contact_text(self, customer=None, contact_name=None, supplier=None):
if customer:
cond = customer and 'customer="%s"' % customer or 'name="%s"' % contact_name
elif supplier:
cond = supplier and 'supplier="%s"' % supplier or 'name="%s"' % contact_name
else:
cond = 'name="%s"' % contact_name
details = webnotes.conn.sql("select name, first_name, last_name, email_id, phone, mobile_no, department, designation from `tabContact` where %s and docstatus != 2 order by is_primary_contact desc limit 1" % cond, as_dict = 1)
extract = lambda x: details and details[0] and details[0].get(x,'') or ''
contact_fields = [('','first_name'),(' ','last_name')]
contact_display = ''.join([a[0]+cstr(extract(a[1])) for a in contact_fields if extract(a[1])])
if contact_display.startswith('\n'): contact_display = contact_display[1:]
return {
"contact_display": contact_display,
"contact_person": details and details[0]["name"] or "",
"contact_email": details and details[0]["email_id"] or "",
"contact_mobile": details and details[0]["mobile_no"] or "",
"contact_designation": details and details[0]["designation"] or "",
"contact_department": details and details[0]["department"] or "",
}
# TODO deprecate this - used only in sales_order.js # TODO deprecate this - used only in sales_order.js
def get_shipping_address(self, name): def get_shipping_address(self, name):
details = webnotes.conn.sql("select name, address_line1, address_line2, city, country, pincode, state, phone from `tabAddress` where customer = '%s' and docstatus != 2 order by is_shipping_address desc, is_primary_address desc limit 1" %(name), as_dict = 1) shipping_address = get_default_address("customer", name, is_shipping_address=True)
return {
address_display = "" 'shipping_address_name' : shipping_address,
if details: 'shipping_address' : get_address_display(shipping_address) if shipping_address else None
address_display = get_address_display(details[0])
ret = {
'shipping_address_name' : details and details[0]['name'] or '',
'shipping_address' : address_display
} }
return ret
# Get Supplier Default Primary Address - first load # Get Supplier Default Primary Address - first load
# ----------------------- # -----------------------
def get_default_supplier_address(self, args): def get_default_supplier_address(self, args):
if isinstance(args, basestring): if isinstance(args, basestring):
args = load_json(args) args = load_json(args)
address_text, address_name = self.get_address_text(supplier=args['supplier'])
address_name = get_default_address("supplier", args["supplier"])
ret = { ret = {
'supplier_address' : address_name, 'supplier_address' : address_name,
'address_display' : address_text, 'address_display' : get_address_display(address_name),
} }
ret.update(self.get_contact_text(supplier=args['supplier'])) ret.update(map_party_contact_details(None, "supplier", args["supplier"]))
ret.update(self.get_supplier_details(args['supplier'])) ret.update(self.get_supplier_details(args['supplier']))
return ret return ret
@ -202,12 +176,11 @@ class TransactionBase(StatusUpdater):
# ----------------------- # -----------------------
def get_supplier_address(self, args): def get_supplier_address(self, args):
args = load_json(args) args = load_json(args)
address_text, address_name = self.get_address_text(address_name=args['address'])
ret = { ret = {
'supplier_address' : address_name, 'supplier_address' : args['address'],
'address_display' : address_text, 'address_display' : get_address_display(args["address"]),
} }
ret.update(self.get_contact_text(contact_name=args['contact'])) ret.update(map_party_contact_details(contact_name=args['contact']))
return ret return ret
# Get Supplier Details # Get Supplier Details
@ -317,23 +290,24 @@ class TransactionBase(StatusUpdater):
[d[0] for d in fields], as_dict=1) [d[0] for d in fields], as_dict=1)
for field, condition in fields: for field, condition in fields:
self.validate_value(field, condition, prevdoc_values[field], doc) if prevdoc_values[field] is not None:
self.validate_value(field, condition, prevdoc_values[field], doc)
def get_default_address_and_contact(party_field, party_name, fetch_shipping_address=False): def get_default_address_and_contact(party_field, party_name, fetch_shipping_address=False):
out = {} out = {}
# get addresses # get addresses
billing_address = get_address_dict(party_field, party_name) billing_address = get_default_address(party_field, party_name)
if billing_address: if billing_address:
out[party_field + "_address"] = billing_address["name"] out[party_field + "_address"] = billing_address
out["address_display"] = get_address_display(billing_address) out["address_display"] = get_address_display(billing_address)
else: else:
out[party_field + "_address"] = out["address_display"] = None out[party_field + "_address"] = out["address_display"] = None
if fetch_shipping_address: if fetch_shipping_address:
shipping_address = get_address_dict(party_field, party_name, is_shipping_address=True) shipping_address = get_default_address(party_field, party_name, is_shipping_address=True)
if shipping_address: if shipping_address:
out["shipping_address_name"] = shipping_address["name"] out["shipping_address_name"] = shipping_address
out["shipping_address"] = get_address_display(shipping_address) out["shipping_address"] = get_address_display(shipping_address)
else: else:
out["shipping_address_name"] = out["shipping_address"] = None out["shipping_address_name"] = out["shipping_address"] = None
@ -341,39 +315,47 @@ def get_default_address_and_contact(party_field, party_name, fetch_shipping_addr
# get contact # get contact
if party_field == "lead": if party_field == "lead":
out["customer_address"] = out.get("lead_address") out["customer_address"] = out.get("lead_address")
out.update(map_lead_fields(party_name)) out.update(map_lead_contact_details(party_name))
else: else:
out.update(map_contact_fields(party_field, party_name)) out.update(map_party_contact_details(None, party_field, party_name))
return out return out
def get_address_dict(party_field, party_name, is_shipping_address=None): def get_default_address(party_field, party_name, is_shipping_address=False):
order_by = "is_shipping_address desc, is_primary_address desc, name asc" if \ if is_shipping_address:
is_shipping_address else "is_primary_address desc, name asc" order_by = "is_shipping_address desc, is_primary_address desc, name asc"
else:
order_by = "is_primary_address desc, name asc"
address = webnotes.conn.sql("""select * from `tabAddress` where `%s`=%s order by %s address = webnotes.conn.sql("""select name from `tabAddress` where `%s`=%s order by %s
limit 1""" % (party_field, "%s", order_by), party_name, as_dict=True, limit 1""" % (party_field, "%s", order_by), party_name)
update={"doctype": "Address"})
return address[0] if address else None return address[0][0] if address else None
def get_default_contact(party_field, party_name):
contact = webnotes.conn.sql("""select name from `tabContact` where `%s`=%s
order by is_primary_contact desc, name asc limit 1""" % (party_field, "%s"),
(party_name,))
return contact[0][0] if contact else None
def get_address_display(address_dict): def get_address_display(address_dict):
def _prepare_for_display(a_dict, sequence): if not isinstance(address_dict, dict):
display = "" address_dict = webnotes.conn.get_value("Address", address_dict, "*", as_dict=True)
for separator, fieldname in sequence:
if a_dict.get(fieldname):
display += separator + a_dict.get(fieldname)
return display.strip()
meta = webnotes.get_doctype("Address") meta = webnotes.get_doctype("Address")
address_sequence = (("", "address_line1"), ("\n", "address_line2"), ("\n", "city"), sequence = (("", "address_line1"), ("\n", "address_line2"), ("\n", "city"),
("\n", "state"), ("\n" + meta.get_label("pincode") + ": ", "pincode"), ("\n", "country"), ("\n", "state"), ("\n" + meta.get_label("pincode") + ": ", "pincode"), ("\n", "country"),
("\n" + meta.get_label("phone") + ": ", "phone"), ("\n" + meta.get_label("fax") + ": ", "fax")) ("\n" + meta.get_label("phone") + ": ", "phone"), ("\n" + meta.get_label("fax") + ": ", "fax"))
return _prepare_for_display(address_dict, address_sequence) display = ""
for separator, fieldname in sequence:
if address_dict.get(fieldname):
display += separator + address_dict.get(fieldname)
def map_lead_fields(party_name): return display.strip()
def map_lead_contact_details(party_name):
out = {} out = {}
for fieldname in ["contact_display", "contact_email", "contact_mobile", "contact_phone"]: for fieldname in ["contact_display", "contact_email", "contact_mobile", "contact_phone"]:
out[fieldname] = None out[fieldname] = None
@ -390,15 +372,19 @@ def map_lead_fields(party_name):
return out return out
def map_contact_fields(party_field, party_name): def map_party_contact_details(contact_name=None, party_field=None, party_name=None):
out = {} out = {}
for fieldname in ["contact_person", "contact_display", "contact_email", for fieldname in ["contact_person", "contact_display", "contact_email",
"contact_mobile", "contact_phone", "contact_designation", "contact_department"]: "contact_mobile", "contact_phone", "contact_designation", "contact_department"]:
out[fieldname] = None out[fieldname] = None
if not contact_name:
contact_name = get_default_contact(party_field, party_name)
contact = webnotes.conn.sql("""select * from `tabContact` where `%s`=%s contact = webnotes.conn.sql("""select * from `tabContact` where `%s`=%s
order by is_primary_contact desc, name asc limit 1""" % (party_field, "%s"), order by is_primary_contact desc, name asc limit 1""" % (party_field, "%s"),
(party_name,), as_dict=True) (party_name,), as_dict=True)
if contact: if contact:
contact = contact[0] contact = contact[0]
out.update({ out.update({

View File

@ -136,6 +136,10 @@ img {
padding-left: 10px; padding-left: 10px;
} }
fieldset {
margin-bottom: 20px;
}
/* buttons */ /* buttons */
.btn-default { .btn-default {
color: #ffffff; color: #ffffff;

View File

@ -2,7 +2,7 @@
{ {
"creation": "2013-06-19 15:57:32", "creation": "2013-06-19 15:57:32",
"docstatus": 0, "docstatus": 0,
"modified": "2013-07-05 14:55:05", "modified": "2013-07-10 18:42:29",
"modified_by": "Administrator", "modified_by": "Administrator",
"owner": "Administrator" "owner": "Administrator"
}, },
@ -44,6 +44,19 @@
"fieldtype": "Check", "fieldtype": "Check",
"label": "Enable Shopping Cart" "label": "Enable Shopping Cart"
}, },
{
"doctype": "DocField",
"fieldname": "section_break_2",
"fieldtype": "Section Break"
},
{
"doctype": "DocField",
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"reqd": 1
},
{ {
"doctype": "DocField", "doctype": "DocField",
"fieldname": "default_territory", "fieldname": "default_territory",
@ -52,6 +65,24 @@
"options": "Territory", "options": "Territory",
"reqd": 1 "reqd": 1
}, },
{
"doctype": "DocField",
"fieldname": "column_break_4",
"fieldtype": "Column Break"
},
{
"doctype": "DocField",
"fieldname": "default_customer_group",
"fieldtype": "Link",
"label": "Default Customer Group",
"options": "Customer Group",
"reqd": 1
},
{
"doctype": "DocField",
"fieldname": "section_break_6",
"fieldtype": "Section Break"
},
{ {
"doctype": "DocField", "doctype": "DocField",
"fieldname": "price_lists", "fieldname": "price_lists",
@ -60,14 +91,6 @@
"options": "Shopping Cart Price List", "options": "Shopping Cart Price List",
"reqd": 0 "reqd": 0
}, },
{
"doctype": "DocField",
"fieldname": "sales_taxes_and_charges_masters",
"fieldtype": "Table",
"label": "Shopping Cart Taxes and Charges Masters",
"options": "Shopping Cart Taxes and Charges Master",
"reqd": 0
},
{ {
"doctype": "DocField", "doctype": "DocField",
"fieldname": "shipping_rules", "fieldname": "shipping_rules",
@ -78,11 +101,16 @@
}, },
{ {
"doctype": "DocField", "doctype": "DocField",
"fieldname": "company", "fieldname": "column_break_10",
"fieldtype": "Link", "fieldtype": "Column Break"
"label": "Company", },
"options": "Company", {
"reqd": 1 "doctype": "DocField",
"fieldname": "sales_taxes_and_charges_masters",
"fieldtype": "Table",
"label": "Shopping Cart Taxes and Charges Masters",
"options": "Shopping Cart Taxes and Charges Master",
"reqd": 0
}, },
{ {
"doctype": "DocPerm" "doctype": "DocPerm"

View File

@ -3,17 +3,26 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import webnotes import webnotes
from webnotes import msgprint, _
import webnotes.defaults import webnotes.defaults
from webnotes.utils import flt, get_fullname, fmt_money from webnotes.utils import flt, get_fullname, fmt_money, cstr
class WebsitePriceListMissingError(webnotes.ValidationError): pass class WebsitePriceListMissingError(webnotes.ValidationError): pass
def set_cart_count(quotation=None):
if not quotation:
quotation = _get_cart_quotation()
webnotes.add_cookies["cart_count"] = cstr(len(quotation.doclist.get(
{"parentfield": "quotation_details"})) or "")
@webnotes.whitelist() @webnotes.whitelist()
def get_cart_quotation(doclist=None): def get_cart_quotation(doclist=None):
party = get_lead_or_customer() party = get_lead_or_customer()
if not doclist: if not doclist:
doclist = _get_cart_quotation(party).doclist quotation = _get_cart_quotation(party)
doclist = quotation.doclist
set_cart_count(quotation)
return { return {
"doclist": decorate_quotation_doclist(doclist), "doclist": decorate_quotation_doclist(doclist),
@ -22,6 +31,26 @@ def get_cart_quotation(doclist=None):
"shipping_rules": get_applicable_shipping_rules(party) "shipping_rules": get_applicable_shipping_rules(party)
} }
@webnotes.whitelist()
def place_order():
quotation = _get_cart_quotation()
controller = quotation.make_controller()
for fieldname in ["customer_address", "shipping_address_name"]:
if not quotation.doc.fields.get(fieldname):
msgprint(_("Please select a") + " " + _(controller.meta.get_label(fieldname)), raise_exception=True)
quotation.ignore_permissions = True
quotation.submit()
from selling.doctype.quotation.quotation import _make_sales_order
sales_order = webnotes.bean(_make_sales_order(quotation.doc.name, ignore_permissions=True))
sales_order.ignore_permissions = True
sales_order.insert()
sales_order.submit()
webnotes.add_cookies["cart_count"] = ""
return sales_order.doc.name
@webnotes.whitelist() @webnotes.whitelist()
def update_cart(item_code, qty, with_doclist=0): def update_cart(item_code, qty, with_doclist=0):
quotation = _get_cart_quotation() quotation = _get_cart_quotation()
@ -46,6 +75,8 @@ def update_cart(item_code, qty, with_doclist=0):
quotation.ignore_permissions = True quotation.ignore_permissions = True
quotation.save() quotation.save()
set_cart_count(quotation)
if with_doclist: if with_doclist:
return get_cart_quotation(quotation.doclist) return get_cart_quotation(quotation.doclist)
else: else:
@ -192,11 +223,47 @@ def _get_cart_quotation(party=None):
"__islocal": 1, "__islocal": 1,
(party.doctype.lower()): party.name (party.doctype.lower()): party.name
}) })
# map_contact_fields(qbean, party)
qbean.run_method("onload_post_render") qbean.run_method("onload_post_render")
apply_cart_settings(party, qbean) apply_cart_settings(party, qbean)
return qbean return qbean
def update_party(fullname, company_name=None, mobile_no=None, phone=None):
party = get_lead_or_customer()
if party.doctype == "Lead":
party.company_name = company_name
party.lead_name = fullname
party.mobile_no = mobile_no
party.phone = phone
else:
party.customer_name = company_name or fullname
party.customer_type == "Company" if company_name else "Individual"
contact_name = webnotes.conn.get_value("Contact", {"email_id": webnotes.session.user,
"customer": party.name})
contact = webnotes.bean("Contact", contact_name)
contact.doc.first_name = fullname
contact.doc.last_name = None
contact.doc.customer_name = party.customer_name
contact.doc.mobile_no = mobile_no
contact.doc.phone = phone
contact.ignore_permissions = True
contact.save()
party_bean = webnotes.bean(party.fields)
party_bean.ignore_permissions = True
party_bean.save()
qbean = _get_cart_quotation(party)
qbean.doc.customer_name = company_name or fullname
qbean.run_method("set_contact_fields")
qbean.ignore_permissions = True
qbean.save()
def apply_cart_settings(party=None, quotation=None): def apply_cart_settings(party=None, quotation=None):
if not party: if not party:
party = get_lead_or_customer() party = get_lead_or_customer()
@ -237,7 +304,7 @@ def set_taxes(quotation, cart_settings, billing_territory):
quotation.doc.charge = cart_settings.get_tax_master(billing_territory) quotation.doc.charge = cart_settings.get_tax_master(billing_territory)
# clear table # clear table
quotation.doclist = quotation.doc.clear_table(quotation.doclist, "other_charges") quotation.set_doclist(quotation.doclist.get({"parentfield": ["!=", "other_charges"]}))
# append taxes # append taxes
controller = quotation.make_controller() controller = quotation.make_controller()

View File

@ -10,8 +10,10 @@
<div class="pull-right hide" style="margin:4px;" id="user-tools-post-login"> <div class="pull-right hide" style="margin:4px;" id="user-tools-post-login">
<a href="profile" title="My Profile" id="user-full-name"></a> | <a href="profile" title="My Profile" id="user-full-name"></a> |
<a href="account" title="My Account">My Account</a> | <a href="account" title="My Account">My Account</a> |
{% if shopping_cart_enabled -%}
<a href="cart" title="Shopping Cart"><i class="icon-shopping-cart"></i> <a href="cart" title="Shopping Cart"><i class="icon-shopping-cart"></i>
<span class="cart-count"></span></a> | <span class="cart-count"></span></a> |
{%- endif %}
<a href="server.py?cmd=web_logout" title="Sign Out"><i class="icon-signout"></i></a> <a href="server.py?cmd=web_logout" title="Sign Out"><i class="icon-signout"></i></a>
</div> </div>
<div class="clearfix"></div> <div class="clearfix"></div>

View File

@ -32,7 +32,7 @@
<p class="help">Item Code: <span itemprop="productID">{{ name }}</span></p> <p class="help">Item Code: <span itemprop="productID">{{ name }}</span></p>
<h4>Product Description</h4> <h4>Product Description</h4>
<div itemprop="description"> <div itemprop="description">
{{ web_long_description or web_short_description or {{ web_long_description or web_short_description or description or
"[No description given]" }} "[No description given]" }}
</div> </div>
<div style="min-height: 100px; margin: 10px 0;"> <div style="min-height: 100px; margin: 10px 0;">

View File

@ -17,8 +17,6 @@
// js inside blog page // js inside blog page
$(document).ready(function() { $(document).ready(function() {
// make list of items in the cart
// wn.cart.render();
wn.cart.bind_events(); wn.cart.bind_events();
wn.call({ wn.call({
type: "POST", type: "POST",
@ -36,6 +34,7 @@ $(document).ready(function() {
wn.cart.show_error("Oops!", "Something went wrong."); wn.cart.show_error("Oops!", "Something went wrong.");
} }
} else { } else {
wn.cart.set_cart_count();
wn.cart.render(r.message); wn.cart.render(r.message);
} }
} }
@ -75,6 +74,10 @@ $.extend(wn.cart, {
$("#cart-add-billing-address").on("click", function() { $("#cart-add-billing-address").on("click", function() {
window.location.href = "address?address_fieldname=customer_address"; window.location.href = "address?address_fieldname=customer_address";
}); });
$(".btn-place-order").on("click", function() {
wn.cart.place_order();
});
}, },
render: function(out) { render: function(out) {
@ -282,5 +285,27 @@ $.extend(wn.cart, {
$address_wrapper.find('.accordion-body[data-address-name="'+ address_name +'"]') $address_wrapper.find('.accordion-body[data-address-name="'+ address_name +'"]')
.collapse("show"); .collapse("show");
},
place_order: function() {
wn.call({
type: "POST",
method: "website.helpers.cart.place_order",
callback: function(r) {
if(r.exc) {
var msg = "";
if(r._server_messages) {
msg = JSON.parse(r._server_messages || []).join("<br>");
}
$("#cart-error")
.empty()
.html(msg || "Something went wrong!")
.toggle(true);
} else {
window.location.href = "order?name=" + encodeURIComponent(r.message);
}
}
});
} }
}); });

View File

@ -113,11 +113,3 @@
})(); })();
</script> </script>
{% endblock %} {% endblock %}
{% block css %}
<style>
fieldset {
margin-bottom: 20px;
}
</style>
{% endblock %}

View File

@ -13,8 +13,9 @@
<div class="progress-bar progress-bar-info" style="width: 100%;"></div> <div class="progress-bar progress-bar-info" style="width: 100%;"></div>
</div> </div>
<div id="cart-container" class="hide"> <div id="cart-container" class="hide">
<button class="btn btn-success pull-right" type="button">Place Order</button> <button class="btn btn-success pull-right btn-place-order" type="button">Place Order</button>
<div class="clearfix"></div> <div class="clearfix"></div>
<div id="cart-error" class="alert alert-danger" style="display: none;"></div>
<hr> <hr>
<div class="row"> <div class="row">
<div class="col col-lg-9 col-sm-9"> <div class="col col-lg-9 col-sm-9">
@ -50,7 +51,7 @@
</div> </div>
<hr> <hr>
</div> </div>
<button class="btn btn-success pull-right" type="button">Place Order</button> <button class="btn btn-success pull-right btn-place-order" type="button">Place Order</button>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -12,24 +12,28 @@
<h2><i class="icon-user"></i> My Profile</h2> <h2><i class="icon-user"></i> My Profile</h2>
<hr> <hr>
<div class="alert" id="message" style="display: none;"></div> <div class="alert" id="message" style="display: none;"></div>
<form class="form-horizontal"> <form>
<div class="control-group"> <fieldset>
<label class="control-label" for="fullname">Full Name</label> <label>Full Name</label>
<div class="controls"> <input type="text" id="fullname" placeholder="Your Name">
<input type="text" id="fullname" placeholder="Your Name"> </fieldset>
</div> <fieldset>
</div> <label>Password</label>
<div class="control-group"> <input type="password" id="password" placeholder="Password">
<label class="control-label" for="password">Password</label> </fieldset>
<div class="controls"> <fieldset>
<input type="password" id="password" placeholder="Password"> <label>Company Name</label>
</div> <input type="text" id="company_name" placeholder="Company Name" value="{{ company_name }}">
</div> </fieldset>
<div class="control-group"> <fieldset>
<div class="controls"> <label>Mobile No</label>
<button id="update_profile" type="submit" class="btn btn-default">Update</button> <input type="text" id="mobile_no" placeholder="Mobile No" value="{{ mobile_no }}">
</div> </fieldset>
</div> <fieldset>
<label>Phone</label>
<input type="text" id="phone" placeholder="Phone" value="{{ phone }}">
</fieldset>
<button id="update_profile" type="submit" class="btn btn-default">Update</button>
</form> </form>
</div> </div>
<script> <script>
@ -37,11 +41,14 @@ $(document).ready(function() {
$("#fullname").val(getCookie("full_name") || ""); $("#fullname").val(getCookie("full_name") || "");
$("#update_profile").click(function() { $("#update_profile").click(function() {
wn.call({ wn.call({
method: "core.doctype.profile.profile.update_profile", method: "startup.webutils.update_profile",
type: "POST", type: "POST",
args: { args: {
fullname: $("#fullname").val(), fullname: $("#fullname").val(),
password: $("#password").val() password: $("#password").val(),
company_name: $("#company_name").val(),
mobile_no: $("#mobile_no").val(),
phone: $("#phone").val()
}, },
btn: this, btn: this,
msg: $("#message"), msg: $("#message"),