[webshop] Place Order - submits Quotation, creates Customer if required, creates and submits Sales Order
diff --git a/website/css/website.css b/website/css/website.css
index 816b3ef..64cff7f 100644
--- a/website/css/website.css
+++ b/website/css/website.css
@@ -136,6 +136,10 @@
 	padding-left: 10px;
 }
 
+fieldset {
+	margin-bottom: 20px;
+}
+
 /* buttons */
 .btn-default {
   color: #ffffff;
diff --git a/website/doctype/shopping_cart_settings/shopping_cart_settings.txt b/website/doctype/shopping_cart_settings/shopping_cart_settings.txt
index 8cb1480..7455864 100644
--- a/website/doctype/shopping_cart_settings/shopping_cart_settings.txt
+++ b/website/doctype/shopping_cart_settings/shopping_cart_settings.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-06-19 15:57:32", 
   "docstatus": 0, 
-  "modified": "2013-07-05 14:55:05", 
+  "modified": "2013-07-10 18:42:29", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -46,6 +46,19 @@
  }, 
  {
   "doctype": "DocField", 
+  "fieldname": "section_break_2", 
+  "fieldtype": "Section Break"
+ }, 
+ {
+  "doctype": "DocField", 
+  "fieldname": "company", 
+  "fieldtype": "Link", 
+  "label": "Company", 
+  "options": "Company", 
+  "reqd": 1
+ }, 
+ {
+  "doctype": "DocField", 
   "fieldname": "default_territory", 
   "fieldtype": "Link", 
   "label": "Default Territory", 
@@ -54,6 +67,24 @@
  }, 
  {
   "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", 
   "fieldname": "price_lists", 
   "fieldtype": "Table", 
   "label": "Shopping Cart Price Lists", 
@@ -62,14 +93,6 @@
  }, 
  {
   "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", 
   "fieldname": "shipping_rules", 
   "fieldtype": "Table", 
   "label": "Shopping Cart Shipping Rules", 
@@ -78,11 +101,16 @@
  }, 
  {
   "doctype": "DocField", 
-  "fieldname": "company", 
-  "fieldtype": "Link", 
-  "label": "Company", 
-  "options": "Company", 
-  "reqd": 1
+  "fieldname": "column_break_10", 
+  "fieldtype": "Column Break"
+ }, 
+ {
+  "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"
diff --git a/website/helpers/cart.py b/website/helpers/cart.py
index d4ab64d..ea72e40 100644
--- a/website/helpers/cart.py
+++ b/website/helpers/cart.py
@@ -3,17 +3,26 @@
 
 from __future__ import unicode_literals
 import webnotes
+from webnotes import msgprint, _
 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
 
+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()
 def get_cart_quotation(doclist=None):
 	party = get_lead_or_customer()
 	
 	if not doclist:
-		doclist = _get_cart_quotation(party).doclist
+		quotation = _get_cart_quotation(party)
+		doclist = quotation.doclist
+		set_cart_count(quotation)
 	
 	return {
 		"doclist": decorate_quotation_doclist(doclist),
@@ -21,6 +30,26 @@
 			for address in get_address_docs(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()
 def update_cart(item_code, qty, with_doclist=0):
@@ -46,6 +75,8 @@
 	quotation.ignore_permissions = True
 	quotation.save()
 	
+	set_cart_count(quotation)
+	
 	if with_doclist:
 		return get_cart_quotation(quotation.doclist)
 	else:
@@ -192,11 +223,47 @@
 			"__islocal": 1,
 			(party.doctype.lower()): party.name
 		})
+		
+		# map_contact_fields(qbean, party)
+		
 		qbean.run_method("onload_post_render")
 		apply_cart_settings(party, 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):
 	if not party:
 		party = get_lead_or_customer()
@@ -237,8 +304,8 @@
 	quotation.doc.charge = cart_settings.get_tax_master(billing_territory)
 
 	# clear table
-	quotation.doclist = quotation.doc.clear_table(quotation.doclist, "other_charges")
-
+	quotation.set_doclist(quotation.doclist.get({"parentfield": ["!=", "other_charges"]}))
+	
 	# append taxes
 	controller = quotation.make_controller()
 	controller.append_taxes_from_master("other_charges", "charge")
diff --git a/website/templates/html/outer.html b/website/templates/html/outer.html
index cc1181c..0102acd 100644
--- a/website/templates/html/outer.html
+++ b/website/templates/html/outer.html
@@ -10,8 +10,10 @@
 		<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="account" title="My Account">My Account</a> |
+			{% if shopping_cart_enabled -%}
 			<a href="cart" title="Shopping Cart"><i class="icon-shopping-cart"></i> 
 				<span class="cart-count"></span></a> |
+			{%- endif %}
 			<a href="server.py?cmd=web_logout" title="Sign Out"><i class="icon-signout"></i></a>
 		</div>
 		<div class="clearfix"></div>
diff --git a/website/templates/html/product_page.html b/website/templates/html/product_page.html
index b3e8be2..73520ef 100644
--- a/website/templates/html/product_page.html
+++ b/website/templates/html/product_page.html
@@ -32,7 +32,7 @@
 				<p class="help">Item Code: <span itemprop="productID">{{ name }}</span></p>
 				<h4>Product Description</h4>
 				<div itemprop="description">
-				{{ web_long_description or web_short_description or 
+				{{ web_long_description or web_short_description or description or 
 					"[No description given]" }}
 				</div>
 				<div style="min-height: 100px; margin: 10px 0;">
diff --git a/website/templates/js/cart.js b/website/templates/js/cart.js
index 27f604f..bb3fcb9 100644
--- a/website/templates/js/cart.js
+++ b/website/templates/js/cart.js
@@ -17,8 +17,6 @@
 // js inside blog page
 
 $(document).ready(function() {
-	// make list of items in the cart
-	// wn.cart.render();
 	wn.cart.bind_events();
 	wn.call({
 		type: "POST",
@@ -36,6 +34,7 @@
 					wn.cart.show_error("Oops!", "Something went wrong.");
 				}
 			} else {
+				wn.cart.set_cart_count();
 				wn.cart.render(r.message);
 			}
 		}
@@ -75,6 +74,10 @@
 		$("#cart-add-billing-address").on("click", function() {
 			window.location.href = "address?address_fieldname=customer_address";
 		});
+		
+		$(".btn-place-order").on("click", function() {
+			wn.cart.place_order();
+		});
 	},
 	
 	render: function(out) {
@@ -282,5 +285,27 @@
 		
 		$address_wrapper.find('.accordion-body[data-address-name="'+ address_name +'"]')
 			.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);
+				}
+			}
+		});
 	}
 });
\ No newline at end of file
diff --git a/website/templates/pages/address.html b/website/templates/pages/address.html
index 5b90928..cf1fc4b 100644
--- a/website/templates/pages/address.html
+++ b/website/templates/pages/address.html
@@ -112,12 +112,4 @@
 	};
 })();
 </script>
-{% endblock %}
-
-{% block css %}
-<style>
-fieldset {
-	margin-bottom: 20px;
-}
-</style>
 {% endblock %}
\ No newline at end of file
diff --git a/website/templates/pages/cart.html b/website/templates/pages/cart.html
index cefcb5a..5bfca33 100644
--- a/website/templates/pages/cart.html
+++ b/website/templates/pages/cart.html
@@ -13,8 +13,9 @@
 		<div class="progress-bar progress-bar-info" style="width: 100%;"></div>
 	</div>
 	<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 id="cart-error" class="alert alert-danger" style="display: none;"></div>
 		<hr>
 		<div class="row">
 			<div class="col col-lg-9 col-sm-9">
@@ -50,7 +51,7 @@
 			</div>
 			<hr>
 		</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>
 {% endblock %}
\ No newline at end of file
diff --git a/website/templates/pages/profile.html b/website/templates/pages/profile.html
index 993839e..61ae1b0 100644
--- a/website/templates/pages/profile.html
+++ b/website/templates/pages/profile.html
@@ -12,24 +12,28 @@
 	<h2><i class="icon-user"></i> My Profile</h2>
 	<hr>
 	<div class="alert" id="message" style="display: none;"></div>
-	<form class="form-horizontal">
-		<div class="control-group">
-			<label class="control-label" for="fullname">Full Name</label>
-			<div class="controls">
-				<input type="text" id="fullname" placeholder="Your Name">
-			</div>
-		</div>
-		<div class="control-group">
-			<label class="control-label" for="password">Password</label>
-			<div class="controls">
-				<input type="password" id="password" placeholder="Password">
-			</div>
-		</div>
-		<div class="control-group">
-			<div class="controls">
-				<button id="update_profile" type="submit" class="btn btn-default">Update</button>
-			</div>
-		</div>
+	<form>
+		<fieldset>
+			<label>Full Name</label>
+			<input type="text" id="fullname" placeholder="Your Name">
+		</fieldset>
+		<fieldset>
+			<label>Password</label>
+			<input type="password" id="password" placeholder="Password">
+		</fieldset>
+		<fieldset>
+			<label>Company Name</label>
+			<input type="text" id="company_name" placeholder="Company Name" value="{{ company_name }}">
+		</fieldset>
+		<fieldset>
+			<label>Mobile No</label>
+			<input type="text" id="mobile_no" placeholder="Mobile No" value="{{ mobile_no }}">
+		</fieldset>
+		<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>
 </div>
 <script>
@@ -37,11 +41,14 @@
 	$("#fullname").val(getCookie("full_name") || "");
 	$("#update_profile").click(function() {
 		wn.call({
-			method: "core.doctype.profile.profile.update_profile",
+			method: "startup.webutils.update_profile",
 			type: "POST",
 			args: {
 				fullname: $("#fullname").val(),
-				password: $("#password").val()
+				password: $("#password").val(),
+				company_name: $("#company_name").val(),
+				mobile_no: $("#mobile_no").val(),
+				phone: $("#phone").val()
 			},
 			btn: this,
 			msg: $("#message"),
@@ -53,4 +60,4 @@
 	})
 })
 </script>
-{% endblock %}
+{% endblock %}
\ No newline at end of file