Merge branch 'responsive' of github.com:webnotes/erpnext into responsive

This commit is contained in:
Nabin Hait 2013-07-11 11:58:43 +05:30
commit c0816d7efe
31 changed files with 474 additions and 198 deletions

View File

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

View File

@ -21,7 +21,7 @@ wn.pages['latest-updates'].onload = function(wrapper) {
var $tbody = $('<table class="table table-bordered"><tbody></tbody></table>')
.appendTo(parent).find("tbody");
$.each(r.message, function(i, log) {
if(log.message.indexOf("minor")!==-1 && log.message.indexOf("[")!==-1) {
if(log.message.indexOf("minor")===1 && log.message.indexOf("[")!==-1) {
log.message = log.message.replace(/(\[[^\]]*\])/g,
function(match, p1, offset, string) {
match = match.toLowerCase();

View File

@ -21,7 +21,6 @@ patch_list = [
"execute:webnotes.reload_doc('core', 'doctype', 'report')",
"execute:webnotes.reload_doc('core', 'doctype', 'doctype') # 2013-07-08",
"execute:webnotes.reload_doc('core', 'doctype', 'page') # 2013-06-24",
"patches.mar_2012.so_rv_mapper_fix",
"patches.mar_2012.clean_property_setter",
"patches.april_2012.naming_series_patch",
"patches.mar_2012.cleanup_control_panel",

View File

@ -75,6 +75,7 @@ $.extend(erpnext.complete_setup, {
if(!data) return;
$(this).set_working();
$c_obj('Setup Control','setup_account',data,function(r, rt){
$(this).done_working();
if(!r.exc) {
sys_defaults = r.message;
user_fullname = r.message.user_fullname;
@ -84,12 +85,16 @@ $.extend(erpnext.complete_setup, {
wn.container.wntoolbar.set_user_name();
setTimeout(function() { window.location.reload(); }, 3000);
} else {
$(this).done_working();
}
});
};
d.fields_dict.company_name.input.onchange = function() {
var parts = d.get_input("company_name").val().split(" ");
var abbr = $.map(parts, function(p) { return p ? p.substr(0,1) : null }).join("");
d.get_input("company_abbr").val(abbr.toUpperCase());
}
d.fields_dict.country.input.onchange = function() {
var country = d.fields_dict.country.input.value;
var $timezone = $(d.fields_dict.timezone.input);

View File

@ -95,6 +95,8 @@ $(document).ready(function() {
$("#user-full-name").text(full_name);
}
wn.cart.set_cart_count();
$("#user-tools a").tooltip({"placement":"bottom"});
$("#user-tools-post-login a").tooltip({"placement":"bottom"});
});
@ -212,8 +214,16 @@ $.extend(wn.cart, {
callback: function(r) {
if(opts.callback)
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)
def delete_customer_address(self):
for rec in sql("select * from `tabAddress` where customer=%s", (self.doc.name,), as_dict=1):
sql("delete from `tabAddress` where name=%s", (rec['name']))
addresses = webnotes.conn.sql("""select name, lead from `tabAddress`
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):
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()
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
def set_missing_values(source, target):
@ -120,7 +123,7 @@ def make_customer(source_name, target_doclist=None):
"contact_no": "phone_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]

View File

@ -230,8 +230,18 @@ class DocType(SellingController):
@webnotes.whitelist()
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
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, {
"Quotation": {
"doctype": "Sales Order",
@ -255,12 +265,38 @@ def make_sales_order(source_name, target_doclist=None):
"Sales Team": {
"doctype": "Sales Team",
}
}, target_doclist)
}, target_doclist, set_missing_values, ignore_permissions=ignore_permissions)
# postprocess: fetch shipping address, set missing values
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
def quotation_details(doctype, txt, searchfield, start, page_len, filters):
from controllers.queries import get_match_cond
@ -297,4 +333,4 @@ def quotation_details(doctype, txt, searchfield, start, page_len, filters):
return webnotes.conn.sql(""" select name, item_name, description from `tabItem` item
where %s %s and %s like %s order by name desc limit %s, %s""" %
("%s", get_match_cond(doctype, searchfield), searchfield, "%s", "%s", "%s"),
(filters["cond"], "%%%s%%" % txt, start, page_len))
(filters["cond"], "%%%s%%" % txt, start, page_len))

View File

@ -319,7 +319,7 @@ def get_orders():
# find customer id
customer = webnotes.conn.get_value("Contact", {"email_id": webnotes.session.user},
"customer")
if customer:
orders = webnotes.conn.sql("""select
name, creation, currency from `tabSales Order`
@ -334,6 +334,7 @@ def get_orders():
from `tabSales Order Item`
where parent=%s
order by idx""", order.name, as_dict=1)
return orders
else:
return []

View File

@ -39,6 +39,7 @@ class DocType:
where company=%s and docstatus<2 limit 1""", self.doc.name):
self.create_default_accounts()
self.create_default_warehouses()
self.create_default_web_page()
if not self.doc.cost_center:
self.create_default_cost_center()
@ -52,8 +53,46 @@ class DocType:
for whname in ("Stores", "Work In Progress", "Finished Goods"):
webnotes.bean({
"doctype":"Warehouse",
"warehouse_name": whname,
"company": self.doc.name
}).insert()
def create_default_web_page(self):
if not webnotes.conn.get_value("Website Settings", None, "home_page"):
import os
with open(os.path.join(os.path.dirname(__file__), "sample_home_page.html"), "r") as webfile:
webpage = webnotes.bean({
"doctype": "Web Page",
"title": self.doc.name + " Home",
"published": 1,
"description": "Standard Home Page for " + self.doc.company,
"main_section": webfile.read() % self.doc.fields
}).insert()
# update in home page in settings
website_settings = webnotes.bean("Website Settings", "Website Settings")
website_settings.doc.home_page = webpage.doc.name
website_settings.doc.banner_html = """<h3 style='margin-bottom: 20px;'>""" + self.doc.name + "</h3>"
website_settings.doc.copyright = self.doc.name
website_settings.doclist.append({
"doctype": "Top Bar Item",
"parentfield": "top_bar_items",
"label":"Home",
"url": webpage.doc.name
})
website_settings.doclist.append({
"doctype": "Top Bar Item",
"parentfield": "top_bar_items",
"label":"Contact",
"url": "contact"
})
website_settings.doclist.append({
"doctype": "Top Bar Item",
"parentfield": "top_bar_items",
"label":"Blog",
"url": "blog"
})
website_settings.save()
def create_default_accounts(self):
self.fld_dict = {'account_name':0,'parent_account':1,'group_or_ledger':2,'is_pl_account':3,'account_type':4,'debit_or_credit':5,'company':6,'tax_rate':7}

View File

@ -0,0 +1,22 @@
<h2 style="text-align: center;"><i class="icon-home"></i> Sample Home Page</h2>
<br>
<p>This is a sample home page for your company <b>%(name)s's</b> website. This was
created from the Website Module inside ERPNext. ERPNext provides you with simple
tools to build and update your website. You can add sections like your Product Catalog,
Blog, Contact Us, About Us and so on. Messages entered in the "Contact" page are
automatically added as Leads in the system.
<h5>What you can do with your website:</h5>
<ul>
<li>Automatically generate products / services catalog from your Items.
<li>Capture Leads from your website.
<li>Communicate with your customers by sharing your thoughts in your Blog.
<li>Introduce your company and team in the About Us page.
</ul>
<p>Infact,
<a href="https://erpnext.com" target="_blank">erpnext.com</a>
website is built on ERPNext itself.</p>
<p class="text-muted">For more help, click here</p>

View File

@ -2,7 +2,7 @@
{
"creation": "2012-07-12 23:29:45",
"docstatus": 0,
"modified": "2013-07-10 14:54:11",
"modified": "2013-07-10 19:24:07",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -12,6 +12,7 @@
"allow_print": 1,
"description": "Send automatic emails to Contacts on Submitting transactions.",
"doctype": "DocType",
"icon": "icon-envelope",
"issingle": 1,
"module": "Setup",
"name": "__common__"

View File

@ -65,7 +65,7 @@ class DocType:
webnotes.bean([{
"doctype":"Fiscal Year",
'year': curr_fiscal_year,
'year_start_date': fy_start_date,
'year_start_date': fy_start_date
}]).insert()
curr_fiscal_year, fy_start_date, fy_abbr = self.get_fy_details(args.get('fy_start'))
@ -79,9 +79,10 @@ class DocType:
# Company
webnotes.bean([{
"doctype":"Company",
'domain': args.get("industry"),
'company_name':args.get('company_name'),
'abbr':args.get('company_abbr'),
'default_currency':args.get('currency')
'default_currency':args.get('currency'),
}]).insert()
self.curr_fiscal_year = curr_fiscal_year
@ -148,7 +149,7 @@ class DocType:
# control panel
cp = webnotes.doc("Control Panel", "Control Panel")
for k in ['industry', 'country', 'timezone', 'company_name']:
for k in ['country', 'timezone', 'company_name']:
cp.fields[k] = args[k]
cp.save()

View File

@ -6,7 +6,6 @@ from __future__ import unicode_literals
import webnotes
import home
def on_login_post_session(login_manager):
"""
called after login
@ -30,7 +29,14 @@ def on_login_post_session(login_manager):
'%s logged in at %s' % (get_user_fullname(login_manager.user), nowtime()),
login_manager.user=='Administrator' and '#8CA2B3' or '#1B750D')
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():
"""check if account is expired. If expired, do not allow login"""
import conf

View File

@ -146,9 +146,6 @@ def import_defaults():
{'doctype': 'Supplier Type', 'supplier_type': 'Hardware'},
{'doctype': 'Supplier Type', 'supplier_type': 'Pharmaceutical'},
{'doctype': 'Supplier Type', 'supplier_type': 'Distributor'},
# Workstation
{'doctype': 'Workstation', 'name': 'Default Workstation', 'workstation_name': 'Default Workstation', 'warehouse': 'Default Warehouse'},
# Sales Person
{'doctype': 'Sales Person', 'sales_person_name': 'Sales Team', 'is_group': "Yes", "parent_sales_person": ""},
@ -166,12 +163,11 @@ def import_defaults():
from webnotes.modules import scrub
for r in records:
if not webnotes.conn.exists(r['doctype'], r['name']):
bean = webnotes.bean(r)
# ignore mandatory for root
parent_link_field = ("parent_" + scrub(bean.doc.doctype))
if parent_link_field in bean.doc.fields and not bean.doc.fields.get(parent_link_field):
bean.ignore_mandatory = True
bean.insert()
bean = webnotes.bean(r)
# ignore mandatory for root
parent_link_field = ("parent_" + scrub(bean.doc.doctype))
if parent_link_field in bean.doc.fields and not bean.doc.fields.get(parent_link_field):
bean.ignore_mandatory = True
bean.insert()

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.encoded_title = quote(encode(args.title or ""), str(""))
args.shopping_cart_enabled = cint(webnotes.conn.get_default("shopping_cart_enabled"))
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

@ -665,11 +665,15 @@ class DocType(StockController):
return result and result[0] or {}
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)
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 = {
'customer_name' : res and res[0][0] or '',
'customer_address' : addr and addr[0] or ''}
'customer_address' : address_display}
return ret
@ -682,12 +686,17 @@ class DocType(StockController):
return result and result[0] or {}
def get_supp_addr(self):
from utilities.transaction_base import get_default_address, get_address_display
res = sql("""select supplier_name from `tabSupplier`
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 = {
'supplier_name' : res and res[0][0] or '',
'supplier_address' : addr and addr[0] or ''}
'supplier_address' : address_display }
return ret
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,
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):
out = self.get_default_address_and_contact("customer")
@ -53,12 +88,7 @@ class TransactionBase(StatusUpdater):
3. Clears existing Sales Team and fetches the one mentioned in Customer
"""
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 \
webnotes.conn.get_value("Customer Group", self.doc.customer_group, "default_price_list") or \
self.doc.price_list
@ -110,91 +140,35 @@ class TransactionBase(StatusUpdater):
# -----------------------
def get_customer_address(self, args):
args = load_json(args)
address_text, address_name = self.get_address_text(address_name=args['address'])
ret = {
'customer_address' : address_name,
'address_display' : address_text,
'customer_address' : args["address"],
'address_display' : get_address_display(args["address"]),
}
ret.update(self.get_contact_text(contact_name=args['contact']))
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
ret.update(map_party_contact_details(args['contact']))
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])
return ret
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
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)
address_display = ""
if details:
address_display = get_address_display(details[0])
ret = {
'shipping_address_name' : details and details[0]['name'] or '',
'shipping_address' : address_display
shipping_address = get_default_address("customer", name, is_shipping_address=True)
return {
'shipping_address_name' : shipping_address,
'shipping_address' : get_address_display(shipping_address) if shipping_address else None
}
return ret
# Get Supplier Default Primary Address - first load
# -----------------------
def get_default_supplier_address(self, args):
if isinstance(args, basestring):
args = load_json(args)
address_text, address_name = self.get_address_text(supplier=args['supplier'])
address_name = get_default_address("supplier", args["supplier"])
ret = {
'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']))
return ret
@ -202,12 +176,11 @@ class TransactionBase(StatusUpdater):
# -----------------------
def get_supplier_address(self, args):
args = load_json(args)
address_text, address_name = self.get_address_text(address_name=args['address'])
ret = {
'supplier_address' : address_name,
'address_display' : address_text,
'supplier_address' : args['address'],
'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
# Get Supplier Details
@ -322,23 +295,24 @@ class TransactionBase(StatusUpdater):
[d[0] for d in fields], as_dict=1)
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):
out = {}
# get addresses
billing_address = get_address_dict(party_field, party_name)
billing_address = get_default_address(party_field, party_name)
if billing_address:
out[party_field + "_address"] = billing_address["name"]
out[party_field + "_address"] = billing_address
out["address_display"] = get_address_display(billing_address)
else:
out[party_field + "_address"] = out["address_display"] = None
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:
out["shipping_address_name"] = shipping_address["name"]
out["shipping_address_name"] = shipping_address
out["shipping_address"] = get_address_display(shipping_address)
else:
out["shipping_address_name"] = out["shipping_address"] = None
@ -346,39 +320,47 @@ def get_default_address_and_contact(party_field, party_name, fetch_shipping_addr
# get contact
if party_field == "lead":
out["customer_address"] = out.get("lead_address")
out.update(map_lead_fields(party_name))
out.update(map_lead_contact_details(party_name))
else:
out.update(map_contact_fields(party_field, party_name))
out.update(map_party_contact_details(None, party_field, party_name))
return out
def get_address_dict(party_field, party_name, is_shipping_address=None):
order_by = "is_shipping_address desc, is_primary_address desc, name asc" if \
is_shipping_address else "is_primary_address desc, name asc"
address = webnotes.conn.sql("""select * from `tabAddress` where `%s`=%s order by %s
limit 1""" % (party_field, "%s", order_by), party_name, as_dict=True,
update={"doctype": "Address"})
return address[0] if address else None
def get_default_address(party_field, party_name, is_shipping_address=False):
if is_shipping_address:
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 name from `tabAddress` where `%s`=%s order by %s
limit 1""" % (party_field, "%s", order_by), party_name)
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 _prepare_for_display(a_dict, sequence):
display = ""
for separator, fieldname in sequence:
if a_dict.get(fieldname):
display += separator + a_dict.get(fieldname)
return display.strip()
if not isinstance(address_dict, dict):
address_dict = webnotes.conn.get_value("Address", address_dict, "*", as_dict=True)
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" + 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)
return display.strip()
def map_lead_fields(party_name):
def map_lead_contact_details(party_name):
out = {}
for fieldname in ["contact_display", "contact_email", "contact_mobile", "contact_phone"]:
out[fieldname] = None
@ -395,15 +377,19 @@ def map_lead_fields(party_name):
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 = {}
for fieldname in ["contact_person", "contact_display", "contact_email",
"contact_mobile", "contact_phone", "contact_designation", "contact_department"]:
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
order by is_primary_contact desc, name asc limit 1""" % (party_field, "%s"),
(party_name,), as_dict=True)
if contact:
contact = contact[0]
out.update({

View File

@ -41,6 +41,10 @@ img {
margin-left: 5px;
}
div.web-footer {
border-top: 1px solid #dddddd;
padding-top: 10px;
}
.web-footer-menu ul {
list-style: none;
@ -136,6 +140,10 @@ img {
padding-left: 10px;
}
fieldset {
margin-bottom: 20px;
}
/* buttons */
.btn-default {
color: #ffffff;

View File

@ -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"
},
@ -44,6 +44,19 @@
"fieldtype": "Check",
"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",
"fieldname": "default_territory",
@ -52,6 +65,24 @@
"options": "Territory",
"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",
"fieldname": "price_lists",
@ -60,14 +91,6 @@
"options": "Shopping Cart Price List",
"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",
"fieldname": "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"

View File

@ -9,7 +9,7 @@ body {
background-color: #{{ doc.background_color }};
background-image: none;
{% else %}
background-color: #edede7;
background-color: #ffffff;
{% endif %}
{% if doc.font or doc.google_web_font_for_text %}
font-family: '{{ doc.google_web_font_for_text or doc.font }}', 'Helvetica Neue', Arial, Sans !important;

View File

@ -34,7 +34,7 @@ $.extend(cur_frm.cscript, {
url: function(doc, cdt, cdn) {
this.label(doc, cdt, cdn);
}
},
set_parent_label_options: function() {
wn.meta.get_docfield("Top Bar Item", "parent_label", cur_frm.docname).options =

View File

@ -2,7 +2,7 @@
{
"creation": "2013-04-30 12:58:46",
"docstatus": 0,
"modified": "2013-07-05 15:02:50",
"modified": "2013-07-10 20:37:38",
"modified_by": "Administrator",
"owner": "Administrator"
},

View File

@ -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 @@ def get_cart_quotation(doclist=None):
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 @@ def update_cart(item_code, qty, with_doclist=0):
quotation.ignore_permissions = True
quotation.save()
set_cart_count(quotation)
if with_doclist:
return get_cart_quotation(quotation.doclist)
else:
@ -192,11 +223,47 @@ def _get_cart_quotation(party=None):
"__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 @@ def set_taxes(quotation, cart_settings, billing_territory):
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")

View File

@ -1,4 +1,4 @@
<div class="navbar navbar-inverse" style="">
<div class="navbar" style="margin: 0px -15px">
{%- if brand_html %}<a class="navbar-brand" href="index">{{ brand_html }}</a>{% endif -%}
<div class="container">
<button type="button" class="navbar-toggle" data-toggle="collapse"

View File

@ -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>

View File

@ -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;">

View File

@ -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 @@ $(document).ready(function() {
wn.cart.show_error("Oops!", "Something went wrong.");
}
} else {
wn.cart.set_cart_count();
wn.cart.render(r.message);
}
}
@ -75,6 +74,10 @@ $.extend(wn.cart, {
$("#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 @@ $.extend(wn.cart, {
$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);
}
}
});
}
});

View File

@ -112,12 +112,4 @@
};
})();
</script>
{% 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>
<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 %}

View File

@ -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 @@ $(document).ready(function() {
$("#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 @@ $(document).ready(function() {
})
})
</script>
{% endblock %}
{% endblock %}