[shopping-cart] i'm back
diff --git a/erpnext/config/desktop.py b/erpnext/config/desktop.py
index 34f1599..ce9b255 100644
--- a/erpnext/config/desktop.py
+++ b/erpnext/config/desktop.py
@@ -48,5 +48,12 @@
"color": "#2c3e50",
"icon": "icon-phone",
"type": "module"
+ },
+ "Shopping Cart": {
+ "color": "#B7E090",
+ "icon": "icon-shopping-cart",
+ "label": _("Shopping Cart"),
+ "link": "Form/Shopping Cart Settings",
+ "type": "module"
}
}
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 54b911a..ea65400 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -11,14 +11,18 @@
app_include_js = "assets/js/erpnext.min.js"
app_include_css = "assets/css/erpnext.css"
web_include_js = "assets/js/erpnext-web.min.js"
+web_include_css = "assets/css/shopping-cart-web.css"
after_install = "erpnext.setup.install.after_install"
boot_session = "erpnext.startup.boot.boot_session"
notification_config = "erpnext.startup.notifications.get_notification_config"
+on_session_creation = "erpnext.shopping_cart.utils.set_cart_count"
+on_logout = "erpnext.shopping_cart.utils.clear_cart_count"
+update_website_context = ["erpnext.shopping_cart.utils.update_website_context", "erpnext.startup.webutils.update_website_context"]
+
dump_report_map = "erpnext.startup.report_data_map.data_map"
-update_website_context = "erpnext.startup.webutils.update_website_context"
before_tests = "erpnext.setup.utils.before_tests"
@@ -36,7 +40,13 @@
"User": {
"validate": "erpnext.hr.doctype.employee.employee.validate_employee_role",
"on_update": "erpnext.hr.doctype.employee.employee.update_user_permissions"
- }
+ },
+ "Sales Taxes and Charges Master": {
+ "on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings"
+ },
+ "Price List": {
+ "on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings"
+ },
}
scheduler_events = {
@@ -55,6 +65,5 @@
]
}
-default_mail_footer = """<div style="padding: 7px; text-align: right; color: #888"><small>
- <a style="color: #888" href="https://erpnext.com">Sent via ERPNext</a></div>"""
-
+default_mail_footer = """<div style="padding: 7px; text-align: right;">
+ <a style="color: #888; font-size: 80%;" href="https://erpnext.com">Sent via ERPNext</a></div>"""
diff --git a/erpnext/modules.txt b/erpnext/modules.txt
index 68d095e..243c2d8 100644
--- a/erpnext/modules.txt
+++ b/erpnext/modules.txt
@@ -9,3 +9,4 @@
Support
Utilities
Contacts
+Shopping Cart
diff --git a/erpnext/patches/v4_2/party_model.py b/erpnext/patches/v4_2/party_model.py
index e1fa982..2871531 100644
--- a/erpnext/patches/v4_2/party_model.py
+++ b/erpnext/patches/v4_2/party_model.py
@@ -74,6 +74,9 @@
for d in accounts:
account_map.setdefault(d.name, d)
+ if not account_map:
+ return
+
for dt in ["Journal Voucher Detail", "GL Entry"]:
records = frappe.db.sql("""select name, account from `tab%s` where account in (%s)""" %
(dt, ", ".join(['%s']*len(account_map))), tuple(account_map.keys()))
diff --git a/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py b/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py
index f569695..e4bf9a9 100644
--- a/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py
+++ b/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py
@@ -7,6 +7,6 @@
account_settings = frappe.get_doc("Accounts Settings")
if not account_settings.frozen_accounts_modifier and account_settings.bde_auth_role:
- account_settings.frozen_accounts_modifier = account_settings.bde_auth_role
+ frappe.db.set_value("Account Settings", None,
+ "frozen_accounts_modifier", account_settings.bde_auth_role)
- account_settings.save()
diff --git a/erpnext/public/build.json b/erpnext/public/build.json
index 0998c53..3f6dd12 100644
--- a/erpnext/public/build.json
+++ b/erpnext/public/build.json
@@ -3,7 +3,8 @@
"public/css/erpnext.css"
],
"js/erpnext-web.min.js": [
- "public/js/website_utils.js"
+ "public/js/website_utils.js",
+ "public/js/shopping_cart.js"
],
"js/erpnext.min.js": [
"public/js/conf.js",
@@ -11,5 +12,8 @@
"public/js/utils.js",
"public/js/queries.js",
"public/js/utils/party.js"
+ ],
+ "css/shopping-cart-web.css": [
+ "public/css/shopping_cart.css"
]
}
diff --git a/erpnext/public/css/shopping_cart.css b/erpnext/public/css/shopping_cart.css
new file mode 100644
index 0000000..5e86972
--- /dev/null
+++ b/erpnext/public/css/shopping_cart.css
@@ -0,0 +1,11 @@
+.item-main-image {
+ max-width: 100%;
+ margin: auto;
+}
+.web-long-description {
+ font-size: 18px;
+ line-height: 200%;
+}
+.item-stock {
+ margin-bottom: 10px !important;
+}
diff --git a/erpnext/public/js/shopping_cart.js b/erpnext/public/js/shopping_cart.js
new file mode 100644
index 0000000..0c718b0
--- /dev/null
+++ b/erpnext/public/js/shopping_cart.js
@@ -0,0 +1,66 @@
+// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+// License: GNU General Public License v3. See license.txt
+
+// shopping cart
+frappe.provide("shopping_cart");
+
+$(function() {
+ // update user
+ if(full_name) {
+ $('.navbar li[data-label="User"] a')
+ .html('<i class="icon-fixed-width icon-user"></i> ' + full_name);
+ }
+
+ // update login
+ shopping_cart.set_cart_count();
+});
+
+$.extend(shopping_cart, {
+ update_cart: function(opts) {
+ if(!full_name) {
+ if(localStorage) {
+ localStorage.setItem("last_visited", window.location.pathname);
+ localStorage.setItem("pending_add_to_cart", opts.item_code);
+ }
+ window.location.href = "/login";
+ } else {
+ return frappe.call({
+ type: "POST",
+ method: "erpnext.shopping_cart.cart.update_cart",
+ args: {
+ item_code: opts.item_code,
+ qty: opts.qty,
+ with_doc: opts.with_doc || 0
+ },
+ btn: opts.btn,
+ callback: function(r) {
+ if(opts.callback)
+ opts.callback(r);
+
+ shopping_cart.set_cart_count();
+ }
+ });
+ }
+ },
+
+ set_cart_count: function() {
+ var cart_count = getCookie("cart_count");
+ var $cart = $("#website-post-login").find('[data-label="Cart"]');
+ var $badge = $cart.find(".badge");
+ var $cog = $("#website-post-login").find(".dropdown-toggle");
+ var $cog_count = $cog.find(".cart-count");
+ if(cart_count) {
+ if($badge.length === 0) {
+ var $badge = $('<span class="badge pull-right"></span>').prependTo($cart.find("a"));
+ }
+ $badge.html(cart_count);
+ if($cog_count.length === 0) {
+ var $cog_count = $('<sup class="cart-count"></span>').insertAfter($cog.find(".icon-cog"));
+ }
+ $cog_count.html(cart_count);
+ } else {
+ $badge.remove();
+ $cog_count.remove();
+ }
+ }
+});
diff --git a/erpnext/shopping_cart/__init__.py b/erpnext/shopping_cart/__init__.py
new file mode 100644
index 0000000..656918b
--- /dev/null
+++ b/erpnext/shopping_cart/__init__.py
@@ -0,0 +1,126 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.utils import get_fullname, flt
+from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import is_shopping_cart_enabled, get_default_territory
+
+# TODO
+# validate stock of each item in Website Warehouse or have a list of possible warehouses in Shopping Cart Settings
+
+def get_quotation(user=None):
+ if not user:
+ user = frappe.session.user
+ if user == "Guest":
+ raise frappe.PermissionError
+
+ is_shopping_cart_enabled()
+ party = get_party(user)
+ values = {
+ "order_type": "Shopping Cart",
+ party.doctype.lower(): party.name,
+ "docstatus": 0,
+ "contact_email": user
+ }
+
+ try:
+ quotation = frappe.get_doc("Quotation", values)
+ except frappe.DoesNotExistError:
+ quotation = frappe.new_doc("Quotation")
+ quotation.update(values)
+ if party.doctype == "Customer":
+ quotation.contact_person = frappe.db.get_value("Contact", {"customer": party.name, "email_id": user})
+ quotation.insert(ignore_permissions=True)
+
+ return quotation
+
+def set_item_in_cart(item_code, qty, user=None):
+ validate_item(item_code)
+ quotation = get_quotation(user=user)
+ qty = flt(qty)
+ quotation_item = quotation.get("quotation_details", {"item_code": item_code})
+
+ if qty==0:
+ if quotation_item:
+ # remove
+ quotation.get("quotation_details").remove(quotation_item[0])
+ else:
+ # add or update
+ if quotation_item:
+ quotation_item[0].qty = qty
+ else:
+ quotation.append("quotation_details", {
+ "doctype": "Quotation Item",
+ "item_code": item_code,
+ "qty": qty
+ })
+
+ quotation.save(ignore_permissions=True)
+ return quotation
+
+def set_address_in_cart(address_fieldname, address, user=None):
+ quotation = get_quotation(user=user)
+ validate_address(quotation, address_fieldname, address)
+
+ if quotation.get(address_fieldname) != address:
+ quotation.set(address_fieldname, address)
+ if address_fieldname=="customer_address":
+ quotation.set("address_display", None)
+ else:
+ quotation.set("shipping_address", None)
+
+ quotation.save(ignore_permissions=True)
+
+ return quotation
+
+def validate_item(item_code):
+ item = frappe.db.get_value("Item", item_code, ["item_name", "show_in_website"], as_dict=True)
+ if not item.show_in_website:
+ frappe.throw(_("{0} cannot be purchased using Shopping Cart").format(item.item_name))
+
+def validate_address(quotation, address_fieldname, address):
+ party = get_party(quotation.contact_email)
+ address_doc = frappe.get_doc(address)
+ if address_doc.get(party.doctype.lower()) != party.name:
+ if address_fieldname=="customer_address":
+ frappe.throw(_("Invalid Billing Address"))
+ else:
+ frappe.throw(_("Invalid Shipping Address"))
+
+def get_party(user):
+ def _get_party(user):
+ customer = frappe.db.get_value("Contact", {"email_id": user}, "customer")
+ if customer:
+ return frappe.get_doc("Customer", customer)
+
+ lead = frappe.db.get_value("Lead", {"email_id": user})
+ if lead:
+ return frappe.get_doc("Lead", lead)
+
+ # create a lead
+ lead = frappe.new_doc("Lead")
+ lead.update({
+ "email_id": user,
+ "lead_name": get_fullname(user),
+ "territory": guess_territory()
+ })
+ lead.insert(ignore_permissions=True)
+
+ return lead
+
+ if not getattr(frappe.local, "shopping_cart_party", None):
+ frappe.local.shopping_cart_party = {}
+
+ if not frappe.local.shopping_cart_party.get(user):
+ frappe.local.shopping_cart_party[user] = _get_party(user)
+
+ return frappe.local.shopping_cart_party[user]
+
+def guess_territory():
+ territory = None
+ if frappe.session.get("session_country"):
+ territory = frappe.db.get_value("Territory", frappe.session.get("session_country"))
+
+ return territory or get_default_territory()
diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py
new file mode 100644
index 0000000..e39a54c
--- /dev/null
+++ b/erpnext/shopping_cart/cart.py
@@ -0,0 +1,434 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import throw, _
+import frappe.defaults
+from frappe.utils import flt, get_fullname, fmt_money, cstr
+from erpnext.utilities.doctype.address.address import get_address_display
+from frappe.utils.nestedset import get_root_of
+
+class WebsitePriceListMissingError(frappe.ValidationError): pass
+
+def set_cart_count(quotation=None):
+ if not quotation:
+ quotation = _get_cart_quotation()
+ cart_count = cstr(len(quotation.get("quotation_details")))
+ frappe.local.cookie_manager.set_cookie("cart_count", cart_count)
+
+@frappe.whitelist()
+def get_cart_quotation(doc=None):
+ party = get_lead_or_customer()
+
+ if not doc:
+ quotation = _get_cart_quotation(party)
+ doc = quotation
+ set_cart_count(quotation)
+
+ return {
+ "doc": decorate_quotation_doc(doc),
+ "addresses": [{"name": address.name, "display": address.display}
+ for address in get_address_docs(party)],
+ "shipping_rules": get_applicable_shipping_rules(party)
+ }
+
+@frappe.whitelist()
+def place_order():
+ quotation = _get_cart_quotation()
+ quotation.company = frappe.db.get_value("Shopping Cart Settings", None, "company")
+ for fieldname in ["customer_address", "shipping_address_name"]:
+ if not quotation.get(fieldname):
+ throw(_("{0} is required").format(quotation.meta.get_label(fieldname)))
+
+ quotation.ignore_permissions = True
+ quotation.submit()
+
+ if quotation.lead:
+ # company used to create customer accounts
+ frappe.defaults.set_user_default("company", quotation.company)
+
+ from erpnext.selling.doctype.quotation.quotation import _make_sales_order
+ sales_order = frappe.get_doc(_make_sales_order(quotation.name, ignore_permissions=True))
+ for item in sales_order.get("sales_order_details"):
+ item.reserved_warehouse = frappe.db.get_value("Item", item.item_code, "website_warehouse") or None
+
+ sales_order.ignore_permissions = True
+ sales_order.insert()
+ sales_order.submit()
+ frappe.local.cookie_manager.delete_cookie("cart_count")
+
+ return sales_order.name
+
+@frappe.whitelist()
+def update_cart(item_code, qty, with_doc):
+ quotation = _get_cart_quotation()
+
+ qty = flt(qty)
+ if qty == 0:
+ quotation.set("quotation_details", quotation.get("quotation_details", {"item_code": ["!=", item_code]}))
+ if not quotation.get("quotation_details") and \
+ not quotation.get("__islocal"):
+ quotation.__delete = True
+
+ else:
+ quotation_items = quotation.get("quotation_details", {"item_code": item_code})
+ if not quotation_items:
+ quotation.append("quotation_details", {
+ "doctype": "Quotation Item",
+ "item_code": item_code,
+ "qty": qty
+ })
+ else:
+ quotation_items[0].qty = qty
+
+ apply_cart_settings(quotation=quotation)
+
+ if hasattr(quotation, "__delete"):
+ frappe.delete_doc("Quotation", quotation.name, ignore_permissions=True)
+ quotation = _get_cart_quotation()
+ else:
+ quotation.ignore_permissions = True
+ quotation.save()
+
+ set_cart_count(quotation)
+
+ if with_doc:
+ return get_cart_quotation(quotation)
+ else:
+ return quotation.name
+
+@frappe.whitelist()
+def update_cart_address(address_fieldname, address_name):
+ quotation = _get_cart_quotation()
+ address_display = get_address_display(frappe.get_doc("Address", address_name).as_dict())
+
+ if address_fieldname == "shipping_address_name":
+ quotation.shipping_address_name = address_name
+ quotation.shipping_address = address_display
+
+ if not quotation.customer_address:
+ address_fieldname == "customer_address"
+
+ if address_fieldname == "customer_address":
+ quotation.customer_address = address_name
+ quotation.address_display = address_display
+
+
+ apply_cart_settings(quotation=quotation)
+
+ quotation.ignore_permissions = True
+ quotation.save()
+
+ return get_cart_quotation(quotation)
+
+def guess_territory():
+ territory = None
+ geoip_country = frappe.session.get("session_country")
+ if geoip_country:
+ territory = frappe.db.get_value("Territory", geoip_country)
+
+ return territory or \
+ frappe.db.get_value("Shopping Cart Settings", None, "territory") or \
+ get_root_of("Territory")
+
+def decorate_quotation_doc(quotation_doc):
+ doc = frappe._dict(quotation_doc.as_dict())
+ for d in doc.get("quotation_details", []):
+ d.update(frappe.db.get_value("Item", d["item_code"],
+ ["website_image", "description", "page_name"], as_dict=True))
+ d["formatted_rate"] = fmt_money(d.get("rate"), currency=doc.currency)
+ d["formatted_amount"] = fmt_money(d.get("amount"), currency=doc.currency)
+
+ for d in doc.get("other_charges", []):
+ d["formatted_tax_amount"] = fmt_money(flt(d.get("tax_amount")) / doc.conversion_rate,
+ currency=doc.currency)
+
+ doc.formatted_grand_total_export = fmt_money(doc.grand_total_export,
+ currency=doc.currency)
+
+ return doc
+
+def _get_cart_quotation(party=None):
+ if not party:
+ party = get_lead_or_customer()
+
+ quotation = frappe.db.get_value("Quotation",
+ {party.doctype.lower(): party.name, "order_type": "Shopping Cart", "docstatus": 0})
+
+ if quotation:
+ qdoc = frappe.get_doc("Quotation", quotation)
+ else:
+ qdoc = frappe.get_doc({
+ "doctype": "Quotation",
+ "naming_series": frappe.defaults.get_user_default("shopping_cart_quotation_series") or "QTN-CART-",
+ "quotation_to": party.doctype,
+ "company": frappe.db.get_value("Shopping Cart Settings", None, "company"),
+ "order_type": "Shopping Cart",
+ "status": "Draft",
+ "docstatus": 0,
+ "__islocal": 1,
+ (party.doctype.lower()): party.name
+ })
+
+ if party.doctype == "Customer":
+ qdoc.contact_person = frappe.db.get_value("Contact", {"email_id": frappe.session.user,
+ "customer": party.name})
+
+ qdoc.ignore_permissions = True
+ qdoc.run_method("set_missing_values")
+ apply_cart_settings(party, qdoc)
+
+ return qdoc
+
+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 = frappe.db.get_value("Contact", {"email_id": frappe.session.user,
+ "customer": party.name})
+ contact = frappe.get_doc("Contact", contact_name)
+ contact.first_name = fullname
+ contact.last_name = None
+ contact.customer_name = party.customer_name
+ contact.mobile_no = mobile_no
+ contact.phone = phone
+ contact.ignore_permissions = True
+ contact.save()
+
+ party_doc = frappe.get_doc(party.as_dict())
+ party_doc.ignore_permissions = True
+ party_doc.save()
+
+ qdoc = _get_cart_quotation(party)
+ if not qdoc.get("__islocal"):
+ qdoc.customer_name = company_name or fullname
+ qdoc.run_method("set_missing_lead_customer_details")
+ qdoc.ignore_permissions = True
+ qdoc.save()
+
+def apply_cart_settings(party=None, quotation=None):
+ if not party:
+ party = get_lead_or_customer()
+ if not quotation:
+ quotation = _get_cart_quotation(party)
+
+ cart_settings = frappe.get_doc("Shopping Cart Settings")
+
+ billing_territory = get_address_territory(quotation.customer_address) or \
+ party.territory or get_root_of("Territory")
+
+ set_price_list_and_rate(quotation, cart_settings, billing_territory)
+
+ quotation.run_method("calculate_taxes_and_totals")
+
+ set_taxes(quotation, cart_settings, billing_territory)
+
+ _apply_shipping_rule(party, quotation, cart_settings)
+
+def set_price_list_and_rate(quotation, cart_settings, billing_territory):
+ """set price list based on billing territory"""
+ quotation.selling_price_list = cart_settings.get_price_list(billing_territory)
+
+ # reset values
+ quotation.price_list_currency = quotation.currency = \
+ quotation.plc_conversion_rate = quotation.conversion_rate = None
+ for item in quotation.get("quotation_details"):
+ item.price_list_rate = item.discount_percentage = item.rate = item.amount = None
+
+ # refetch values
+ quotation.run_method("set_price_list_and_item_details")
+
+ # set it in cookies for using in product page
+ frappe.local.cookie_manager.set_cookie("selling_price_list", quotation.selling_price_list)
+
+def set_taxes(quotation, cart_settings, billing_territory):
+ """set taxes based on billing territory"""
+ quotation.taxes_and_charges = cart_settings.get_tax_master(billing_territory)
+
+ # clear table
+ quotation.set("other_charges", [])
+
+ # append taxes
+ quotation.append_taxes_from_master("other_charges", "taxes_and_charges")
+
+def get_lead_or_customer():
+ customer = frappe.db.get_value("Contact", {"email_id": frappe.session.user}, "customer")
+ if customer:
+ return frappe.get_doc("Customer", customer)
+
+ lead = frappe.db.get_value("Lead", {"email_id": frappe.session.user})
+ if lead:
+ return frappe.get_doc("Lead", lead)
+ else:
+ lead_doc = frappe.get_doc({
+ "doctype": "Lead",
+ "email_id": frappe.session.user,
+ "lead_name": get_fullname(frappe.session.user),
+ "territory": guess_territory(),
+ "status": "Open" # TODO: set something better???
+ })
+
+ if frappe.session.user not in ("Guest", "Administrator"):
+ lead_doc.ignore_permissions = True
+ lead_doc.insert()
+
+ return lead_doc
+
+def get_address_docs(party=None):
+ if not party:
+ party = get_lead_or_customer()
+
+ address_docs = frappe.db.sql("""select * from `tabAddress`
+ where `%s`=%s order by name""" % (party.doctype.lower(), "%s"), party.name,
+ as_dict=True, update={"doctype": "Address"})
+
+ for address in address_docs:
+ address.display = get_address_display(address)
+ address.display = (address.display).replace("\n", "<br>\n")
+
+ return address_docs
+
+@frappe.whitelist()
+def apply_shipping_rule(shipping_rule):
+ quotation = _get_cart_quotation()
+
+ quotation.shipping_rule = shipping_rule
+
+ apply_cart_settings(quotation=quotation)
+
+ quotation.ignore_permissions = True
+ quotation.save()
+
+ return get_cart_quotation(quotation)
+
+def _apply_shipping_rule(party=None, quotation=None, cart_settings=None):
+ shipping_rules = get_shipping_rules(party, quotation, cart_settings)
+
+ if not shipping_rules:
+ return
+
+ elif quotation.shipping_rule not in shipping_rules:
+ quotation.shipping_rule = shipping_rules[0]
+
+ quotation.run_method("apply_shipping_rule")
+ quotation.run_method("calculate_taxes_and_totals")
+
+def get_applicable_shipping_rules(party=None, quotation=None):
+ shipping_rules = get_shipping_rules(party, quotation)
+
+ if shipping_rules:
+ rule_label_map = frappe.db.get_values("Shipping Rule", shipping_rules, "label")
+ # we need this in sorted order as per the position of the rule in the settings page
+ return [[rule, rule_label_map.get(rule)] for rule in shipping_rules]
+
+def get_shipping_rules(party=None, quotation=None, cart_settings=None):
+ if not party:
+ party = get_lead_or_customer()
+ if not quotation:
+ quotation = _get_cart_quotation()
+ if not cart_settings:
+ cart_settings = frappe.get_doc("Shopping Cart Settings")
+
+ # set shipping rule based on shipping territory
+ shipping_territory = get_address_territory(quotation.shipping_address_name) or \
+ party.territory
+
+ shipping_rules = cart_settings.get_shipping_rules(shipping_territory)
+
+ return shipping_rules
+
+def get_address_territory(address_name):
+ """Tries to match city, state and country of address to existing territory"""
+ territory = None
+
+ if address_name:
+ address_fields = frappe.db.get_value("Address", address_name,
+ ["city", "state", "country"])
+ for value in address_fields:
+ territory = frappe.db.get_value("Territory", value)
+ if territory:
+ break
+
+ return territory
+
+import unittest
+test_dependencies = ["Item", "Price List", "Contact", "Shopping Cart Settings"]
+
+class TestCart(unittest.TestCase):
+ def tearDown(self):
+ return
+
+ cart_settings = frappe.get_doc("Shopping Cart Settings")
+ cart_settings.ignore_permissions = True
+ cart_settings.enabled = 0
+ cart_settings.save()
+
+ def enable_shopping_cart(self):
+ return
+ if not frappe.db.get_value("Shopping Cart Settings", None, "enabled"):
+ cart_settings = frappe.get_doc("Shopping Cart Settings")
+ cart_settings.ignore_permissions = True
+ cart_settings.enabled = 1
+ cart_settings.save()
+
+ def test_get_lead_or_customer(self):
+ frappe.session.user = "test@example.com"
+ party1 = get_lead_or_customer()
+ party2 = get_lead_or_customer()
+ self.assertEquals(party1.name, party2.name)
+ self.assertEquals(party1.doctype, "Lead")
+
+ frappe.session.user = "test_contact_customer@example.com"
+ party = get_lead_or_customer()
+ self.assertEquals(party.name, "_Test Customer")
+
+ def test_add_to_cart(self):
+ self.enable_shopping_cart()
+ frappe.session.user = "test@example.com"
+
+ update_cart("_Test Item", 1)
+
+ quotation = _get_cart_quotation()
+ quotation_items = quotation.get("quotation_details", {"item_code": "_Test Item"})
+ self.assertTrue(quotation_items)
+ self.assertEquals(quotation_items[0].qty, 1)
+
+ return quotation
+
+ def test_update_cart(self):
+ self.test_add_to_cart()
+
+ update_cart("_Test Item", 5)
+
+ quotation = _get_cart_quotation()
+ quotation_items = quotation.get("quotation_details", {"item_code": "_Test Item"})
+ self.assertTrue(quotation_items)
+ self.assertEquals(quotation_items[0].qty, 5)
+
+ return quotation
+
+ def test_remove_from_cart(self):
+ quotation0 = self.test_add_to_cart()
+
+ update_cart("_Test Item", 0)
+
+ quotation = _get_cart_quotation()
+ self.assertEquals(quotation0.name, quotation.name)
+
+ quotation_items = quotation.get("quotation_details", {"item_code": "_Test Item"})
+ self.assertEquals(quotation_items, [])
+
+ def test_place_order(self):
+ quotation = self.test_update_cart()
+ sales_order_name = place_order()
+ sales_order = frappe.get_doc("Sales Order", sales_order_name)
+ self.assertEquals(sales_order.getone({"item_code": "_Test Item"}).prevdoc_docname, quotation.name)
diff --git a/erpnext/shopping_cart/doctype/__init__.py b/erpnext/shopping_cart/doctype/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/__init__.py
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_price_list/__init__.py b/erpnext/shopping_cart/doctype/shopping_cart_price_list/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_price_list/__init__.py
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_price_list/shopping_cart_price_list.json b/erpnext/shopping_cart/doctype/shopping_cart_price_list/shopping_cart_price_list.json
new file mode 100644
index 0000000..12b6290
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_price_list/shopping_cart_price_list.json
@@ -0,0 +1,23 @@
+{
+ "creation": "2013-06-20 16:00:18.000000",
+ "docstatus": 0,
+ "doctype": "DocType",
+ "fields": [
+ {
+ "fieldname": "selling_price_list",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Price List",
+ "options": "Price List",
+ "permlevel": 0,
+ "reqd": 1
+ }
+ ],
+ "idx": 1,
+ "istable": 1,
+ "modified": "2013-12-20 19:30:47.000000",
+ "modified_by": "Administrator",
+ "module": "Shopping Cart",
+ "name": "Shopping Cart Price List",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_price_list/shopping_cart_price_list.py b/erpnext/shopping_cart/doctype/shopping_cart_price_list/shopping_cart_price_list.py
new file mode 100644
index 0000000..cd92576
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_price_list/shopping_cart_price_list.py
@@ -0,0 +1,12 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+from frappe.model.document import Document
+
+class ShoppingCartPriceList(Document):
+ pass
\ No newline at end of file
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/__init__.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/__init__.py
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js
new file mode 100644
index 0000000..5ea8e3e
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.js
@@ -0,0 +1,10 @@
+// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+// License: GNU General Public License v3. See license.txt
+
+$.extend(cur_frm.cscript, {
+ onload: function() {
+ if(cur_frm.doc.__onload && cur_frm.doc.__onload.quotation_series) {
+ cur_frm.fields_dict.quotation_series.df.options = cur_frm.doc.__onload.quotation_series;
+ }
+ }
+});
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json
new file mode 100644
index 0000000..7340930
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.json
@@ -0,0 +1,115 @@
+{
+ "creation": "2013-06-19 15:57:32",
+ "description": "Default settings for Shopping Cart",
+ "docstatus": 0,
+ "doctype": "DocType",
+ "fields": [
+ {
+ "fieldname": "enabled",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Enable Shopping Cart",
+ "permlevel": 0
+ },
+ {
+ "fieldname": "section_break_2",
+ "fieldtype": "Section Break",
+ "permlevel": 0
+ },
+ {
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Company",
+ "options": "Company",
+ "permlevel": 0,
+ "reqd": 1
+ },
+ {
+ "description": "<a href=\"#Sales Browser/Territory\">Add / Edit</a>",
+ "fieldname": "default_territory",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "label": "Default Territory",
+ "options": "Territory",
+ "permlevel": 0,
+ "reqd": 1
+ },
+ {
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break",
+ "permlevel": 0
+ },
+ {
+ "description": "<a href=\"#Sales Browser/Customer Group\">Add / Edit</a>",
+ "fieldname": "default_customer_group",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Default Customer Group",
+ "options": "Customer Group",
+ "permlevel": 0,
+ "reqd": 1
+ },
+ {
+ "fieldname": "quotation_series",
+ "fieldtype": "Select",
+ "label": "Quotation Series",
+ "permlevel": 0,
+ "reqd": 1
+ },
+ {
+ "fieldname": "section_break_6",
+ "fieldtype": "Section Break",
+ "permlevel": 0
+ },
+ {
+ "fieldname": "price_lists",
+ "fieldtype": "Table",
+ "label": "Shopping Cart Price Lists",
+ "options": "Shopping Cart Price List",
+ "permlevel": 0,
+ "reqd": 0
+ },
+ {
+ "fieldname": "shipping_rules",
+ "fieldtype": "Table",
+ "label": "Shopping Cart Shipping Rules",
+ "options": "Shopping Cart Shipping Rule",
+ "permlevel": 0,
+ "reqd": 0
+ },
+ {
+ "fieldname": "column_break_10",
+ "fieldtype": "Column Break",
+ "permlevel": 0
+ },
+ {
+ "fieldname": "sales_taxes_and_charges_masters",
+ "fieldtype": "Table",
+ "label": "Shopping Cart Taxes and Charges Masters",
+ "options": "Shopping Cart Taxes and Charges Master",
+ "permlevel": 0,
+ "reqd": 0
+ }
+ ],
+ "icon": "icon-shopping-cart",
+ "idx": 1,
+ "issingle": 1,
+ "modified": "2014-05-26 03:05:53.747800",
+ "modified_by": "Administrator",
+ "module": "Shopping Cart",
+ "name": "Shopping Cart Settings",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "email": 1,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "role": "Website Manager",
+ "write": 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py
new file mode 100644
index 0000000..48e31f6
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py
@@ -0,0 +1,215 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _, msgprint
+from frappe.utils import comma_and
+from frappe.model.document import Document
+from frappe.utils.nestedset import get_ancestors_of
+from erpnext.utilities.doctype.address.address import get_territory_from_address
+
+class ShoppingCartSetupError(frappe.ValidationError): pass
+
+class ShoppingCartSettings(Document):
+ def onload(self):
+ self.get("__onload").quotation_series = frappe.get_meta("Quotation").get_options("naming_series")
+
+ def validate(self):
+ if self.enabled:
+ self.validate_price_lists()
+ self.validate_tax_masters()
+ self.validate_exchange_rates_exist()
+
+ def on_update(self):
+ frappe.db.set_default("shopping_cart_enabled", self.get("enabled") or 0)
+ frappe.db.set_default("shopping_cart_quotation_series", self.get("quotation_series"))
+
+ def validate_overlapping_territories(self, parentfield, fieldname):
+ # for displaying message
+ doctype = self.meta.get_field(parentfield).options
+
+ # specify atleast one entry in the table
+ self.validate_table_has_rows(parentfield, raise_exception=ShoppingCartSetupError)
+
+ territory_name_map = self.get_territory_name_map(parentfield, fieldname)
+ for territory, names in territory_name_map.items():
+ if len(names) > 1:
+ frappe.throw(_("{0} {1} has a common territory {2}").format(_(doctype), comma_and(names), territory), ShoppingCartSetupError)
+
+ return territory_name_map
+
+ def validate_price_lists(self):
+ territory_name_map = self.validate_overlapping_territories("price_lists", "selling_price_list")
+
+ # validate that a Shopping Cart Price List exists for the default territory as a catch all!
+ price_list_for_default_territory = self.get_name_from_territory(self.default_territory, "price_lists",
+ "selling_price_list")
+
+ if not price_list_for_default_territory:
+ msgprint(_("Please specify a Price List which is valid for Territory") +
+ ": " + self.default_territory, raise_exception=ShoppingCartSetupError)
+
+ def validate_tax_masters(self):
+ self.validate_overlapping_territories("sales_taxes_and_charges_masters",
+ "sales_taxes_and_charges_master")
+
+ def get_territory_name_map(self, parentfield, fieldname):
+ territory_name_map = {}
+
+ # entries in table
+ names = [doc.get(fieldname) for doc in self.get(parentfield)]
+
+ if names:
+ # for condition in territory check
+ parenttype = frappe.get_meta(self.meta.get_options(parentfield)).get_options(fieldname)
+
+ # to validate territory overlap
+ # make a map of territory: [list of names]
+ # if list against each territory has more than one element, raise exception
+ territory_name = frappe.db.sql("""select `territory`, `parent`
+ from `tabApplicable Territory`
+ where `parenttype`=%s and `parent` in (%s)""" %
+ ("%s", ", ".join(["%s"]*len(names))), tuple([parenttype] + names))
+
+ for territory, name in territory_name:
+ territory_name_map.setdefault(territory, []).append(name)
+
+ if len(territory_name_map[territory]) > 1:
+ territory_name_map[territory].sort(key=lambda val: names.index(val))
+
+ return territory_name_map
+
+ def validate_exchange_rates_exist(self):
+ """check if exchange rates exist for all Price List currencies (to company's currency)"""
+ company_currency = frappe.db.get_value("Company", self.company, "default_currency")
+ if not company_currency:
+ msgprint(_("Please specify currency in Company") + ": " + self.company,
+ raise_exception=ShoppingCartSetupError)
+
+ price_list_currency_map = frappe.db.get_values("Price List",
+ [d.selling_price_list for d in self.get("price_lists")],
+ "currency")
+
+ # check if all price lists have a currency
+ for price_list, currency in price_list_currency_map.items():
+ if not currency:
+ frappe.throw(_("Currency is required for Price List {0}").format(price_list))
+
+ expected_to_exist = [currency + "-" + company_currency
+ for currency in price_list_currency_map.values()
+ if currency != company_currency]
+
+ if expected_to_exist:
+ exists = frappe.db.sql_list("""select name from `tabCurrency Exchange`
+ where name in (%s)""" % (", ".join(["%s"]*len(expected_to_exist)),),
+ tuple(expected_to_exist))
+
+ missing = list(set(expected_to_exist).difference(exists))
+
+ if missing:
+ msgprint(_("Missing Currency Exchange Rates for {0}").format(comma_and(missing)),
+ raise_exception=ShoppingCartSetupError)
+
+ def get_name_from_territory(self, territory, parentfield, fieldname):
+ name = None
+ territory_name_map = self.get_territory_name_map(parentfield, fieldname)
+
+ if territory_name_map.get(territory):
+ name = territory_name_map.get(territory)
+ else:
+ territory_ancestry = self.get_territory_ancestry(territory)
+ for ancestor in territory_ancestry:
+ if territory_name_map.get(ancestor):
+ name = territory_name_map.get(ancestor)
+ break
+
+ return name
+
+ def get_price_list(self, billing_territory):
+ price_list = self.get_name_from_territory(billing_territory, "price_lists", "selling_price_list")
+ return price_list and price_list[0] or None
+
+ def get_tax_master(self, billing_territory):
+ tax_master = self.get_name_from_territory(billing_territory, "sales_taxes_and_charges_masters",
+ "sales_taxes_and_charges_master")
+ return tax_master and tax_master[0] or None
+
+ def get_shipping_rules(self, shipping_territory):
+ return self.get_name_from_territory(shipping_territory, "shipping_rules", "shipping_rule")
+
+ def get_territory_ancestry(self, territory):
+ if not hasattr(self, "_territory_ancestry"):
+ self._territory_ancestry = {}
+
+ if not self._territory_ancestry.get(territory):
+ self._territory_ancestry[territory] = get_ancestors_of("Territory", territory)
+
+ return self._territory_ancestry[territory]
+
+def validate_cart_settings(doc, method):
+ frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings").run_method("validate")
+
+def get_shopping_cart_settings():
+ if not getattr(frappe.local, "shopping_cart_settings", None):
+ frappe.local.shopping_cart_settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings")
+
+ return frappe.local.shopping_cart_settings
+
+def get_default_territory():
+ return get_shopping_cart_settings().default_territory
+
+def is_shopping_cart_enabled():
+ if not get_shopping_cart_settings().enabled:
+ frappe.throw(_("You need to enable Shopping Cart"), ShoppingCartSetupError)
+
+def apply_shopping_cart_settings(quotation, method):
+ """Called via a validate hook on Quotation"""
+ from erpnext.shopping_cart import get_party
+ if quotation.order_type != "Shopping Cart":
+ return
+
+ quotation.billing_territory = (get_territory_from_address(quotation.customer_address)
+ or get_party(quotation.contact_email).territory or get_default_territory())
+ quotation.shipping_territory = (get_territory_from_address(quotation.shipping_address_name)
+ or get_party(quotation.contact_email).territory or get_default_territory())
+
+ set_price_list(quotation)
+ set_taxes_and_charges(quotation)
+ quotation.calculate_taxes_and_totals()
+ set_shipping_rule(quotation)
+
+def set_price_list(quotation):
+ previous_selling_price_list = quotation.selling_price_list
+ quotation.selling_price_list = get_shopping_cart_settings().get_price_list(quotation.billing_territory)
+
+ if not quotation.selling_price_list:
+ quotation.selling_price_list = get_shopping_cart_settings().get_price_list(get_default_territory())
+
+ if previous_selling_price_list != quotation.selling_price_list:
+ quotation.price_list_currency = quotation.currency = quotation.plc_conversion_rate = quotation.conversion_rate = None
+ for d in quotation.get("quotation_details"):
+ d.price_list_rate = d.discount_percentage = d.rate = d.amount = None
+
+ quotation.set_price_list_and_item_details()
+
+def set_taxes_and_charges(quotation):
+ previous_taxes_and_charges = quotation.taxes_and_charges
+ quotation.taxes_and_charges = get_shopping_cart_settings().get_tax_master(quotation.billing_territory)
+
+ if previous_taxes_and_charges != quotation.taxes_and_charges:
+ quotation.set_other_charges()
+
+def set_shipping_rule(quotation):
+ shipping_rules = get_shopping_cart_settings().get_shipping_rules(quotation.shipping_territory)
+ if not shipping_rules:
+ quotation.remove_shipping_charge()
+ return
+
+ if quotation.shipping_rule not in shipping_rules:
+ quotation.remove_shipping_charge()
+ quotation.shipping_rule = shipping_rules[0]
+
+ quotation.apply_shipping_rule()
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py
new file mode 100644
index 0000000..a45aaa4
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py
@@ -0,0 +1,79 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+import unittest
+from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import ShoppingCartSetupError
+
+class TestShoppingCartSettings(unittest.TestCase):
+ def setUp(self):
+ frappe.db.sql("""delete from `tabSingles` where doctype="Shipping Cart Settings" """)
+ frappe.db.sql("""delete from `tabShopping Cart Price List`""")
+ frappe.db.sql("""delete from `tabShopping Cart Taxes and Charges Master`""")
+ frappe.db.sql("""delete from `tabShopping Cart Shipping Rule`""")
+
+ def get_cart_settings(self):
+ return frappe.get_doc({"doctype": "Shopping Cart Settings",
+ "company": "_Test Company"})
+
+ def test_price_list_territory_overlap(self):
+ cart_settings = self.get_cart_settings()
+
+ def _add_price_list(price_list):
+ cart_settings.append("price_lists", {
+ "doctype": "Shopping Cart Price List",
+ "selling_price_list": price_list
+ })
+
+ for price_list in ("_Test Price List Rest of the World", "_Test Price List India",
+ "_Test Price List"):
+ _add_price_list(price_list)
+
+ controller = cart_settings
+ controller.validate_overlapping_territories("price_lists", "selling_price_list")
+
+ _add_price_list("_Test Price List 2")
+
+ controller = cart_settings
+ self.assertRaises(ShoppingCartSetupError, controller.validate_overlapping_territories,
+ "price_lists", "selling_price_list")
+
+ return cart_settings
+
+ def test_taxes_territory_overlap(self):
+ cart_settings = self.get_cart_settings()
+
+ def _add_tax_master(tax_master):
+ cart_settings.append("sales_taxes_and_charges_masters", {
+ "doctype": "Shopping Cart Taxes and Charges Master",
+ "sales_taxes_and_charges_master": tax_master
+ })
+
+ for tax_master in ("_Test Sales Taxes and Charges Master", "_Test India Tax Master"):
+ _add_tax_master(tax_master)
+
+ controller = cart_settings
+ controller.validate_overlapping_territories("sales_taxes_and_charges_masters",
+ "sales_taxes_and_charges_master")
+
+ _add_tax_master("_Test Sales Taxes and Charges Master - Rest of the World")
+
+ controller = cart_settings
+ self.assertRaises(ShoppingCartSetupError, controller.validate_overlapping_territories,
+ "sales_taxes_and_charges_masters", "sales_taxes_and_charges_master")
+
+ def test_exchange_rate_exists(self):
+ frappe.db.sql("""delete from `tabCurrency Exchange`""")
+
+ cart_settings = self.test_price_list_territory_overlap()
+ controller = cart_settings
+ self.assertRaises(ShoppingCartSetupError, controller.validate_exchange_rates_exist)
+
+ from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records as \
+ currency_exchange_records
+ frappe.get_doc(currency_exchange_records[0]).insert()
+ controller.validate_exchange_rates_exist()
+
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_shipping_rule/__init__.py b/erpnext/shopping_cart/doctype/shopping_cart_shipping_rule/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_shipping_rule/__init__.py
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_shipping_rule/shopping_cart_shipping_rule.json b/erpnext/shopping_cart/doctype/shopping_cart_shipping_rule/shopping_cart_shipping_rule.json
new file mode 100644
index 0000000..5ff55f9
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_shipping_rule/shopping_cart_shipping_rule.json
@@ -0,0 +1,23 @@
+{
+ "creation": "2013-07-03 13:15:34.000000",
+ "docstatus": 0,
+ "doctype": "DocType",
+ "fields": [
+ {
+ "fieldname": "shipping_rule",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Shipping Rule",
+ "options": "Shipping Rule",
+ "permlevel": 0,
+ "reqd": 1
+ }
+ ],
+ "idx": 1,
+ "istable": 1,
+ "modified": "2013-12-20 19:30:47.000000",
+ "modified_by": "Administrator",
+ "module": "Shopping Cart",
+ "name": "Shopping Cart Shipping Rule",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_shipping_rule/shopping_cart_shipping_rule.py b/erpnext/shopping_cart/doctype/shopping_cart_shipping_rule/shopping_cart_shipping_rule.py
new file mode 100644
index 0000000..17aa964
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_shipping_rule/shopping_cart_shipping_rule.py
@@ -0,0 +1,12 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+from frappe.model.document import Document
+
+class ShoppingCartShippingRule(Document):
+ pass
\ No newline at end of file
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/__init__.py b/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/__init__.py
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.json b/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.json
new file mode 100644
index 0000000..bfe31e5
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.json
@@ -0,0 +1,23 @@
+{
+ "creation": "2013-06-20 16:57:03.000000",
+ "docstatus": 0,
+ "doctype": "DocType",
+ "fields": [
+ {
+ "fieldname": "sales_taxes_and_charges_master",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Tax Master",
+ "options": "Sales Taxes and Charges Master",
+ "permlevel": 0,
+ "reqd": 1
+ }
+ ],
+ "idx": 1,
+ "istable": 1,
+ "modified": "2013-12-20 19:30:47.000000",
+ "modified_by": "Administrator",
+ "module": "Shopping Cart",
+ "name": "Shopping Cart Taxes and Charges Master",
+ "owner": "Administrator"
+}
\ No newline at end of file
diff --git a/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.py b/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.py
new file mode 100644
index 0000000..e0d0f9f
--- /dev/null
+++ b/erpnext/shopping_cart/doctype/shopping_cart_taxes_and_charges_master/shopping_cart_taxes_and_charges_master.py
@@ -0,0 +1,12 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+from frappe.model.document import Document
+
+class ShoppingCartTaxesandChargesMaster(Document):
+ pass
diff --git a/erpnext/shopping_cart/product.py b/erpnext/shopping_cart/product.py
new file mode 100644
index 0000000..5a86d1d
--- /dev/null
+++ b/erpnext/shopping_cart/product.py
@@ -0,0 +1,54 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+from frappe.utils import cint, fmt_money, cstr
+from erpnext.shopping_cart.cart import _get_cart_quotation
+from urllib import unquote
+
+@frappe.whitelist(allow_guest=True)
+def get_product_info(item_code):
+ """get product price / stock info"""
+ if not cint(frappe.db.get_default("shopping_cart_enabled")):
+ return {}
+
+ cart_quotation = _get_cart_quotation()
+
+ price_list = cstr(unquote(frappe.local.request.cookies.get("selling_price_list")))
+
+ warehouse = frappe.db.get_value("Item", item_code, "website_warehouse")
+ if warehouse:
+ in_stock = frappe.db.sql("""select actual_qty from tabBin where
+ item_code=%s and warehouse=%s""", (item_code, warehouse))
+ if in_stock:
+ in_stock = in_stock[0][0] > 0 and 1 or 0
+ else:
+ in_stock = -1
+
+ price = price_list and frappe.db.sql("""select price_list_rate, currency from
+ `tabItem Price` where item_code=%s and price_list=%s""",
+ (item_code, price_list), as_dict=1) or []
+
+ price = price and price[0] or None
+ qty = 0
+
+ if price:
+ price["formatted_price"] = fmt_money(price["price_list_rate"], currency=price["currency"])
+
+ price["currency"] = not cint(frappe.db.get_default("hide_currency_symbol")) \
+ and (frappe.db.get_value("Currency", price.currency, "symbol") or price.currency) \
+ or ""
+
+ if frappe.session.user != "Guest":
+ item = cart_quotation.get({"item_code": item_code})
+ if item:
+ qty = item[0].qty
+
+ return {
+ "price": price,
+ "stock": in_stock,
+ "uom": frappe.db.get_value("Item", item_code, "stock_uom"),
+ "qty": qty
+ }
diff --git a/erpnext/shopping_cart/test_shopping_cart.py b/erpnext/shopping_cart/test_shopping_cart.py
new file mode 100644
index 0000000..f77522a
--- /dev/null
+++ b/erpnext/shopping_cart/test_shopping_cart.py
@@ -0,0 +1,230 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import unittest
+import frappe
+from erpnext.shopping_cart import get_quotation, set_item_in_cart
+
+class TestShoppingCart(unittest.TestCase):
+ """
+ Note:
+ Shopping Cart == Quotation
+ """
+ def setUp(self):
+ frappe.set_user("Administrator")
+ self.enable_shopping_cart()
+
+ def tearDown(self):
+ frappe.set_user("Administrator")
+ self.disable_shopping_cart()
+
+ def test_get_cart_new_user(self):
+ self.login_as_new_user()
+
+ # test if lead is created and quotation with new lead is fetched
+ quotation = get_quotation()
+ self.assertEquals(quotation.quotation_to, "Lead")
+ self.assertEquals(frappe.db.get_value("Lead", quotation.lead, "email_id"), "test_cart_user@example.com")
+ self.assertEquals(quotation.customer, None)
+ self.assertEquals(quotation.contact_email, frappe.session.user)
+
+ return quotation
+
+ def test_get_cart_lead(self):
+ self.login_as_lead()
+
+ # test if quotation with lead is fetched
+ quotation = get_quotation()
+ self.assertEquals(quotation.quotation_to, "Lead")
+ self.assertEquals(quotation.lead, frappe.db.get_value("Lead", {"email_id": "test_cart_lead@example.com"}))
+ self.assertEquals(quotation.customer, None)
+ self.assertEquals(quotation.contact_email, frappe.session.user)
+
+ return quotation
+
+ def test_get_cart_customer(self):
+ self.login_as_customer()
+
+ # test if quotation with customer is fetched
+ quotation = get_quotation()
+ self.assertEquals(quotation.quotation_to, "Customer")
+ self.assertEquals(quotation.customer, "_Test Customer")
+ self.assertEquals(quotation.lead, None)
+ self.assertEquals(quotation.contact_email, frappe.session.user)
+
+ return quotation
+
+ def test_add_to_cart(self):
+ self.login_as_lead()
+
+ # add first item
+ set_item_in_cart("_Test Item", 1)
+ quotation = self.test_get_cart_lead()
+ self.assertEquals(quotation.get("quotation_details")[0].item_code, "_Test Item")
+ self.assertEquals(quotation.get("quotation_details")[0].qty, 1)
+ self.assertEquals(quotation.get("quotation_details")[0].amount, 10)
+
+ # add second item
+ set_item_in_cart("_Test Item 2", 1)
+ quotation = self.test_get_cart_lead()
+ self.assertEquals(quotation.get("quotation_details")[1].item_code, "_Test Item 2")
+ self.assertEquals(quotation.get("quotation_details")[1].qty, 1)
+ self.assertEquals(quotation.get("quotation_details")[1].amount, 20)
+
+ self.assertEquals(len(quotation.get("quotation_details")), 2)
+
+ def test_update_cart(self):
+ # first, add to cart
+ self.test_add_to_cart()
+
+ # update first item
+ set_item_in_cart("_Test Item", 5)
+ quotation = self.test_get_cart_lead()
+ self.assertEquals(quotation.get("quotation_details")[0].item_code, "_Test Item")
+ self.assertEquals(quotation.get("quotation_details")[0].qty, 5)
+ self.assertEquals(quotation.get("quotation_details")[0].amount, 50)
+ self.assertEquals(quotation.net_total, 70)
+ self.assertEquals(len(quotation.get("quotation_details")), 2)
+
+ def test_remove_from_cart(self):
+ # first, add to cart
+ self.test_add_to_cart()
+
+ # remove first item
+ set_item_in_cart("_Test Item", 0)
+ quotation = self.test_get_cart_lead()
+ self.assertEquals(quotation.get("quotation_details")[0].item_code, "_Test Item 2")
+ self.assertEquals(quotation.get("quotation_details")[0].qty, 1)
+ self.assertEquals(quotation.get("quotation_details")[0].amount, 20)
+ self.assertEquals(quotation.net_total, 20)
+ self.assertEquals(len(quotation.get("quotation_details")), 1)
+
+ # remove second item
+ set_item_in_cart("_Test Item 2", 0)
+ quotation = self.test_get_cart_lead()
+ self.assertEquals(quotation.net_total, 0)
+ self.assertEquals(len(quotation.get("quotation_details")), 0)
+
+ def test_set_billing_address(self):
+ return
+
+ # first, add to cart
+ self.test_add_to_cart()
+
+ quotation = self.test_get_cart_lead()
+ default_address = frappe.get_doc("Address", {"lead": quotation.lead, "is_primary_address": 1})
+ self.assertEquals("customer_address", default_address.name)
+
+ def test_set_shipping_address(self):
+ # first, add to cart
+ self.test_add_to_cart()
+
+
+
+ def test_shipping_rule(self):
+ self.test_set_shipping_address()
+
+ # check if shipping rule changed
+ pass
+
+ def test_price_list(self):
+ self.test_set_billing_address()
+
+ # check if price changed
+ pass
+
+ def test_place_order(self):
+ pass
+
+ # helper functions
+ def enable_shopping_cart(self):
+ settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings")
+
+ if settings.default_territory == "_Test Territory Rest Of The World":
+ settings.enabled = 1
+ else:
+ settings.update({
+ "enabled": 1,
+ "company": "_Test Company",
+ "default_territory": "_Test Territory Rest Of The World",
+ "default_customer_group": "_Test Customer Group",
+ "quotation_series": "_T-Quotation-"
+ })
+ settings.set("price_lists", [
+ # price lists
+ {"doctype": "Shopping Cart Price List", "parentfield": "price_lists",
+ "selling_price_list": "_Test Price List India"},
+ {"doctype": "Shopping Cart Price List", "parentfield": "price_lists",
+ "selling_price_list": "_Test Price List Rest of the World"}
+ ])
+ settings.set("sales_taxes_and_charges_masters", [
+ # tax masters
+ {"doctype": "Shopping Cart Taxes and Charges Master", "parentfield": "sales_taxes_and_charges_masters",
+ "sales_taxes_and_charges_master": "_Test India Tax Master"},
+ {"doctype": "Shopping Cart Taxes and Charges Master", "parentfield": "sales_taxes_and_charges_masters",
+ "sales_taxes_and_charges_master": "_Test Sales Taxes and Charges Master - Rest of the World"},
+ ])
+ settings.set("shipping_rules", {"doctype": "Shopping Cart Shipping Rule", "parentfield": "shipping_rules",
+ "shipping_rule": "_Test Shipping Rule - India"})
+
+ settings.save()
+ frappe.local.shopping_cart_settings = None
+
+ def disable_shopping_cart(self):
+ settings = frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings")
+ settings.enabled = 0
+ settings.save()
+ frappe.local.shopping_cart_settings = None
+
+ def login_as_new_user(self):
+ frappe.set_user("test_cart_user@example.com")
+
+ def login_as_lead(self):
+ self.create_lead()
+ frappe.set_user("test_cart_lead@example.com")
+
+ def login_as_customer(self):
+ frappe.set_user("test_contact_customer@example.com")
+
+ def create_lead(self):
+ if frappe.db.get_value("Lead", {"email_id": "test_cart_lead@example.com"}):
+ return
+
+ lead = frappe.get_doc({
+ "doctype": "Lead",
+ "email_id": "test_cart_lead@example.com",
+ "lead_name": "_Test Website Lead",
+ "status": "Open",
+ "territory": "_Test Territory Rest Of The World"
+ })
+ lead.insert(ignore_permissions=True)
+
+ frappe.get_doc({
+ "doctype": "Address",
+ "address_line1": "_Test Address Line 1",
+ "address_title": "_Test Cart Lead Address",
+ "address_type": "Office",
+ "city": "_Test City",
+ "country": "United States",
+ "lead": lead.name,
+ "lead_name": "_Test Website Lead",
+ "is_primary_address": 1,
+ "phone": "+91 0000000000"
+ }).insert(ignore_permissions=True)
+
+ frappe.get_doc({
+ "doctype": "Address",
+ "address_line1": "_Test Address Line 1",
+ "address_title": "_Test Cart Lead Address",
+ "address_type": "Home",
+ "city": "_Test City",
+ "country": "India",
+ "lead": lead.name,
+ "lead_name": "_Test Website Lead",
+ "phone": "+91 0000000000"
+ }).insert(ignore_permissions=True)
+
+
+test_dependencies = ["Sales Taxes and Charges Master", "Price List", "Item Price", "Shipping Rule", "Currency Exchange",
+ "Customer Group", "Lead", "Customer", "Contact", "Address", "Item"]
diff --git a/erpnext/shopping_cart/utils.py b/erpnext/shopping_cart/utils.py
new file mode 100644
index 0000000..ee011a4
--- /dev/null
+++ b/erpnext/shopping_cart/utils.py
@@ -0,0 +1,47 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+import frappe.defaults
+from frappe.utils import cint
+
+def show_cart_count():
+ if (frappe.db.get_default("shopping_cart_enabled") and
+ frappe.db.get_value("User", frappe.session.user, "user_type") == "Website User"):
+ return True
+
+ return False
+
+def set_cart_count(login_manager):
+ if show_cart_count():
+ from .shopping_cart.cart import set_cart_count
+ set_cart_count()
+
+def clear_cart_count(login_manager):
+ if show_cart_count():
+ frappe.local.cookie_manager.delete_cookie("cart_count")
+
+def update_website_context(context):
+ post_login = []
+ cart_enabled = cint(frappe.db.get_default("shopping_cart_enabled"))
+ context["shopping_cart_enabled"] = cart_enabled
+
+ if cart_enabled:
+ post_login += [
+ {"label": "Cart", "url": "cart", "icon": "icon-shopping-cart", "class": "cart-count"},
+ {"class": "divider"}
+ ]
+
+ post_login += [
+ {"label": "User", "url": "user", "icon": "icon-user"},
+ {"label": "Addresses", "url": "addresses", "icon": "icon-map-marker"},
+ {"label": "My Orders", "url": "orders", "icon": "icon-list"},
+ {"label": "My Tickets", "url": "tickets", "icon": "icon-tags"},
+ {"label": "Invoices", "url": "invoices", "icon": "icon-file-text"},
+ {"label": "Shipments", "url": "shipments", "icon": "icon-truck"},
+ {"class": "divider"}
+ ]
+
+ context["post_login"] = post_login + context.get("post_login", [])
diff --git a/erpnext/templates/includes/cart.js b/erpnext/templates/includes/cart.js
new file mode 100644
index 0000000..90cfea5
--- /dev/null
+++ b/erpnext/templates/includes/cart.js
@@ -0,0 +1,297 @@
+// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+// License: GNU General Public License v3. See license.txt
+
+// js inside blog page
+
+// shopping cart
+frappe.provide("shopping_cart");
+
+$.extend(shopping_cart, {
+ show_error: function(title, text) {
+ $("#cart-container").html('<div class="well"><h4>' + title + '</h4> ' + text + '</div>');
+ },
+
+ bind_events: function() {
+ // bind update button
+ $(document).on("click", ".item-update-cart button", function() {
+ var item_code = $(this).attr("data-item-code");
+ shopping_cart.update_cart({
+ item_code: item_code,
+ qty: $('input[data-item-code="'+item_code+'"]').val(),
+ with_doc: 1,
+ btn: this,
+ callback: function(r) {
+ if(!r.exc) {
+ shopping_cart.render(r.message);
+ var $button = $('button[data-item-code="'+item_code+'"]').addClass("btn-success");
+ setTimeout(function() { $button.removeClass("btn-success"); }, 1000);
+ }
+ },
+ });
+ });
+
+ $("#cart-add-shipping-address").on("click", function() {
+ window.location.href = "address?address_fieldname=shipping_address_name";
+ });
+
+ $("#cart-add-billing-address").on("click", function() {
+ window.location.href = "address?address_fieldname=customer_address";
+ });
+
+ $(".btn-place-order").on("click", function() {
+ shopping_cart.place_order(this);
+ });
+ },
+
+ render: function(out) {
+ var doc = out.doc;
+ var addresses = out.addresses;
+
+ var $cart_items = $("#cart-items").empty();
+ var $cart_taxes = $("#cart-taxes").empty();
+ var $cart_totals = $("#cart-totals").empty();
+ var $cart_billing_address = $("#cart-billing-address").empty();
+ var $cart_shipping_address = $("#cart-shipping-address").empty();
+
+ var no_items = $.map(doc.quotation_details || [],
+ function(d) { return d.item_code || null;}).length===0;
+ if(no_items) {
+ shopping_cart.show_error("Empty :-(", frappe._("Go ahead and add something to your cart."));
+ $("#cart-addresses").toggle(false);
+ return;
+ }
+
+ var shipping_rule_added = false;
+ var taxes_exist = false;
+ var shipping_rule_labels = $.map(out.shipping_rules || [], function(rule) { return rule[1]; });
+
+ $.each(doc.quotation_details || [], function(i, d) {
+ shopping_cart.render_item_row($cart_items, d);
+ });
+
+ $.each(doc.other_charges || [], function(i, d) {
+ if(out.shipping_rules && out.shipping_rules.length &&
+ shipping_rule_labels.indexOf(d.description)!==-1) {
+ shipping_rule_added = true;
+ shopping_cart.render_tax_row($cart_taxes, d, out.shipping_rules);
+ } else {
+ shopping_cart.render_tax_row($cart_taxes, d);
+ }
+
+ taxes_exist = true;
+ });
+
+ if(out.shipping_rules && out.shipping_rules.length && !shipping_rule_added) {
+ shopping_cart.render_tax_row($cart_taxes, {description: "", formatted_tax_amount: ""},
+ out.shipping_rules);
+ taxes_exist = true;
+ }
+
+ if(taxes_exist)
+ $('<hr>').appendTo($cart_taxes);
+
+ shopping_cart.render_tax_row($cart_totals, {
+ description: "<strong>Total</strong>",
+ formatted_tax_amount: "<strong>" + doc.formatted_grand_total_export + "</strong>"
+ });
+
+ if(!(addresses && addresses.length)) {
+ $cart_shipping_address.html('<div class="well">'+frappe._("Hey! Go ahead and add an address")+'</div>');
+ } else {
+ shopping_cart.render_address($cart_shipping_address, addresses, doc.shipping_address_name);
+ shopping_cart.render_address($cart_billing_address, addresses, doc.customer_address);
+ }
+ },
+
+ render_item_row: function($cart_items, doc) {
+ doc.image_html = doc.website_image ?
+ '<div style="height: 120px; overflow: hidden;"><img src="' + doc.website_image + '" /></div>' :
+ '{% include "templates/includes/product_missing_image.html" %}';
+
+ if(doc.description === doc.item_name) doc.description = "";
+
+ $(repl('<div class="row">\
+ <div class="col-md-9 col-sm-9">\
+ <div class="row">\
+ <div class="col-md-3">%(image_html)s</div>\
+ <div class="col-md-9">\
+ <h4><a href="%(page_name)s">%(item_name)s</a></h4>\
+ <p>%(description)s</p>\
+ </div>\
+ </div>\
+ </div>\
+ <div class="col-md-3 col-sm-3 text-right">\
+ <div class="input-group item-update-cart">\
+ <input type="text" placeholder="Qty" value="%(qty)s" \
+ data-item-code="%(item_code)s" class="text-right form-control">\
+ <div class="input-group-btn">\
+ <button class="btn btn-primary" data-item-code="%(item_code)s">\
+ <i class="icon-ok"></i></button>\
+ </div>\
+ </div>\
+ <p style="margin-top: 10px;">at %(formatted_rate)s</p>\
+ <small class="text-muted" style="margin-top: 10px;">= %(formatted_amount)s</small>\
+ </div>\
+ </div><hr>', doc)).appendTo($cart_items);
+ },
+
+ render_tax_row: function($cart_taxes, doc, shipping_rules) {
+ var shipping_selector;
+ if(shipping_rules) {
+ shipping_selector = '<select class="form-control">' + $.map(shipping_rules, function(rule) {
+ return '<option value="' + rule[0] + '">' + rule[1] + '</option>' }).join("\n") +
+ '</select>';
+ }
+
+ var $tax_row = $(repl('<div class="row">\
+ <div class="col-md-9 col-sm-9">\
+ <div class="row">\
+ <div class="col-md-9 col-md-offset-3">' +
+ (shipping_selector || '<p>%(description)s</p>') +
+ '</div>\
+ </div>\
+ </div>\
+ <div class="col-md-3 col-sm-3 text-right">\
+ <p' + (shipping_selector ? ' style="margin-top: 5px;"' : "") + '>%(formatted_tax_amount)s</p>\
+ </div>\
+ </div>', doc)).appendTo($cart_taxes);
+
+ if(shipping_selector) {
+ $tax_row.find('select option').each(function(i, opt) {
+ if($(opt).html() == doc.description) {
+ $(opt).attr("selected", "selected");
+ }
+ });
+ $tax_row.find('select').on("change", function() {
+ shopping_cart.apply_shipping_rule($(this).val(), this);
+ });
+ }
+ },
+
+ apply_shipping_rule: function(rule, btn) {
+ return frappe.call({
+ btn: btn,
+ type: "POST",
+ method: "erpnext.shopping_cart.cart.apply_shipping_rule",
+ args: { shipping_rule: rule },
+ callback: function(r) {
+ if(!r.exc) {
+ shopping_cart.render(r.message);
+ }
+ }
+ });
+ },
+
+ render_address: function($address_wrapper, addresses, address_name) {
+ $.each(addresses, function(i, address) {
+ $(repl('<div class="panel panel-default"> \
+ <div class="panel-heading"> \
+ <div class="row"> \
+ <div class="col-md-10 address-title" \
+ data-address-name="%(name)s"><strong>%(name)s</strong></div> \
+ <div class="col-md-2"><input type="checkbox" \
+ data-address-name="%(name)s"></div> \
+ </div> \
+ </div> \
+ <div class="panel-collapse collapse" data-address-name="%(name)s"> \
+ <div class="panel-body">%(display)s</div> \
+ </div> \
+ </div>', address))
+ .css({"margin": "10px auto"})
+ .appendTo($address_wrapper);
+ });
+
+ $address_wrapper.find(".panel-heading")
+ .find(".address-title")
+ .css({"cursor": "pointer"})
+ .on("click", function() {
+ $address_wrapper.find('.panel-collapse[data-address-name="'
+ +$(this).attr("data-address-name")+'"]').collapse("toggle");
+ });
+
+ $address_wrapper.find('input[type="checkbox"]').on("click", function() {
+ if($(this).prop("checked")) {
+ var me = this;
+ $address_wrapper.find('input[type="checkbox"]').each(function(i, chk) {
+ if($(chk).attr("data-address-name")!=$(me).attr("data-address-name")) {
+ $(chk).prop("checked", false);
+ }
+ });
+
+ return frappe.call({
+ type: "POST",
+ method: "erpnext.shopping_cart.cart.update_cart_address",
+ args: {
+ address_fieldname: $address_wrapper.attr("data-fieldname"),
+ address_name: $(this).attr("data-address-name")
+ },
+ callback: function(r) {
+ if(!r.exc) {
+ shopping_cart.render(r.message);
+ }
+ }
+ });
+ } else {
+ return false;
+ }
+ });
+
+ $address_wrapper.find('input[type="checkbox"][data-address-name="'+ address_name +'"]')
+ .prop("checked", true);
+
+ $address_wrapper.find(".panel-collapse").collapse({
+ parent: $address_wrapper,
+ toggle: false
+ });
+
+ $address_wrapper.find('.panel-collapse[data-address-name="'+ address_name +'"]')
+ .collapse("show");
+ },
+
+ place_order: function(btn) {
+ return frappe.call({
+ type: "POST",
+ method: "erpnext.shopping_cart.cart.place_order",
+ btn: btn,
+ 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 || frappe._("Something went wrong!"))
+ .toggle(true);
+ } else {
+ window.location.href = "order?name=" + encodeURIComponent(r.message);
+ }
+ }
+ });
+ }
+});
+
+$(document).ready(function() {
+ shopping_cart.bind_events();
+ return frappe.call({
+ type: "POST",
+ method: "erpnext.shopping_cart.cart.get_cart_quotation",
+ callback: function(r) {
+ $("#cart-container").removeClass("hide");
+ $(".progress").remove();
+ if(r.exc) {
+ if(r.exc.indexOf("WebsitePriceListMissingError")!==-1) {
+ shopping_cart.show_error("Oops!", frappe._("Price List not configured."));
+ } else if(r["403"]) {
+ shopping_cart.show_error("Hey!", frappe._("You need to be logged in to view your cart."));
+ } else {
+ shopping_cart.show_error("Oops!", frappe._("Something went wrong."));
+ }
+ } else {
+ shopping_cart.set_cart_count();
+ shopping_cart.render(r.message);
+ }
+ }
+ });
+});
diff --git a/erpnext/templates/includes/product_page.js b/erpnext/templates/includes/product_page.js
index 42d4ae7..03520fc 100644
--- a/erpnext/templates/includes/product_page.js
+++ b/erpnext/templates/includes/product_page.js
@@ -7,7 +7,7 @@
frappe.call({
type: "POST",
- method: "shopping_cart.shopping_cart.product.get_product_info",
+ method: "erpnext.shopping_cart.product.get_product_info",
args: {
item_code: "{{ name }}"
},
diff --git a/erpnext/templates/includes/sale.html b/erpnext/templates/includes/sale.html
new file mode 100644
index 0000000..e823248
--- /dev/null
+++ b/erpnext/templates/includes/sale.html
@@ -0,0 +1,85 @@
+<div class="sale-content">
+ <ul class="breadcrumb">
+ <li><a href="index">Home</a></li>
+ <li><a href="{{ parent_link }}">{{ parent_title }}</a></li>
+ <li class="active"><i class="icon-file icon-fixed-width"></i> {{ doc.name }}</li>
+ </ul>
+ <h3><i class="icon-file icon-fixed-width"></i> {{ doc.name }}</h3>
+ {% if doc.name == _("Not Allowed") -%}
+ <script>ask_to_login();</script>
+ {% else %}
+ <hr>
+ <div>
+ <div class="row">
+ <div class="col-xs-6">
+ {% if doc.status -%}{{ doc.status }}{%- endif %}
+ </div>
+ <div class="col-xs-6">
+ <span class="pull-right">{{ frappe.utils.formatdate(doc.posting_date or doc.transaction_date) }}</span>
+ </div>
+ </div>
+ <br>
+ <div class="row">
+ <div class="col-md-12">
+ <table class="table table-bordered">
+ <tbody>
+ <tr>
+ <th>Sr</th>
+ <th>Item Name</th>
+ <th>Description</th>
+ <th>Qty</th>
+ <th>UoM</th>
+ <th>Basic Rate</th>
+ <th>Amount</th>
+ </tr>
+ {%- for row in doc.get({"doctype": doc.doctype + " Item"}) %}
+ <tr>
+ <td style="width: 3%;">{{ row.idx }}</td>
+ <td style="width: 20%;">{{ row.item_name }}</td>
+ <td style="width: 37%;">{{ row.description }}</td>
+ <td style="width: 5%; text-align: right;">{{ row.qty }}</td>
+ <td style="width: 5%;">{{ row.stock_uom }}</td>
+ <td style="width: 15%; text-align: right;">{{ frappe.utils.fmt_money(row.rate, currency=doc.currency) }}</td>
+ <td style="width: 15%; text-align: right;">{{ frappe.utils.fmt_money(row.amount, currency=doc.currency) }}</td>
+ </tr>
+ {% endfor -%}
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-6"></div>
+ <div class="col-md-6">
+ <table cellspacing=0 width=100%>
+ <tbody>
+ <tr>
+ <td>Net Total</td>
+ <td width=40% style="text-align: right;">{{
+ frappe.utils.fmt_money(doc.net_total/doc.conversion_rate, currency=doc.currency)
+ }}</td>
+ </tr>
+ {%- for charge in doc.get({"doctype":"Sales Taxes and Charges"}) -%}
+ {%- if not charge.included_in_print_rate -%}
+ <tr>
+ <td>{{ charge.description }}</td>
+ <td style="text-align: right;">{{ frappe.utils.fmt_money(charge.tax_amount / doc.conversion_rate, currency=doc.currency) }}</td>
+ </tr>
+ {%- endif -%}
+ {%- endfor -%}
+ <tr>
+ <td>Grand Total</td>
+ <td style="text-align: right;">{{ frappe.utils.fmt_money(doc.grand_total_export, currency=doc.currency) }}</td>
+ </tr>
+ <tr style='font-weight: bold'>
+ <td>Rounded Total</td>
+ <td style="text-align: right;">{{ frappe.utils.fmt_money(doc.rounded_total_export, currency=doc.currency) }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ {%- endif %}
+</div>
+
+<!-- no-sidebar -->
diff --git a/erpnext/templates/includes/sales_transactions.html b/erpnext/templates/includes/sales_transactions.html
new file mode 100644
index 0000000..e8717af
--- /dev/null
+++ b/erpnext/templates/includes/sales_transactions.html
@@ -0,0 +1,30 @@
+<script>
+$(document).ready(function() {
+ global_number_format = "{{ global_number_format }}";
+ currency = "{{ currency }}";
+ frappe.currency_symbols = {{ currency_symbols }};
+});
+</script>
+
+{% include "templates/includes/transactions.html" %}
+
+<script>
+ var render = function(doc) {
+ doc.grand_total_export = format_currency(doc.grand_total_export, doc.currency);
+ if(!doc.status) doc.status = "";
+
+ $(repl('<a href="{{ page }}?name=%(name)s" class="list-group-item">\
+ <div class="row">\
+ <div class="col-md-6">\
+ <div class="row col-md-12">%(name)s</div>\
+ <div class="row col-md-12 text-muted">%(items)s</div>\
+ <div class="row col-md-12">%(status)s</div>\
+ </div>\
+ <div class="col-md-3 text-right">%(grand_total_export)s</div>\
+ <div class="col-md-3 text-right text-muted">%(creation)s</div>\
+ </div>\
+ </a>', doc)).appendTo($list);
+ };
+</script>
+
+<!-- no-sidebar -->
diff --git a/erpnext/templates/includes/transactions.html b/erpnext/templates/includes/transactions.html
new file mode 100644
index 0000000..b0eda19
--- /dev/null
+++ b/erpnext/templates/includes/transactions.html
@@ -0,0 +1,53 @@
+<div class="transactions-content">
+ <ul class="breadcrumb">
+ <li><a href="index">Home</a></li>
+ <li class="active"><i class="{{ icon }} icon-fixed-width"></i> {{ title }}</li>
+ </ul>
+ <p id="msgprint-alert" class="alert alert-danger"
+ style="display: none;"> </p>
+ <div class="list-group transaction-list">
+ <div class="progress progress-striped active">
+ <div class="progress-bar progress-bar-info" style="width: 100%;"></div>
+ </div>
+ </div>
+ <div class="text-center">
+ <button class="btn btn-default btn-show-more hide">More</button>
+ </div>
+</div>
+<script>
+var get_transactions = function(btn) {
+ frappe.call({
+ method: "{{ method }}",
+ args: { start: start },
+ btn: btn,
+ callback: function(r) {
+ $list.find(".progress").remove();
+ $show_more.toggleClass("hide", !(r.message && r.message.length===20));
+ if(!(r.message && r.message.length)) {
+ if(!$list.html().trim()) {
+ $list.html("<div class='text-muted'>\
+ {{ empty_list_message }}</div>");
+ }
+ return;
+ }
+
+ start += r.message.length;
+
+ $.each(r.message, function(i, doc) {
+ render(doc);
+ });
+ }
+ })
+};
+
+$(document).ready(function() {
+ window.start = 0;
+ window.$list = $(".transaction-list");
+ window.$list.find(".list-group-item").remove();
+ window.$show_more = $(".btn-show-more").on("click", function() { get_transactions(this); })
+
+ get_transactions();
+});
+</script>
+
+<!-- no-sidebar -->
diff --git a/erpnext/templates/pages/address.html b/erpnext/templates/pages/address.html
new file mode 100644
index 0000000..95ddb76
--- /dev/null
+++ b/erpnext/templates/pages/address.html
@@ -0,0 +1,112 @@
+{% block title %} {{ title }} {% endblock %}
+
+{% block header %}<h2>{{ title }}</h2>{% endblock %}
+
+{% block content %}
+{% macro render_fields(docfields) -%}
+{% for df in docfields -%}
+ {% if df.fieldtype == "Data" -%}
+ <fieldset>
+ <label>{{ df.label }}</label>
+ <input class="form-control" type="text" placeholder="Type {{ df.label }}"
+ data-fieldname="{{ df.fieldname }}" data-fieldtype="{{ df.fieldtype }}"
+ {% if doc and doc.get(df.fieldname) -%} value="{{ doc[df.fieldname] }}" {%- endif %}>
+ </fieldset>
+ {% elif df.fieldtype == "Check" -%}
+ <fieldset class="checkbox">
+ <label><input type="checkbox" data-fieldname="{{ df.fieldname }}"
+ data-fieldtype="{{ df.fieldtype }}"
+ {% if doc and frappe.utils.cint(doc.get(df.fieldname)) -%} checked="checked" {%- endif %}>
+ {{ df.label }}</label>
+ </fieldset>
+ {% elif df.fieldtype in ("Select", "Link") -%}
+ <fieldset>
+ {% set select_options = frappe.get_list(df.options)|map(attribute="name")
+ if df.fieldtype == "Link" else df.options.split("\n") %}
+ <label>{{ df.label }}</label>
+ <select class="form-control" data-fieldname="{{ df.fieldname }}" data-fieldtype="{{ df.fieldtype }}">
+ {% for value in select_options -%}
+ {% if doc and doc.get(df.fieldname) == value -%}
+ <option selected="selected">{{ value }}</option>
+ {% else -%}
+ <option>{{ value }}</option>
+ {%- endif %}
+ {%- endfor %}
+ </select>
+ </fieldset>
+ {%- endif %}
+{%- endfor %}
+{%- endmacro %}
+
+<div class="container content">
+ <ul class="breadcrumb">
+ <li><a href="index">Home</a></li>
+ <li><a href="addresses">My Addresses</a></li>
+ <li class="active"><i class="icon-map-marker icon-fixed-width"></i> {{ title }}</li>
+ </ul>
+ <h3><i class="icon-map-marker icon-fixed-width"></i> {{ title }}</h3>
+ <button type="button" class="btn btn-primary pull-right" id="address-save"><i class="icon-ok"></i>
+ {{ doc and "Save" or "Insert" }}</button>
+ <div class="clearfix"></div>
+ <hr>
+ <div id="address-error" class="alert alert-danger" style="display:none"></div>
+ <form autocomplete="on">
+ <div class="row">
+ <section class="col-md-6">
+ {{ render_fields(meta.left_fields) }}
+ </section>
+ <section class="col-md-6">
+ {{ render_fields(meta.right_fields) }}
+ </section>
+ </section>
+ </form>
+</div>
+
+<script>
+;(function() {
+ console.log("yoyo");
+ frappe.ready(function() {
+ bind_save();
+ });
+
+ var bind_save = function() {
+ $("#address-save").on("click", function() {
+ console.log("clicked!");
+
+ var fields = {
+ name: "{{ docname or '' }}"
+ };
+
+ $("form").find("[data-fieldname]").each(function(i, input) {
+ var $input = $(input);
+ var fieldname = $(input).attr("data-fieldname");
+ var fieldtype = $(input).attr("data-fieldtype");
+
+ if(fieldtype == "Check") {
+ fields[fieldname] = $input.is(":checked") ? 1 : 0;
+ } else {
+ fields[fieldname] = $input.val();
+ }
+ });
+
+ frappe.call({
+ btn: $(this),
+ type: "POST",
+ method: "shopping_cart.templates.pages.address.save_address",
+ args: { fields: fields, address_fieldname: get_url_arg("address_fieldname") },
+ error_msg: "#address-error",
+ callback: function(r) {
+ if(get_url_arg("address_fieldname")) {
+ window.location.href = "cart";
+ } else {
+ window.location.href = "address?name=" + encodeURIComponent(r.message);
+ }
+ }
+ });
+ });
+ };
+})();
+</script>
+
+<!-- no-sidebar -->
+{% endblock %}
diff --git a/erpnext/templates/pages/address.py b/erpnext/templates/pages/address.py
new file mode 100644
index 0000000..46dde92
--- /dev/null
+++ b/erpnext/templates/pages/address.py
@@ -0,0 +1,62 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import json
+
+import frappe
+from erpnext.shopping_cart.cart import get_lead_or_customer, update_cart_address
+from frappe.desk.form.meta import get_meta
+
+no_cache = 1
+no_sitemap = 1
+
+def get_context(context):
+ def _get_fields(fieldnames):
+ return [frappe._dict(zip(["label", "fieldname", "fieldtype", "options"],
+ [df.label, df.fieldname, df.fieldtype, df.options]))
+ for df in get_meta("Address").get("fields", {"fieldname": ["in", fieldnames]})]
+
+ docname = doc = None
+ title = "New Address"
+ if frappe.form_dict.name:
+ doc = frappe.get_doc("Address", frappe.form_dict.name)
+ docname = doc.name
+ title = doc.name
+
+ return {
+ "doc": doc,
+ "meta": frappe._dict({
+ "left_fields": _get_fields(["address_title", "address_type", "address_line1", "address_line2",
+ "city", "state", "pincode", "country"]),
+ "right_fields": _get_fields(["email_id", "phone", "fax", "is_primary_address",
+ "is_shipping_address"])
+ }),
+ "docname": docname,
+ "title": title
+ }
+
+@frappe.whitelist()
+def save_address(fields, address_fieldname=None):
+ party = get_lead_or_customer()
+ fields = json.loads(fields)
+
+ if fields.get("name"):
+ doc = frappe.get_doc("Address", fields.get("name"))
+ else:
+ doc = frappe.get_doc({"doctype": "Address", "__islocal": 1})
+
+ doc.update(fields)
+
+ party_fieldname = party.doctype.lower()
+ doc.update({
+ party_fieldname: party.name,
+ (party_fieldname + "_name"): party.get(party_fieldname + "_name")
+ })
+ doc.ignore_permissions = True
+ doc.save()
+
+ if address_fieldname:
+ update_cart_address(address_fieldname, doc.name)
+
+ return doc.name
diff --git a/erpnext/templates/pages/addresses.html b/erpnext/templates/pages/addresses.html
new file mode 100644
index 0000000..58a9798
--- /dev/null
+++ b/erpnext/templates/pages/addresses.html
@@ -0,0 +1,52 @@
+{% block title %} {{ "My Addresses" }} {% endblock %}
+
+{% block header %}<h2>My Addresses</h2>{% endblock %}
+
+{% block breadcrumbs %}{% include "templates/includes/breadcrumbs.html" %}{% endblock %}
+
+{% block content %}
+<div class="addresses-content">
+ <p><a class="btn btn-default" href="address"><i class="icon-plus"> New Address</i></a></p>
+ <hr>
+ <div id="address-list">
+ <div class="progress progress-striped active">
+ <div class="progress-bar progress-bar-info" style="width: 100%;"></div>
+ </div>
+ </div>
+</div>
+
+<script>
+;(function() {
+ var fetch_addresses = function() {
+ frappe.call({
+ method: "shopping_cart.templates.pages.addresses.get_addresses",
+ callback: function(r) {
+ $("#address-list .progress").remove();
+ var $list = $("#address-list");
+
+ if(!(r.message && r.message.length)) {
+ $list.html("<div class='alert'>No Addresses Found</div>");
+ return;
+ }
+
+ $.each(r.message, function(i, address) {
+ address.url_name = encodeURIComponent(address.name);
+ $(repl('<div> \
+ <p><a href="address?name=%(url_name)s">%(name)s</a></p> \
+ <p>%(display)s</p> \
+ <hr> \
+ </div>', address)).appendTo($list);
+ });
+ }
+ });
+ };
+
+ $(document).ready(function() {
+ fetch_addresses();
+ });
+})();
+</script>
+
+<!-- no-sidebar -->
+{% endblock %}
+
diff --git a/erpnext/templates/pages/addresses.py b/erpnext/templates/pages/addresses.py
new file mode 100644
index 0000000..531d3a3
--- /dev/null
+++ b/erpnext/templates/pages/addresses.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from erpnext.shopping_cart.cart import get_address_docs
+
+no_cache = 1
+no_sitemap = 1
+
+@frappe.whitelist()
+def get_addresses():
+ return get_address_docs()
diff --git a/erpnext/templates/pages/cart.html b/erpnext/templates/pages/cart.html
new file mode 100644
index 0000000..a8dc03e
--- /dev/null
+++ b/erpnext/templates/pages/cart.html
@@ -0,0 +1,57 @@
+{% block title %} {{ "Shopping Cart" }} {% endblock %}
+
+{% block header %}<h2><i class="icon-shopping-cart"></i> Shopping Cart</h2>{% endblock %}
+
+{% block script %}{% include "templates/includes/cart.js" %}{% endblock %}
+
+{% block content %}
+<div class="cart-content">
+ <div class="progress progress-striped active">
+ <div class="progress-bar progress-bar-info" style="width: 100%;"></div>
+ </div>
+ <div id="cart-container" class="hide">
+ <p class="pull-right"><button class="btn btn-success btn-place-order" type="button">Place Order</button></p>
+ <div class="clearfix"></div>
+ <div id="cart-error" class="alert alert-danger" style="display: none;"></div>
+ <hr>
+ <div class="row">
+ <div class="col-md-9 col-sm-9">
+ <div class="row">
+ <div class="col-md-9 col-md-offset-3"><h4>Item Details</h4></div>
+ </div>
+ </div>
+ <div class="col-md-3 col-sm-3 text-right"><h4>Qty, Amount</h4></div>
+ </div><hr>
+ <div id="cart-items">
+ </div>
+ <div id="cart-taxes">
+ </div>
+ <div id="cart-totals">
+ </div>
+ <hr>
+ <div id="cart-addresses">
+ <div class="row">
+ <div class="col-md-6">
+ <h4>Shipping Address</h4>
+ <div id="cart-shipping-address" class="panel-group"
+ data-fieldname="shipping_address_name"></div>
+ <button class="btn btn-default" type="button" id="cart-add-shipping-address">
+ <span class="icon icon-plus"></span> New Shipping Address</button>
+ </div>
+ <div class="col-md-6">
+ <h4>Billing Address</h4>
+ <div id="cart-billing-address" class="panel-group"
+ data-fieldname="customer_address"></div>
+ <button class="btn btn-default" type="button" id="cart-add-billing-address">
+ <span class="icon icon-plus"></span> New Billing Address</button>
+ </div>
+ </div>
+ <hr>
+ </div>
+ <p class="pull-right"><button class="btn btn-success btn-place-order" type="button">Place Order</button></p>
+ </div>
+</div>
+
+<!-- no-sidebar -->
+{% endblock %}
+
diff --git a/erpnext/templates/pages/cart.py b/erpnext/templates/pages/cart.py
new file mode 100644
index 0000000..9c9f096
--- /dev/null
+++ b/erpnext/templates/pages/cart.py
@@ -0,0 +1,7 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+no_cache = 1
+no_sitemap = 1
\ No newline at end of file
diff --git a/erpnext/templates/pages/invoice.html b/erpnext/templates/pages/invoice.html
new file mode 100644
index 0000000..13b0e72
--- /dev/null
+++ b/erpnext/templates/pages/invoice.html
@@ -0,0 +1,6 @@
+{% block title %} {{ doc.name }} {% endblock %}
+
+{% block header %}<h2>{{ doc.name }}</h2>{% endblock %}
+
+{% block content%}{% include "templates/includes/sale.html" %}{% endblock %}
+
diff --git a/erpnext/templates/pages/invoice.py b/erpnext/templates/pages/invoice.py
new file mode 100644
index 0000000..5b55007
--- /dev/null
+++ b/erpnext/templates/pages/invoice.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.utils import flt, fmt_money
+from shopping_cart.templates.utils import get_transaction_context
+
+no_cache = 1
+no_sitemap = 1
+
+def get_context(context):
+ invoice_context = frappe._dict({
+ "parent_link": "invoices",
+ "parent_title": "Invoices"
+ })
+ invoice_context.update(get_transaction_context("Sales Invoice", frappe.form_dict.name))
+ modify_status(invoice_context.doc)
+ return invoice_context
+
+def modify_status(doc):
+ doc.status = ""
+ if flt(doc.outstanding_amount):
+ doc.status = '<span class="label %s"><i class="icon-fixed-width %s"></i> %s</span>' % \
+ ("label-warning", "icon-exclamation-sign",
+ _("To Pay") + " = " + fmt_money(doc.outstanding_amount, currency=doc.currency))
+ else:
+ doc.status = '<span class="label %s"><i class="icon-fixed-width %s"></i> %s</span>' % \
+ ("label-success", "icon-ok", _("Paid"))
+
\ No newline at end of file
diff --git a/erpnext/templates/pages/invoices.html b/erpnext/templates/pages/invoices.html
new file mode 100644
index 0000000..9f493ca
--- /dev/null
+++ b/erpnext/templates/pages/invoices.html
@@ -0,0 +1,6 @@
+{% block title %} {{ title }} {% endblock %}
+
+{% block header %}<h2>{{ title }}</h2>{% endblock %}
+
+{% block content %}{% include "templates/includes/sales_transactions.html" %}{% endblock %}
+
diff --git a/erpnext/templates/pages/invoices.py b/erpnext/templates/pages/invoices.py
new file mode 100644
index 0000000..98c5140
--- /dev/null
+++ b/erpnext/templates/pages/invoices.py
@@ -0,0 +1,29 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from shopping_cart.templates.utils import get_currency_context
+
+no_cache = 1
+no_sitemap = 1
+
+def get_context(context):
+ invoices_context = get_currency_context()
+ invoices_context.update({
+ "title": "Invoices",
+ "method": "shopping_cart.templates.pages.invoices.get_invoices",
+ "icon": "icon-file-text",
+ "empty_list_message": "No Invoices Found",
+ "page": "invoice"
+ })
+ return invoices_context
+
+@frappe.whitelist()
+def get_invoices(start=0):
+ from shopping_cart.templates.utils import get_transaction_list
+ from shopping_cart.templates.pages.invoice import modify_status
+ invoices = get_transaction_list("Sales Invoice", start, ["outstanding_amount"])
+ for d in invoices:
+ modify_status(d)
+ return invoices
\ No newline at end of file
diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html
new file mode 100644
index 0000000..13b0e72
--- /dev/null
+++ b/erpnext/templates/pages/order.html
@@ -0,0 +1,6 @@
+{% block title %} {{ doc.name }} {% endblock %}
+
+{% block header %}<h2>{{ doc.name }}</h2>{% endblock %}
+
+{% block content%}{% include "templates/includes/sale.html" %}{% endblock %}
+
diff --git a/erpnext/templates/pages/order.py b/erpnext/templates/pages/order.py
new file mode 100644
index 0000000..832a60e
--- /dev/null
+++ b/erpnext/templates/pages/order.py
@@ -0,0 +1,34 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from shopping_cart.templates.utils import get_transaction_context
+
+no_cache = 1
+no_sitemap = 1
+
+def get_context(context):
+ order_context = frappe._dict({
+ "parent_link": "orders",
+ "parent_title": "My Orders"
+ })
+
+ order_context.update(get_transaction_context("Sales Order", frappe.form_dict.name))
+ modify_status(order_context.doc)
+ return order_context
+
+def modify_status(doc):
+ doc.status = []
+ if 0 < doc.per_billed < 100:
+ doc.status.append(("label-warning", "icon-ok", _("Partially Billed")))
+ elif doc.per_billed == 100:
+ doc.status.append(("label-success", "icon-ok", _("Billed")))
+
+ if 0 < doc.per_delivered < 100:
+ doc.status.append(("label-warning", "icon-truck", _("Partially Delivered")))
+ elif doc.per_delivered == 100:
+ doc.status.append(("label-success", "icon-truck", _("Delivered")))
+ doc.status = " " + " ".join(('<span class="label %s"><i class="icon-fixed-width %s"></i> %s</span>' % s
+ for s in doc.status))
diff --git a/erpnext/templates/pages/orders.html b/erpnext/templates/pages/orders.html
new file mode 100644
index 0000000..d58cbd8
--- /dev/null
+++ b/erpnext/templates/pages/orders.html
@@ -0,0 +1,5 @@
+{% block title %} {{ title }} {% endblock %}
+
+{% block header %}<h2>{{ title }}</h2>{% endblock %}
+
+{% block content %}{% include "templates/includes/sales_transactions.html" %}{% endblock %}
diff --git a/erpnext/templates/pages/orders.py b/erpnext/templates/pages/orders.py
new file mode 100644
index 0000000..c443b6a
--- /dev/null
+++ b/erpnext/templates/pages/orders.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from shopping_cart.templates.utils import get_currency_context, get_transaction_list
+from shopping_cart.templates.pages.order import modify_status
+
+no_cache = 1
+no_sitemap = 1
+
+def get_context(context):
+ orders_context = get_currency_context()
+ orders_context.update({
+ "title": "My Orders",
+ "method": "shopping_cart.templates.pages.orders.get_orders",
+ "icon": "icon-list",
+ "empty_list_message": "No Orders Yet",
+ "page": "order",
+ })
+ return orders_context
+
+@frappe.whitelist()
+def get_orders(start=0):
+ orders = get_transaction_list("Sales Order", start, ["per_billed", "per_delivered"])
+ for d in orders:
+ modify_status(d)
+
+ return orders
+
\ No newline at end of file
diff --git a/erpnext/templates/pages/shipment.html b/erpnext/templates/pages/shipment.html
new file mode 100644
index 0000000..13b0e72
--- /dev/null
+++ b/erpnext/templates/pages/shipment.html
@@ -0,0 +1,6 @@
+{% block title %} {{ doc.name }} {% endblock %}
+
+{% block header %}<h2>{{ doc.name }}</h2>{% endblock %}
+
+{% block content%}{% include "templates/includes/sale.html" %}{% endblock %}
+
diff --git a/erpnext/templates/pages/shipment.py b/erpnext/templates/pages/shipment.py
new file mode 100644
index 0000000..ba98e1d
--- /dev/null
+++ b/erpnext/templates/pages/shipment.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from shopping_cart.templates.utils import get_transaction_context
+
+no_cache = 1
+no_sitemap = 1
+
+def get_context(context):
+ shipment_context = frappe._dict({
+ "parent_link": "shipments",
+ "parent_title": "Shipments"
+ })
+ shipment_context.update(get_transaction_context("Delivery Note", frappe.form_dict.name))
+ return shipment_context
diff --git a/erpnext/templates/pages/shipments.html b/erpnext/templates/pages/shipments.html
new file mode 100644
index 0000000..d58cbd8
--- /dev/null
+++ b/erpnext/templates/pages/shipments.html
@@ -0,0 +1,5 @@
+{% block title %} {{ title }} {% endblock %}
+
+{% block header %}<h2>{{ title }}</h2>{% endblock %}
+
+{% block content %}{% include "templates/includes/sales_transactions.html" %}{% endblock %}
diff --git a/erpnext/templates/pages/shipments.py b/erpnext/templates/pages/shipments.py
new file mode 100644
index 0000000..fe28c7e
--- /dev/null
+++ b/erpnext/templates/pages/shipments.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from shopping_cart.templates.utils import get_currency_context
+
+no_cache = 1
+no_sitemap = 1
+
+def get_context(context):
+ shipments_context = get_currency_context()
+ shipments_context.update({
+ "title": "Shipments",
+ "method": "shopping_cart.templates.pages.shipments.get_shipments",
+ "icon": "icon-truck",
+ "empty_list_message": "No Shipments Found",
+ "page": "shipment"
+ })
+ return shipments_context
+
+@frappe.whitelist()
+def get_shipments(start=0):
+ from shopping_cart.templates.utils import get_transaction_list
+ return get_transaction_list("Delivery Note", start)
diff --git a/erpnext/templates/pages/ticket.html b/erpnext/templates/pages/ticket.html
new file mode 100644
index 0000000..39c69df
--- /dev/null
+++ b/erpnext/templates/pages/ticket.html
@@ -0,0 +1,116 @@
+{% block title %} {{ title }} {% endblock %}
+
+{% block header %}<h2><i class="icon-ticket icon-fixed-width"></i> {{ title }}</h2>{% endblock %}
+
+{% block content %}
+{% set status_label = {
+ "Open": "label-success",
+ "To Reply": "label-danger",
+ "Closed": "label-default"
+} %}
+
+<div class="ticket-content">
+ <ul class="breadcrumb">
+ <li><a href="index">Home</a></li>
+ <li><a href="tickets">My Tickets</a></li>
+ <li class="active"><i class="icon-ticket icon-fixed-width"></i> {{ doc.name or "" }}</li>
+ </ul>
+ {% if not doc -%}
+ <script>ask_to_login();</script>
+ {% else %}
+ <hr>
+ {%- if doc.status -%}
+ {% if doc.status == "Waiting for Customer" -%}
+ {% set status = "To Reply" %}
+ {% else %}
+ {% set status = doc.status %}
+ {%- endif -%}
+ <div class="row">
+ <div class="col-md-2" style="margin-bottom: 7px;">
+ <span class="label {{ status_label.get(status) or 'label-default' }}">{{ status }}</span>
+ </div>
+ <div class="col-md-8">
+ <div class="row col-md-12">{{ doc.subject }}</div>
+ </div>
+ <div class="col-md-2">
+ <span class="text-muted pull-right">{{ frappe.utils.formatdate(doc.creation) }}</span>
+ </div>
+ </div>
+ <div class="row">
+ <h4 class="col-xs-6">Messages</h4>
+ <div class="col-xs-6">
+ <button class="btn btn-sm btn-primary pull-right" id="ticket-reply">
+ <i class="icon-envelope icon-fixed-width"></i> Reply</button>
+ <button class="btn btn-sm btn-success pull-right hide" id="ticket-reply-send">
+ <i class="icon-arrow-right icon-fixed-width"></i> Send</button>
+ </div>
+ </div>
+ <p id="ticket-alert" class="alert alert-danger"
+ style="display: none;"> </p>
+ <div>
+ <table class="table table-bordered table-striped" id="ticket-thread">
+ <tbody>
+ {%- for comm in
+ (doc.get({"doctype":"Communication"})|sort(reverse=True, attribute="creation")) %}
+ <tr>
+ <td>
+ <h5 style="text-transform: none">
+ {{ comm.sender }} on {{ frappe.utils.formatdate(comm.creation) }}</h5>
+ <hr>
+ <p>{{ frappe.utils.is_html(comm.content) and comm.content or
+ comm.content.replace("\n", "<br>")}}</p>
+ </td>
+ </tr>
+ {% endfor -%}
+ </tbody>
+ </table>
+ </div>
+ {%- endif -%}
+ {% endif -%}
+</div>
+
+<script>
+$(document).ready(function() {
+ $("#ticket-reply").on("click", function() {
+ if(!$("#ticket-reply-editor").length) {
+ $('<tr id="ticket-reply-editor"><td>\
+ <h5 style="text-transform: none">Reply</h5>\
+ <hr>\
+ <textarea rows=10 class="form-control" style="resize: vertical;"></textarea>\
+ </td></tr>').prependTo($("#ticket-thread").find("tbody"));
+ $("#ticket-reply").addClass("hide");
+ $("#ticket-reply-send").removeClass("hide");
+ }
+ });
+
+ $("#ticket-reply-send").on("click", function() {
+ var reply = $("#ticket-reply-editor").find("textarea").val().trim();
+ if(!reply) {
+ msgprint("Please write something in reply!");
+ } else {
+ frappe.call({
+ type: "POST",
+ method: "shopping_cart.templates.pages.ticket.add_reply",
+ btn: this,
+ args: { ticket: "{{ doc.name }}", message: reply },
+ callback: function(r) {
+ if(r.exc) {
+ msgprint(r._server_messages
+ ? JSON.parse(r._server_messages).join("<br>")
+ : "Something went wrong!");
+ } else {
+ window.location.reload();
+ }
+ }
+ })
+ }
+ });
+});
+
+var msgprint = function(txt) {
+ if(txt) $("#ticket-alert").html(txt).toggle(true);
+}
+</script>
+
+<!-- no-sidebar -->
+{% endblock %}
diff --git a/erpnext/templates/pages/ticket.py b/erpnext/templates/pages/ticket.py
new file mode 100644
index 0000000..9582146
--- /dev/null
+++ b/erpnext/templates/pages/ticket.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.utils import today
+
+no_cache = 1
+no_sitemap = 1
+
+def get_context(context):
+ doc = frappe.get_doc("Support Ticket", frappe.form_dict.name)
+ if doc.raised_by == frappe.session.user:
+ ticket_context = {
+ "title": doc.name,
+ "doc": doc
+ }
+ else:
+ ticket_context = {"title": "Not Allowed", "doc": {}}
+
+ return ticket_context
+
+@frappe.whitelist()
+def add_reply(ticket, message):
+ if not message:
+ raise frappe.throw(_("Please write something"))
+
+ doc = frappe.get_doc("Support Ticket", ticket)
+ if doc.raised_by != frappe.session.user:
+ raise frappe.throw(_("You are not allowed to reply to this ticket."), frappe.PermissionError)
+
+ comm = frappe.get_doc({
+ "doctype":"Communication",
+ "subject": doc.subject,
+ "content": message,
+ "sender": doc.raised_by,
+ "sent_or_received": "Received"
+ })
+ comm.insert(ignore_permissions=True)
+
diff --git a/erpnext/templates/pages/tickets.html b/erpnext/templates/pages/tickets.html
new file mode 100644
index 0000000..6c03313
--- /dev/null
+++ b/erpnext/templates/pages/tickets.html
@@ -0,0 +1,92 @@
+{% block title %} {{ title }} {% endblock %}
+
+{% block header %}<h2>{{ title }}</h2>{% endblock %}
+
+{% block content %}
+{% include "templates/includes/transactions.html" %}
+
+<script>
+ var status_label = {
+ "Open": "label-success",
+ "Waiting for Customer": "label-danger",
+ "Closed": "label-default"
+ }
+
+ var render = function(doc) {
+ doc.status = doc.status.trim();
+ doc.label_class = status_label[doc.status] || "label-default";
+ if(doc.status==="Waiting for Customer") doc.status = "To Reply";
+
+ $(repl('<a href="{{ page }}?name=%(name)s" class="list-group-item">\
+ <div class="row">\
+ <div class="col-md-2" style="margin-bottom: 7px;"><span class="label %(label_class)s">\
+ %(status)s</span></div>\
+ <div class="col-md-8">\
+ <div class="row col-md-12">%(name)s</div>\
+ <div class="row col-md-12 text-muted">%(subject)s</div>\
+ </div>\
+ <div class="col-md-2 pull-right">\
+ <span class="text-muted">%(creation)s</span>\
+ </div>\
+ </div>\
+ </a>', doc)).appendTo($list);
+ };
+
+ frappe.ready(function() {
+ if(!window.$new_ticket) {
+ window.$new_ticket = $('<div>\
+ <button class="btn btn-primary" style="margin-bottom: 15px;" id="new-ticket">\
+ <i class="icon-tag icon-fixed-width"></i> New Ticket\
+ </button>\
+ <button class="btn btn-success hide" style="margin-bottom: 15px;" id="new-ticket-send">\
+ <i class="icon-arrow-right icon-fixed-width"></i> Send\
+ </button>\
+ </div>').insertBefore(".transaction-list");
+ }
+
+ window.$new_ticket.find("#new-ticket").on("click", function() {
+ $(this).addClass("hide");
+ $(window.$new_ticket).find("#new-ticket-send").removeClass("hide");
+ $('<div class="well" id="ticket-editor">\
+ <div class="form-group"><input class="form-control" type="data"\
+ placeholder="Subject" data-fieldname="subject"></div>\
+ <div class="form-group"><textarea rows=10 class="form-control" \
+ style="resize: vertical;" placeholder="Message" \
+ data-fieldname="message"></textarea></div>\
+ </div>')
+ .insertAfter(window.$new_ticket);
+ });
+
+ window.$new_ticket.find("#new-ticket-send").on("click", function() {
+ var subject = $("#ticket-editor").find('[data-fieldname="subject"]').val().trim();
+ var message = $("#ticket-editor").find('[data-fieldname="message"]').val().trim();
+ if(!(subject && message)) {
+ msgprint("Please write something in subject and message!");
+ } else {
+ frappe.call({
+ type: "POST",
+ method: "shopping_cart.templates.pages.tickets.make_new_ticket",
+ btn: this,
+ args: { subject: subject, message: message },
+ callback: function(r) {
+ if(r.exc) {
+ msgprint(r._server_messages
+ ? JSON.parse(r._server_messages).join("<br>")
+ : "Something went wrong!");
+ } else {
+ window.location.href = "ticket?name=" + encodeURIComponent(r.message);
+ }
+ }
+ })
+ }
+ });
+ });
+
+ var msgprint = function(txt) {
+ if(txt) $("#msgprint-alert").html(txt).toggle(true);
+ }
+</script>
+
+<!-- no-sidebar -->
+{% endblock %}
+
diff --git a/erpnext/templates/pages/tickets.py b/erpnext/templates/pages/tickets.py
new file mode 100644
index 0000000..158173f
--- /dev/null
+++ b/erpnext/templates/pages/tickets.py
@@ -0,0 +1,54 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.utils import cint, formatdate
+
+no_cache = 1
+no_sitemap = 1
+
+def get_context(context):
+ return {
+ "title": "My Tickets",
+ "method": "shopping_cart.templates.pages.tickets.get_tickets",
+ "icon": "icon-ticket",
+ "empty_list_message": "No Tickets Raised",
+ "page": "ticket"
+ }
+
+@frappe.whitelist()
+def get_tickets(start=0):
+ tickets = frappe.db.sql("""select name, subject, status, creation
+ from `tabSupport Ticket` where raised_by=%s
+ order by modified desc
+ limit %s, 20""", (frappe.session.user, cint(start)), as_dict=True)
+ for t in tickets:
+ t.creation = formatdate(t.creation)
+
+ return tickets
+
+@frappe.whitelist()
+def make_new_ticket(subject, message):
+ if not (subject and message):
+ raise frappe.throw(_("Please write something in subject and message!"))
+
+ ticket = frappe.get_doc({
+ "doctype":"Support Ticket",
+ "subject": subject,
+ "raised_by": frappe.session.user,
+ })
+ ticket.insert(ignore_permissions=True)
+
+ comm = frappe.get_doc({
+ "doctype":"Communication",
+ "subject": subject,
+ "content": message,
+ "sender": frappe.session.user,
+ "sent_or_received": "Received",
+ "reference_doctype": "Support Ticket",
+ "reference_name": ticket.name
+ })
+ comm.insert(ignore_permissions=True)
+
+ return ticket.name
diff --git a/erpnext/templates/pages/user.html b/erpnext/templates/pages/user.html
new file mode 100644
index 0000000..b4a1a39
--- /dev/null
+++ b/erpnext/templates/pages/user.html
@@ -0,0 +1,57 @@
+{% block title %} {{ "My Profile" }} {% endblock %}
+
+{% block header %}<h2>My Profile</h2>{% endblock %}
+
+{% block content %}
+<div class="user-content" style="max-width: 500px;">
+ <ul class="breadcrumb">
+ <li><a href="index">Home</a></li>
+ <li class="active"><i class="icon-user icon-fixed-width"></i> My Profile</li>
+ </ul>
+ <div class="alert alert-warning" id="message" style="display: none;"></div>
+ <form>
+ <fieldset>
+ <label>Full Name</label>
+ <input class="form-control" type="text" id="fullname" placeholder="Your Name">
+ </fieldset>
+ <fieldset>
+ <label>Company Name</label>
+ <input class="form-control" type="text" id="company_name" placeholder="Company Name" value="{{ company_name }}">
+ </fieldset>
+ <fieldset>
+ <label>Mobile No</label>
+ <input class="form-control" type="text" id="mobile_no" placeholder="Mobile No" value="{{ mobile_no }}">
+ </fieldset>
+ <fieldset>
+ <label>Phone</label>
+ <input class="form-control" type="text" id="phone" placeholder="Phone" value="{{ phone }}">
+ </fieldset>
+ <button id="update_user" type="submit" class="btn btn-default">Update</button>
+ </form>
+</div>
+<script>
+$(document).ready(function() {
+ $("#fullname").val(getCookie("full_name") || "");
+ $("#update_user").click(function() {
+ frappe.call({
+ method: "shopping_cart.templates.pages.user.update_user",
+ type: "POST",
+ args: {
+ fullname: $("#fullname").val(),
+ company_name: $("#company_name").val(),
+ mobile_no: $("#mobile_no").val(),
+ phone: $("#phone").val()
+ },
+ btn: this,
+ msg: $("#message"),
+ callback: function(r) {
+ if(!r.exc) $("#user-full-name").html($("#fullname").val());
+ }
+ });
+ return false;
+ })
+})
+</script>
+<!-- no-sidebar -->
+{% endblock %}
+
diff --git a/erpnext/templates/pages/user.py b/erpnext/templates/pages/user.py
new file mode 100644
index 0000000..5869e98
--- /dev/null
+++ b/erpnext/templates/pages/user.py
@@ -0,0 +1,40 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+from frappe.utils import cstr
+from erpnext.shopping_cart.cart import get_lead_or_customer
+
+no_cache = 1
+no_sitemap = 1
+
+def get_context(context):
+ party = get_lead_or_customer()
+ if party.doctype == "Lead":
+ mobile_no = party.mobile_no
+ phone = party.phone
+ else:
+ mobile_no, phone = frappe.db.get_value("Contact", {"email_id": frappe.session.user,
+ "customer": party.name}, ["mobile_no", "phone"])
+
+ return {
+ "company_name": cstr(party.customer_name if party.doctype == "Customer" else party.company_name),
+ "mobile_no": cstr(mobile_no),
+ "phone": cstr(phone)
+ }
+
+@frappe.whitelist()
+def update_user(fullname, password=None, company_name=None, mobile_no=None, phone=None):
+ from erpnext.shopping_cart.cart import update_party
+ update_party(fullname, company_name, mobile_no, phone)
+
+ if not fullname:
+ return _("Name is required")
+
+ frappe.db.set_value("User", frappe.session.user, "first_name", fullname)
+ frappe.local.cookie_manager.set_cookie("full_name", fullname)
+
+ return _("Updated")
+
\ No newline at end of file
diff --git a/erpnext/templates/utils.py b/erpnext/templates/utils.py
index 9892924..139e63a 100644
--- a/erpnext/templates/utils.py
+++ b/erpnext/templates/utils.py
@@ -2,7 +2,10 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
-import frappe
+
+import frappe, json
+from frappe import _
+from frappe.utils import cint, formatdate
@frappe.whitelist(allow_guest=True)
def send_message(subject="Website Query", message="", sender="", status="Open"):
@@ -18,3 +21,47 @@
"sent_or_received": "Received"
})
comm.insert(ignore_permissions=True)
+
+def get_transaction_list(doctype, start, additional_fields=None):
+ # find customer id
+ customer = frappe.db.get_value("Contact", {"email_id": frappe.session.user},
+ "customer")
+
+ if customer:
+ if additional_fields:
+ additional_fields = ", " + ", ".join(("`%s`" % f for f in additional_fields))
+ else:
+ additional_fields = ""
+
+ transactions = frappe.db.sql("""select name, creation, currency, grand_total_export
+ %s
+ from `tab%s` where customer=%s and docstatus=1
+ order by creation desc
+ limit %s, 20""" % (additional_fields, doctype, "%s", "%s"),
+ (customer, cint(start)), as_dict=True)
+ for doc in transactions:
+ items = frappe.db.sql_list("""select item_name
+ from `tab%s Item` where parent=%s limit 6""" % (doctype, "%s"), doc.name)
+ doc.items = ", ".join(items[:5]) + ("..." if (len(items) > 5) else "")
+ doc.creation = formatdate(doc.creation)
+ return transactions
+ else:
+ return []
+
+def get_currency_context():
+ return {
+ "global_number_format": frappe.db.get_default("number_format") or "#,###.##",
+ "currency": frappe.db.get_default("currency"),
+ "currency_symbols": json.dumps(dict(frappe.db.sql("""select name, symbol
+ from tabCurrency where ifnull(enabled,0)=1""")))
+ }
+
+def get_transaction_context(doctype, name):
+ customer = frappe.db.get_value("Contact", {"email_id": frappe.session.user},
+ "customer")
+
+ doc = frappe.get_doc(doctype, name)
+ if doc.customer != customer:
+ return { "doc": frappe._dict({"name": _("Not Allowed")}) }
+ else:
+ return { "doc": doc }
diff --git a/erpnext/translations/ar.csv b/erpnext/translations/ar.csv
index 4e587db..aefb890 100644
--- a/erpnext/translations/ar.csv
+++ b/erpnext/translations/ar.csv
@@ -3329,3 +3329,49 @@
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: مركز التكلفة إلزامي القطعة ل{2}
{0}: {1} not found in Invoice Details table,{0}: {1} غير موجود في جدول تفاصيل الفاتورة
(Half Day),(نصف يوم)
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> إضافة / تحرير < / A>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> إضافة / تحرير < / A>"
+Billed,توصف
+Company,شركة
+Currency is required for Price List {0},مطلوب العملة ل قائمة الأسعار {0}
+Default Customer Group,المجموعة الافتراضية العملاء
+Default Territory,الافتراضي الإقليم
+Delivered,تسليم
+Enable Shopping Cart,تمكين سلة التسوق
+Go ahead and add something to your cart.,المضي قدما وإضافة شيء إلى عربة التسوق.
+Hey! Go ahead and add an address,احترس المضي قدما وإضافة عنوان
+Invalid Billing Address,عنوان الفواتير غير صالحة
+Invalid Shipping Address,العنوان شحن غير صالحة
+Missing Currency Exchange Rates for {0},أسعار صرف العملات في عداد المفقودين ل {0}
+Name is required,مطلوب اسم
+Not Allowed,غير مسموح
+Paid,مدفوع
+Partially Billed,وصفت جزئيا
+Partially Delivered,سلمت جزئيا
+Please specify a Price List which is valid for Territory,الرجاء تحديد قائمة الأسعار التي هي صالحة للأراضي
+Please specify currency in Company,يرجى تحديد العملة في شركة
+Please write something,يرجى كتابة شيء
+Please write something in subject and message!,يرجى كتابة شيء في الموضوع و رسالة !
+Price List,قائمة الأسعار
+Price List not configured.,قائمة السعر لم يتم تكوين.
+Quotation Series,سلسلة الاقتباس
+Shipping Rule,الشحن القاعدة
+Shopping Cart,سلة التسوق
+Shopping Cart Price List,عربة التسوق قائمة الأسعار
+Shopping Cart Price Lists,سلة التسوق قوائم الأسعار
+Shopping Cart Settings,إعدادات سلة التسوق
+Shopping Cart Shipping Rule,سلة التسوق الشحن القاعدة
+Shopping Cart Shipping Rules,سلة التسوق قواعد الشحن
+Shopping Cart Taxes and Charges Master,التسوق سلة الضرائب والرسوم ماجستير
+Shopping Cart Taxes and Charges Masters,التسوق سلة الضرائب والرسوم الماجستير
+Something went wrong!,ذهب شيئا خاطئا!
+Something went wrong.,ذهب شيئا خاطئا.
+Tax Master,ماستر الضرائب
+To Pay,على الدفع
+Updated,تحديث
+You are not allowed to reply to this ticket.,لا يسمح لك للرد على هذه التذكرة .
+You need to be logged in to view your cart.,تحتاج إلى تسجيل الدخول لمشاهدة عربة التسوق.
+You need to enable Shopping Cart,تحتاج إلى تمكين سلة التسوق
+{0} cannot be purchased using Shopping Cart,{0} لا يمكن شراؤها باستخدام عربة التسوق
+{0} is required,{0} مطلوب
+{0} {1} has a common territory {2},{0} {1} لديه أراضي مشتركة {2}
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index a1c0a56..ac797e1 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -3460,3 +3460,51 @@
{0} {1} status is Unstopped,{0} {1} Status unstopped
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: Kostenstelle ist obligatorisch für Artikel {2}
{0}: {1} not found in Invoice Details table,{0}: {1} nicht in der Rechnungs Details-Tabelle gefunden
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> Hinzufügen / Bearbeiten </ a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> Hinzufügen / Bearbeiten </ a>"
+Billed,Abgerechnet
+Company,Unternehmen
+Currency is required for Price List {0},Die Währung ist für Preisliste erforderlich {0}
+Default Customer Group,Standardkundengruppe
+Default Territory,Standardregion
+Default settings for Shopping Cart,Standardeinstellungen für Einkaufswagen
+Delivered,Geliefert
+Enable Shopping Cart,Einkaufswagen aktivieren
+Go ahead and add something to your cart.,Gehen Sie voran und fügen Sie etwas in Ihren Warenkorb.
+Hey! Go ahead and add an address,Hallo! Gehen Sie voran und fügen Sie eine Adresse
+Invalid Billing Address,Ungültige Rechnungsadresse
+Invalid Shipping Address,Falsche Lieferadresse
+Missing Currency Exchange Rates for {0},Fehlende Wechselkurse für {0}
+Name is required,Name ist erforderlich
+Not Allowed,Nicht erlaubt
+Paid,bezahlt
+Partially Billed,teilweise Angekündigt
+Partially Delivered,teilweise Lieferung
+Please specify a Price List which is valid for Territory,"Legen Sie eine Preisliste fest, die für die Region gültig ist"
+Please specify currency in Company,Geben Sie die Währung im Unternehmen an
+Please write something,Bitte schreiben Sie etwas
+Please write something in subject and message!,Bitte schreiben Sie etwas in Betreff und die Nachricht !
+Price List,Preisliste
+Price List not configured.,Preisliste nicht konfiguriert.
+Quotation Series,Angebotsserie
+Shipping Rule,Versandregel
+Shopping Cart,Einkaufswagen
+Shopping Cart Price List,Einkaufswagen Preisliste
+Shopping Cart Price Lists,Einkaufswagen Preislisten
+Shopping Cart Settings,Einkaufswageneinstellungen
+Shopping Cart Shipping Rule,Einkaufswagen-Versandregel
+Shopping Cart Shipping Rules,Einkaufswagen-Versandregeln
+Shopping Cart Taxes and Charges Master,Einkaufswagen-Steuern und Abgabenstamm
+Shopping Cart Taxes and Charges Masters,Einkaufswagen-Steuern und Abgabenstämme
+Something went wrong!,Etwas ist schiefgelaufen!
+Something went wrong.,Es gab ein Problem.
+Tax Master,Steuerstamm
+To Pay,To Pay
+Updated,Aktualisiert
+Website Manager,
+You are not allowed to reply to this ticket.,"Sie sind nicht berechtigt, auf diesem Ticket antworten ."
+You need to be logged in to view your cart.,"Sie müssen angemeldet sein, um Ihren Warenkorb zu sehen."
+You need to enable Shopping Cart,Sie benötigen den Einkaufswagen zu ermöglichen
+{0} cannot be purchased using Shopping Cart,{0} kann nicht mit Einkaufswagen erworben werden
+{0} is required,{0} ist erforderlich
+{0} {1} has a common territory {2},{0} {1} hat einen gemeinsamen Territorium {2}
diff --git a/erpnext/translations/el.csv b/erpnext/translations/el.csv
index 4e1e05f..7526120 100644
--- a/erpnext/translations/el.csv
+++ b/erpnext/translations/el.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} η κατάσταση είναι ανεμπόδιστη
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: Κέντρο Κόστους είναι υποχρεωτική για τη θέση {2}
{0}: {1} not found in Invoice Details table,{0}: {1} δεν βρέθηκε στον πίνακα Στοιχεία τιμολογίου
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> Προσθήκη / Επεξεργασία < / a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> Προσθήκη / Επεξεργασία < / a>"
+Billed,Χρεώνεται
+Company,Εταιρεία
+Currency is required for Price List {0},Νόμισμα απαιτείται για Τιμοκατάλογος {0}
+Default Customer Group,Προεπιλογή Ομάδα πελατών
+Default Territory,Έδαφος Προεπιλογή
+Delivered,Δημοσιεύθηκε
+Enable Shopping Cart,Ενεργοποίηση Καλάθι Αγορών
+Go ahead and add something to your cart.,Προχωρήστε και να προσθέσω κάτι στο καλάθι σας.
+Hey! Go ahead and add an address,Γειά! Προχωρήστε και να προσθέσετε μια διεύθυνση
+Invalid Billing Address,Μη έγκυρη διεύθυνση χρέωσης
+Invalid Shipping Address,Μη έγκυρη διεύθυνση αποστολής
+Missing Currency Exchange Rates for {0},Λείπει Τιμές συναλλάγματος για {0}
+Name is required,Όνομα απαιτείται
+Not Allowed,δεν επιτρέπονται κατοικίδια
+Paid,Αμειβόμενος
+Partially Billed,μερικώς Billed
+Partially Delivered,μερικώς Δημοσιεύθηκε
+Please specify a Price List which is valid for Territory,Παρακαλείστε να προσδιορίσετε μια λίστα τιμών που ισχύει για Επικράτεια
+Please specify currency in Company,Παρακαλείστε να προσδιορίσετε το νόμισμα στην εταιρεία
+Please write something,Παρακαλώ γράψτε κάτι
+Please write something in subject and message!,Παρακαλώ γράψτε κάτι στο θέμα και το μήνυμα !
+Price List,Τιμοκατάλογος
+Price List not configured.,Τιμοκατάλογος δεν έχει ρυθμιστεί.
+Quotation Series,Σειρά Προσφοράς
+Shipping Rule,Αποστολές Κανόνας
+Shopping Cart,Καλάθι Αγορών
+Shopping Cart Price List,Shopping Τιμοκατάλογος Καλάθι
+Shopping Cart Price Lists,Τιμοκατάλογοι Καλάθι Αγορών
+Shopping Cart Settings,Ρυθμίσεις Καλάθι Αγορών
+Shopping Cart Shipping Rule,Καλάθι Αγορών αποστολή Κανόνας
+Shopping Cart Shipping Rules,Κανόνες Shipping Καλάθι Αγορών
+Shopping Cart Taxes and Charges Master,Φόροι Καλάθι και Χρεώσεις Δάσκαλος
+Shopping Cart Taxes and Charges Masters,Φόροι Καλάθι και Χρεώσεις Masters
+Something went wrong!,Κάτι πήγε στραβά!
+Something went wrong.,Κάτι πήγε στραβά.
+Tax Master,Δάσκαλος φόρου
+To Pay,να πληρώσει
+Updated,Ενημέρωση
+You are not allowed to reply to this ticket.,Δεν επιτρέπεται να απαντήσετε σε αυτό το εισιτήριο .
+You need to be logged in to view your cart.,Θα πρέπει να είστε συνδεδεμένοι για να δείτε το καλάθι σας.
+You need to enable Shopping Cart,Χρειάζεται να ενεργοποιήσετε Καλάθι Αγορών
+{0} cannot be purchased using Shopping Cart,{0} δεν μπορούν να αγοραστούν χρησιμοποιώντας Καλάθι Αγορών
+{0} is required,{0} απαιτείται
+{0} {1} has a common territory {2},{0} {1} έχει ένα κοινό έδαφος {2}
diff --git a/erpnext/translations/es.csv b/erpnext/translations/es.csv
index 0fe2847..1688562 100644
--- a/erpnext/translations/es.csv
+++ b/erpnext/translations/es.csv
@@ -3335,3 +3335,49 @@
{0} {1} status is Unstopped,{0} {1} Estado es destapados
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: Centro de Costo es obligatorio para el punto {2}
{0}: {1} not found in Invoice Details table,{0}: {1} no se encuentra en la factura Detalles mesa
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer grupo""> Añadir / Editar < / a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> Añadir / Editar < / a>"
+Billed,Anunciado
+Company,Empresa
+Currency is required for Price List {0},Se requiere de divisas para el precio de lista {0}
+Default Customer Group,Grupo predeterminado Cliente
+Default Territory,Territorio predeterminado
+Delivered,liberado
+Enable Shopping Cart,Habilitar Compras
+Go ahead and add something to your cart.,Seguir adelante y añadir algo a su carrito.
+Hey! Go ahead and add an address,¡Hey! Seguir adelante y añadir una dirección
+Invalid Billing Address,No válida dirección de facturación
+Invalid Shipping Address,Dirección no válida de envío
+Missing Currency Exchange Rates for {0},Missing Tipo de Cambio para {0}
+Name is required,El nombre es necesario
+Not Allowed,No se permite
+Paid,pagado
+Partially Billed,Parcialmente Anunciado
+Partially Delivered,Parcialmente Entregado
+Please specify a Price List which is valid for Territory,"Por favor, especifique una lista de precios que es válido para el territorio"
+Please specify currency in Company,"Por favor, especifique la moneda en la empresa"
+Please write something,"Por favor, escribir algo"
+Please write something in subject and message!,"Por favor, escriba algo en asunto y el mensaje !"
+Price List,Lista de Precios
+Price List not configured.,Lista de precios no está configurado.
+Quotation Series,Serie Cotización
+Shipping Rule,Regla de envío
+Shopping Cart,Cesta de la compra
+Shopping Cart Price List,Cesta de la compra Precio de lista
+Shopping Cart Price Lists,Compras Listas de precios
+Shopping Cart Settings,Compras Ajustes
+Shopping Cart Shipping Rule,Compras Regla de envío
+Shopping Cart Shipping Rules,Compras Reglas de Envío
+Shopping Cart Taxes and Charges Master,Compras Impuestos y Cargos Maestro
+Shopping Cart Taxes and Charges Masters,Carrito impuestos y las cargas Masters
+Something went wrong!,¡Algo salió mal!
+Something went wrong.,Algo salió mal.
+Tax Master,Maestro de Impuestos
+To Pay,Pagar
+Updated,actualizado
+You are not allowed to reply to this ticket.,No se le permite responder a este boleto.
+You need to be logged in to view your cart.,Tienes que estar registrado para ver su carrito.
+You need to enable Shopping Cart,Necesita habilitar Compras
+{0} cannot be purchased using Shopping Cart,{0} no puede ser comprado usando Compras
+{0} is required,{0} es necesario
+{0} {1} has a common territory {2},{0} {1} tiene un territorio común {2}
diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv
index 2d3af17..34cdafa 100644
--- a/erpnext/translations/fr.csv
+++ b/erpnext/translations/fr.csv
@@ -3330,3 +3330,49 @@
{0} {1} status is Unstopped,Vous ne pouvez pas reporter le numéro de rangée supérieure ou égale à numéro de la ligne actuelle pour ce type de charge
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: Centre de coûts est obligatoire pour objet {2}
{0}: {1} not found in Invoice Details table,{0}: {1} ne trouve pas dans la table Détails de la facture
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> Ajouter / Modifier < / a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> Ajouter / Modifier < / a>"
+Billed,Facturé
+Company,Entreprise
+Currency is required for Price List {0},{0} est obligatoire
+Default Customer Group,Groupe de clients par défaut
+Default Territory,Territoire défaut
+Delivered,Livré
+Enable Shopping Cart,Activer Panier
+Go ahead and add something to your cart.,Allez-y et ajouter quelque chose à votre panier.
+Hey! Go ahead and add an address,Hé ! Allez-y et ajoutez une adresse
+Invalid Billing Address,"Pour exécuter un test ajouter le nom du module dans la route après '{0}' . Par exemple, {1}"
+Invalid Shipping Address,effondrement
+Missing Currency Exchange Rates for {0},Vider le cache
+Name is required,Le nom est obligatoire
+Not Allowed,"Groupe ajoutée, rafraîchissant ..."
+Paid,payé
+Partially Billed,partiellement Facturé
+Partially Delivered,Livré partiellement
+Please specify a Price List which is valid for Territory,S'il vous plaît spécifier une liste de prix qui est valable pour le territoire
+Please specify currency in Company,S'il vous plaît préciser la devise dans la société
+Please write something,S'il vous plaît écrire quelque chose
+Please write something in subject and message!,S'il vous plaît écrire quelque chose dans le thème et le message !
+Price List,Liste des Prix
+Price List not configured.,Liste des prix non configuré.
+Quotation Series,Série de devis
+Shipping Rule,Livraison règle
+Shopping Cart,Panier
+Shopping Cart Price List,Panier Liste des prix
+Shopping Cart Price Lists,Panier Liste des prix
+Shopping Cart Settings,Panier Paramètres
+Shopping Cart Shipping Rule,Panier Livraison règle
+Shopping Cart Shipping Rules,Panier Règles d'expédition
+Shopping Cart Taxes and Charges Master,Panier taxes et redevances Maître
+Shopping Cart Taxes and Charges Masters,Panier Taxes et frais de maîtrise
+Something went wrong!,Quelque chose s'est mal passé!
+Something went wrong.,Une erreur est survenue.
+Tax Master,Maître d'impôt
+To Pay,à payer
+Updated,Mise à jour
+You are not allowed to reply to this ticket.,Vous n'êtes pas autorisé à répondre à ce billet .
+You need to be logged in to view your cart.,Vous devez être connecté pour voir votre panier.
+You need to enable Shopping Cart,Poster n'existe pas . S'il vous plaît ajoutez poste !
+{0} cannot be purchased using Shopping Cart,Envoyer permanence {0} ?
+{0} is required,{0} ne peut pas être acheté en utilisant Panier
+{0} {1} has a common territory {2},Alternative lien de téléchargement
diff --git a/erpnext/translations/hi.csv b/erpnext/translations/hi.csv
index e109249..b9b64fe 100644
--- a/erpnext/translations/hi.csv
+++ b/erpnext/translations/hi.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} स्थिति unstopped है
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: लागत केंद्र मद के लिए अनिवार्य है {2}
{0}: {1} not found in Invoice Details table,{0} {1} चालान विवरण तालिका में नहीं मिला
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> जोड़ें / संपादित करें </ a >"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> जोड़ें / संपादित करें </ a >"
+Billed,का बिल
+Company,कंपनी
+Currency is required for Price List {0},मुद्रा मूल्य सूची के लिए आवश्यक है {0}
+Default Customer Group,डिफ़ॉल्ट ग्राहक समूह
+Default Territory,Default टेरिटरी
+Delivered,दिया गया
+Enable Shopping Cart,शॉपिंग कार्ट सक्षम करें
+Go ahead and add something to your cart.,आगे बढ़ो और अपनी गाड़ी को कुछ जोड़ सकते.
+Hey! Go ahead and add an address,अरे! आगे बढ़ो और एक पते जोड़
+Invalid Billing Address,अवैध बिलिंग पता
+Invalid Shipping Address,अवैध शिपिंग पता
+Missing Currency Exchange Rates for {0},के लिए मुद्रा विनिमय दरें गुम {0}
+Name is required,नाम आवश्यक है
+Not Allowed,अनुमति नहीं
+Paid,प्रदत्त
+Partially Billed,आंशिक रूप से बिल
+Partially Delivered,आंशिक रूप से वितरित
+Please specify a Price List which is valid for Territory,राज्य क्षेत्र के लिए मान्य है जो एक मूल्य सूची निर्दिष्ट करें
+Please specify currency in Company,कंपनी में मुद्रा निर्दिष्ट करें
+Please write something,कुछ लिखें
+Please write something in subject and message!,विषय और संदेश में कुछ लिखने के लिए धन्यवाद !
+Price List,कीमत सूची
+Price List not configured.,मूल्य सूची कॉन्फ़िगर नहीं.
+Quotation Series,कोटेशन सीरीज
+Shipping Rule,नौवहन नियम
+Shopping Cart,खरीदारी की टोकरी
+Shopping Cart Price List,शॉपिंग कार्ट में मूल्य सूची
+Shopping Cart Price Lists,शॉपिंग कार्ट में मूल्य सूची
+Shopping Cart Settings,शॉपिंग कार्ट सेटिंग्स
+Shopping Cart Shipping Rule,शॉपिंग कार्ट शिपिंग नियम
+Shopping Cart Shipping Rules,शॉपिंग कार्ट शिपिंग नियम
+Shopping Cart Taxes and Charges Master,शॉपिंग कार्ट में करों और शुल्कों मास्टर
+Shopping Cart Taxes and Charges Masters,शॉपिंग कार्ट में करों और शुल्कों मास्टर्स
+Something went wrong!,कुछ गलत हो गया!
+Something went wrong.,कुछ गलत हो गया.
+Tax Master,टैक्स मास्टर
+To Pay,भुगतान करने के लिए
+Updated,अद्यतित
+You are not allowed to reply to this ticket.,आप इस टिकट का उत्तर देने की अनुमति नहीं है .
+You need to be logged in to view your cart.,आप अपनी गाड़ी को देखने के लिए लॉग इन करना होगा.
+You need to enable Shopping Cart,आप शॉपिंग कार्ट में सक्रिय करने की जरूरत
+{0} cannot be purchased using Shopping Cart,{0} शॉपिंग कार्ट का उपयोग कर खरीदा नहीं जा सकता
+{0} is required,{0} के लिए आवश्यक है
+{0} {1} has a common territory {2},{0} {1} एक सामान्य क्षेत्र है {2}
diff --git a/erpnext/translations/hr.csv b/erpnext/translations/hr.csv
index 4f5c050..70a8a90 100644
--- a/erpnext/translations/hr.csv
+++ b/erpnext/translations/hr.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} status Unstopped
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: troška je obvezno za točku {2}
{0}: {1} not found in Invoice Details table,{0}: {1} nije pronađen u Pojedinosti dostavnice stolu
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> Dodaj / Uredi < />"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> Dodaj / Uredi < />"
+Billed,Naplaćeno
+Company,Društvo
+Currency is required for Price List {0},Valuta je potrebno za Cjenika {0}
+Default Customer Group,Zadani Korisnik Grupa
+Default Territory,Zadani Regija
+Delivered,Isporučena
+Enable Shopping Cart,Omogućite Košarica
+Go ahead and add something to your cart.,Ići naprijed i dodati nešto u košaricu.
+Hey! Go ahead and add an address,Hej! Ići naprijed i dodati adresu
+Invalid Billing Address,Pogrešna adresa naplate
+Invalid Shipping Address,Invalid Dostava Adresa
+Missing Currency Exchange Rates for {0},Nedostaje Tečajne stope za {0}
+Name is required,Ime je potrebno
+Not Allowed,Not Allowed
+Paid,plaćen
+Partially Billed,djelomično Naplaćeno
+Partially Delivered,djelomično Isporučeno
+Please specify a Price List which is valid for Territory,Navedite cjenik koji vrijedi za teritoriju
+Please specify currency in Company,Navedite valutu u Društvu
+Please write something,Molimo napisati nešto
+Please write something in subject and message!,Molimo napisati nešto u temi i poruke !
+Price List,Cjenik
+Price List not configured.,Popis Cijena nije konfiguriran.
+Quotation Series,Ponuda Serija
+Shipping Rule,Dostava Pravilo
+Shopping Cart,Košarica
+Shopping Cart Price List,Košarica Cjenik
+Shopping Cart Price Lists,Košarica cjenike
+Shopping Cart Settings,Košarica Postavke
+Shopping Cart Shipping Rule,Košarica Dostava Pravilo
+Shopping Cart Shipping Rules,Košarica Dostava Pravila
+Shopping Cart Taxes and Charges Master,Košarica poreze i troškove Master
+Shopping Cart Taxes and Charges Masters,Košarica Porezi i naknade Masters
+Something went wrong!,Nešto je pošlo po krivu!
+Something went wrong.,Nešto je pošlo po zlu.
+Tax Master,Porezna Master
+To Pay,platiti
+Updated,Obnovljeno
+You are not allowed to reply to this ticket.,Vi ne smijete odgovoriti na ovu kartu.
+You need to be logged in to view your cart.,Morate biti prijavljeni da biste vidjeli svoju košaricu.
+You need to enable Shopping Cart,Morate omogućiti Košarica
+{0} cannot be purchased using Shopping Cart,{0} ne može se kupiti pomoću Košarica
+{0} is required,{0} je potrebno
+{0} {1} has a common territory {2},{0} {1} ima zajednički teritorij {2}
diff --git a/erpnext/translations/id.csv b/erpnext/translations/id.csv
index dfd93cf..025baa0 100644
--- a/erpnext/translations/id.csv
+++ b/erpnext/translations/id.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} status unstopped
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: Biaya Pusat adalah wajib untuk Item {2}
{0}: {1} not found in Invoice Details table,{0}: {1} tidak ditemukan dalam Faktur Rincian table
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> Add / Edit </ a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> Tambah / Edit </ a>"
+Billed,Ditagih
+Company,Perusahaan
+Currency is required for Price List {0},Mata Uang diperlukan untuk Daftar Harga {0}
+Default Customer Group,Bawaan Pelanggan Grup
+Default Territory,Wilayah standar
+Delivered,Disampaikan
+Enable Shopping Cart,Aktifkan Keranjang Belanja
+Go ahead and add something to your cart.,Pergi ke depan dan menambahkan sesuatu ke keranjang Anda.
+Hey! Go ahead and add an address,Hei! Pergi ke depan dan menambahkan alamat
+Invalid Billing Address,Alamat Penagihan valid
+Invalid Shipping Address,Alamat Pengiriman valid
+Missing Currency Exchange Rates for {0},Hilang Kurs mata uang Tarif untuk {0}
+Name is required,Nama dibutuhkan
+Not Allowed,Tidak Diizinkan
+Paid,Terbayar
+Partially Billed,Sebagian Ditagih
+Partially Delivered,Sebagian Disampaikan
+Please specify a Price List which is valid for Territory,Tentukan Daftar Harga yang berlaku untuk Wilayah
+Please specify currency in Company,Silakan tentukan mata uang di Perusahaan
+Please write something,Silahkan menulis sesuatu
+Please write something in subject and message!,Silahkan menulis sesuatu dalam subjek dan pesan!
+Price List,Daftar Harga
+Price List not configured.,Daftar Harga belum dikonfigurasi.
+Quotation Series,Quotation Series
+Shipping Rule,Aturan Pengiriman
+Shopping Cart,Daftar Belanja
+Shopping Cart Price List,Daftar Belanja Daftar Harga
+Shopping Cart Price Lists,Daftar Harga Daftar Belanja
+Shopping Cart Settings,Pengaturan Keranjang Belanja
+Shopping Cart Shipping Rule,Belanja Pengiriman Rule
+Shopping Cart Shipping Rules,Daftar Belanja Pengiriman Aturan
+Shopping Cart Taxes and Charges Master,Pajak Keranjang Belanja dan Biaya Guru
+Shopping Cart Taxes and Charges Masters,Daftar Belanja Pajak dan Biaya Masters
+Something went wrong!,Ada yang tidak beres!
+Something went wrong.,Ada Sesuatu yang tidak beres.
+Tax Master,Guru Pajak
+To Pay,Untuk Bayar
+Updated,Diperbarui
+You are not allowed to reply to this ticket.,Anda tidak diizinkan untuk membalas tiket ini.
+You need to be logged in to view your cart.,Anda harus login untuk melihat keranjang Anda.
+You need to enable Shopping Cart,Anda harus mengaktifkan Keranjang Belanja
+{0} cannot be purchased using Shopping Cart,{0} tidak dapat dibeli dengan menggunakan Keranjang Belanja
+{0} is required,{0} diperlukan
+{0} {1} has a common territory {2},{0} {1} memiliki wilayah umum {2}
diff --git a/erpnext/translations/it.csv b/erpnext/translations/it.csv
index 6ca5f99..f59fdd6 100644
--- a/erpnext/translations/it.csv
+++ b/erpnext/translations/it.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} stato è unstopped
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: centro di costo è obbligatoria per la voce {2}
{0}: {1} not found in Invoice Details table,{0}: {1} non trovato in fattura tabella Dettagli
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> Aggiungi / Modifica < / a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> Aggiungi / Modifica < / a>"
+Billed,Addebbitato
+Company,Azienda
+Currency is required for Price List {0},È richiesto di valuta per il listino prezzi {0}
+Default Customer Group,Gruppo Clienti Predefinito
+Default Territory,Territorio Predefinito
+Delivered,Consegnato
+Enable Shopping Cart,Abilita Carello Acquisti
+Go ahead and add something to your cart.,Vai avanti e aggiungere qualcosa al tuo carrello.
+Hey! Go ahead and add an address,Ehi! Vai avanti e aggiungere un indirizzo
+Invalid Billing Address,Valido indirizzo di fatturazione
+Invalid Shipping Address,Valido Indirizzo di spedizione
+Missing Currency Exchange Rates for {0},Manca valuta Tassi di cambio {0}
+Name is required,Il nome è obbligatorio
+Not Allowed,non sono ammessi
+Paid,pagato
+Partially Billed,parzialmente Fatturato
+Partially Delivered,parzialmente Consegnato
+Please specify a Price List which is valid for Territory,Si prega di specificare una lista di prezzi è valido per il Territorio
+Please specify currency in Company,Si prega di specificare la valuta in Azienda
+Please write something,Si prega di scrivere qualcosa
+Please write something in subject and message!,Si prega di scrivere qualcosa in oggetto e il messaggio !
+Price List,Listino Prezzi
+Price List not configured.,Prezzo di listino non è configurato.
+Quotation Series,Serie Quotazione
+Shipping Rule,Spedizione Rule
+Shopping Cart,Carrello spesa
+Shopping Cart Price List,Carrello Prezzo di listino
+Shopping Cart Price Lists,Carrello Listini
+Shopping Cart Settings,Carrello Impostazioni
+Shopping Cart Shipping Rule,Carrello Spedizioni Rule
+Shopping Cart Shipping Rules,Carrello Regole di Spedizione
+Shopping Cart Taxes and Charges Master,Carrello Tasse e Spese master
+Shopping Cart Taxes and Charges Masters,Carrello Tasse e Costi Masters
+Something went wrong!,Qualcosa è andato storto!
+Something went wrong.,Qualcosa è andato storto.
+Tax Master,Tax Maestro
+To Pay,To Pay
+Updated,Aggiornato
+You are not allowed to reply to this ticket.,Non sei autorizzato a rispondere a questo biglietto .
+You need to be logged in to view your cart.,Devi essere loggato per vedere il tuo carrello.
+You need to enable Shopping Cart,È necessario abilitare Carrello
+{0} cannot be purchased using Shopping Cart,{0} non può essere acquistato tramite Carrello
+{0} is required,{0} è richiesto
+{0} {1} has a common territory {2},{0} {1} ha un territorio comune {2}
diff --git a/erpnext/translations/ja.csv b/erpnext/translations/ja.csv
index c779aa6..e755a4a 100644
--- a/erpnext/translations/ja.csv
+++ b/erpnext/translations/ja.csv
@@ -3335,3 +3335,49 @@
{0} {1} status is Unstopped,{0} {1}ステータスが塞がです
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}:コストセンターではアイテムのために必須である{2}
{0}: {1} not found in Invoice Details table,{0}:{1}請求書詳細テーブルにない
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","もし、ごhref=""#Sales Browser/Customer Group"">追加/編集</ A>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","もし、ごhref=""#Sales Browser/Territory"">追加/編集</ A>"
+Billed,課金
+Company,会社
+Currency is required for Price List {0},通貨は価格表{0}に必要です
+Default Customer Group,デフォルトの顧客グループ
+Default Territory,デフォルトの地域
+Delivered,配送
+Enable Shopping Cart,ショッピングカートを使用可能に
+Go ahead and add something to your cart.,先に行くと、ショッピングカートに何かを追加。
+Hey! Go ahead and add an address,ハイ!先に行くとアドレスを追加
+Invalid Billing Address,無効な請求先住所
+Invalid Shipping Address,無効な配送先住所
+Missing Currency Exchange Rates for {0},{0}のために為替レートが不足して
+Name is required,名前が必要です
+Not Allowed,許可されていない
+Paid,料金
+Partially Billed,部分的に銘打た
+Partially Delivered,部分的に配信
+Please specify a Price List which is valid for Territory,地域で有効な価格表を指定してください
+Please specify currency in Company,会社で通貨を指定してください
+Please write something,何かを書いてください
+Please write something in subject and message!,件名とメッセージで何かを書いてください!
+Price List,価格リスト
+Price List not configured.,価格表が構成されていません。
+Quotation Series,引用シリーズ
+Shipping Rule,出荷ルール
+Shopping Cart,カート
+Shopping Cart Price List,ショッピングカート価格表
+Shopping Cart Price Lists,ショッピングカート価格表
+Shopping Cart Settings,ショッピングカートの設定
+Shopping Cart Shipping Rule,ショッピングカート配送ルール
+Shopping Cart Shipping Rules,ショッピングカート配送ルール
+Shopping Cart Taxes and Charges Master,ショッピングカートの税金、料金マスター
+Shopping Cart Taxes and Charges Masters,ショッピングカートの税金、料金のマスターズ
+Something went wrong!,何かが間違っていた!
+Something went wrong.,エラーが発生しました。
+Tax Master,税金のマスター
+To Pay,支払わなければ
+Updated,更新日
+You are not allowed to reply to this ticket.,あなたは、このチケットに返信することはできません。
+You need to be logged in to view your cart.,あなたは買い物カゴを見るためにログインする必要があります。
+You need to enable Shopping Cart,あなたはショッピングカートを有効にする必要があります
+{0} cannot be purchased using Shopping Cart,{0}ショッピングカートを使用して購入することはできません
+{0} is required,{0}が必要である
+{0} {1} has a common territory {2},{0} {1}は、共通の領土を持っている{2}
diff --git a/erpnext/translations/kn.csv b/erpnext/translations/kn.csv
index 8dae972..f01e48a 100644
--- a/erpnext/translations/kn.csv
+++ b/erpnext/translations/kn.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} ಸ್ಥಿತಿಯನ್ನು unstopped ಆಗಿದೆ
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: ವೆಚ್ಚ ಸೆಂಟರ್ ಐಟಂ ಕಡ್ಡಾಯ {2}
{0}: {1} not found in Invoice Details table,{0}: {1} ಸರಕುಪಟ್ಟಿ ವಿವರಗಳು ಟೇಬಲ್ ಕಂಡುಬಂದಿಲ್ಲ
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","ಕವಿದ href=""#Sales Browser/Customer Group""> ಸೇರಿಸಿ / ಸಂಪಾದಿಸಿ </ ಒಂದು >"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","ಕವಿದ href=""#Sales Browser/Territory""> ಸೇರಿಸಿ / ಸಂಪಾದಿಸಿ </ ಒಂದು >"
+Billed,ಖ್ಯಾತವಾದ
+Company,ಕಂಪನಿ
+Currency is required for Price List {0},ಕರೆನ್ಸಿ ಬೆಲೆ ಪಟ್ಟಿ ಅಗತ್ಯವಿದೆ {0}
+Default Customer Group,ಡೀಫಾಲ್ಟ್ ಗ್ರಾಹಕ ಗುಂಪಿನ
+Default Territory,ಡೀಫಾಲ್ಟ್ ಪ್ರದೇಶ
+Delivered,ತಲುಪಿಸಲಾಗಿದೆ
+Enable Shopping Cart,ಶಾಪಿಂಗ್ ಕಾರ್ಟ್ ಸಕ್ರಿಯಗೊಳಿಸಿ
+Go ahead and add something to your cart.,ಮುಂದೆ ಹೋಗಿ ಮತ್ತು ನಿಮ್ಮ ಕಾರ್ಟ್ ಏನಾದರೂ ಸೇರಿಸಿ.
+Hey! Go ahead and add an address,ಹೇ! ಮುಂದೆ ಹೋಗಿ ಒಂದು ಸೇರಿಸಿ
+Invalid Billing Address,ಅಮಾನ್ಯವಾದ ಬಿಲ್ಲಿಂಗ್ ವಿಳಾಸ
+Invalid Shipping Address,ಅಮಾನ್ಯವಾದ ಶಿಪ್ಪಿಂಗ್ ವಿಳಾಸ
+Missing Currency Exchange Rates for {0},ಕರೆನ್ಸಿ ವಿನಿಮಯ ದರಗಳು ಮಿಸ್ಸಿಂಗ್ {0}
+Name is required,ಹೆಸರು ಅಗತ್ಯವಿದೆ
+Not Allowed,ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ
+Paid,ಪಾವತಿಸಿದ
+Partially Billed,ಭಾಗಶಃ ಖ್ಯಾತವಾದ
+Partially Delivered,ಭಾಗಶಃ ತಲುಪಿಸಲಾಗಿದೆ
+Please specify a Price List which is valid for Territory,ಪ್ರದೇಶ ಮಾನ್ಯ ಬೆಲೆ ಪಟ್ಟಿ ಸೂಚಿಸಲು ದಯವಿಟ್ಟು
+Please specify currency in Company,ಕಂಪನಿ ಕರೆನ್ಸಿ ಸೂಚಿಸಲು ದಯವಿಟ್ಟು
+Please write something,ಏನೋ ಬರೆಯಲು ಮಾಡಿ
+Please write something in subject and message!,ವಿಷಯ ಮತ್ತು ಸಂದೇಶದ ಏನೋ ಬರೆಯಲು ಮಾಡಿ !
+Price List,ಬೆಲೆ ಪಟ್ಟಿ
+Price List not configured.,ಬೆಲೆ ಪಟ್ಟಿ ಕಾನ್ಫಿಗರ್.
+Quotation Series,ನುಡಿಮುತ್ತುಗಳು ಸರಣಿ
+Shipping Rule,ಶಿಪ್ಪಿಂಗ್ ರೂಲ್
+Shopping Cart,ಶಾಪಿಂಗ್ ಕಾರ್ಟ್
+Shopping Cart Price List,ಶಾಪಿಂಗ್ ಕಾರ್ಟ್ ಬೆಲೆ ಪಟ್ಟಿ
+Shopping Cart Price Lists,ಶಾಪಿಂಗ್ ಕಾರ್ಟ್ ಬೆಲೆ ಪಟ್ಟಿ
+Shopping Cart Settings,ಶಾಪಿಂಗ್ ಕಾರ್ಟ್ ಸೆಟ್ಟಿಂಗ್ಗಳು
+Shopping Cart Shipping Rule,ಶಾಪಿಂಗ್ ಕಾರ್ಟ್ ಶಿಪ್ಪಿಂಗ್ ರೂಲ್
+Shopping Cart Shipping Rules,ಶಾಪಿಂಗ್ ಕಾರ್ಟ್ ಶಿಪ್ಪಿಂಗ್ ನಿಯಮಗಳು
+Shopping Cart Taxes and Charges Master,ಶಾಪಿಂಗ್ ಕಾರ್ಟ್ ತೆರಿಗೆಗಳು ಮತ್ತು ಶುಲ್ಕಗಳು ಮಾಸ್ಟರ್
+Shopping Cart Taxes and Charges Masters,ಶಾಪಿಂಗ್ ಕಾರ್ಟ್ ತೆರಿಗೆಗಳು ಮತ್ತು ಶುಲ್ಕಗಳು ಮಾಸ್ಟರ್ಸ್
+Something went wrong!,ಏನೋ ತಪ್ಪಾಗಿದೆ!
+Something went wrong.,ಯಾವುದೋ ತಪ್ಪು ಸಂಭವಿಸಿದೆ.
+Tax Master,ತೆರಿಗೆ ಮಾಸ್ಟರ್
+To Pay,ಪಾವತಿಸಲು
+Updated,ನವೀಕರಿಸಲಾಗಿದೆ
+You are not allowed to reply to this ticket.,ಈ ಟಿಕೆಟ್ ಪ್ರತ್ಯುತ್ತರ ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ.
+You need to be logged in to view your cart.,ನಿಮ್ಮ ಕಾರ್ಟ್ ಲಾಗಿನ್ ಅಗತ್ಯವಿದೆ.
+You need to enable Shopping Cart,ನೀವು ಶಾಪಿಂಗ್ ಕಾರ್ಟ್ ಸಕ್ರಿಯಗೊಳಿಸಬೇಕು
+{0} cannot be purchased using Shopping Cart,{0} ಶಾಪಿಂಗ್ ಕಾರ್ಟ್ ಬಳಸಿ ಕೊಳ್ಳಬಹುದು ಸಾಧ್ಯವಿಲ್ಲ
+{0} is required,{0} ಅಗತ್ಯವಿದೆ
+{0} {1} has a common territory {2},{0} {1} ಸಾಮಾನ್ಯ ಪ್ರದೇಶವನ್ನು ಹೊಂದಿದೆ {2}
diff --git a/erpnext/translations/ko.csv b/erpnext/translations/ko.csv
index 34e7a44..4a7ea61 100644
--- a/erpnext/translations/ko.csv
+++ b/erpnext/translations/ko.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} 상태 Unstopped입니다
{0} {1}: Cost Center is mandatory for Item {2},{0} {1} : 코스트 센터는 항목에 대해 필수입니다 {2}
{0}: {1} not found in Invoice Details table,{0} {1} 송장 정보 테이블에서 찾을 수 없습니다
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","만약 당신이 좋아 href=""#Sales Browser/Customer Group""> 추가 / 편집 </ A>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","만약 당신이 좋아 href=""#Sales Browser/Territory""> 추가 / 편집 </ A>"
+Billed,청구
+Company,회사
+Currency is required for Price List {0},환율은 가격 목록에 필요한 {0}
+Default Customer Group,기본 고객 그룹
+Default Territory,기본 지역
+Delivered,배달
+Enable Shopping Cart,쇼핑 카트를 사용
+Go ahead and add something to your cart.,가서 당신의 손수레로 뭔가를 추가 할 수 있습니다.
+Hey! Go ahead and add an address,야!가서 주소를 추가
+Invalid Billing Address,잘못된 청구 주소
+Invalid Shipping Address,잘못된 배송 주소
+Missing Currency Exchange Rates for {0},를 위해 환율 누락 {0}
+Name is required,이름이 필요합니다
+Not Allowed,허용하지 않음
+Paid,유료
+Partially Billed,일부 청구
+Partially Delivered,부분적으로 배달
+Please specify a Price List which is valid for Territory,지역에 유효한 가격 목록을 지정하십시오
+Please specify currency in Company,회사에 통화를 지정하십시오
+Please write something,뭔가를 작성 해주세요
+Please write something in subject and message!,제목과 메시지에 무언가를 써주세요!
+Price List,가격리스트
+Price List not configured.,가격 목록이 구성되어 있지.
+Quotation Series,견적 시리즈
+Shipping Rule,배송 규칙
+Shopping Cart,쇼핑 카트
+Shopping Cart Price List,쇼핑 카트의 가격 목록
+Shopping Cart Price Lists,쇼핑 카트의 가격 목록
+Shopping Cart Settings,쇼핑 카트 설정
+Shopping Cart Shipping Rule,장바구니 배송 규칙
+Shopping Cart Shipping Rules,장바구니 배송 규칙
+Shopping Cart Taxes and Charges Master,쇼핑 카트 세금과 요금 마스터
+Shopping Cart Taxes and Charges Masters,쇼핑 카트 세금과 요금의 석사
+Something went wrong!,문제가 발생했습니다!
+Something went wrong.,문제가 발생했습니다.
+Tax Master,세금 마스터
+To Pay,지불하는
+Updated,업데이트
+You are not allowed to reply to this ticket.,당신이 티켓에 회신 할 수 없습니다.
+You need to be logged in to view your cart.,당신은 당신의 카트를 보려면 로그인해야합니다.
+You need to enable Shopping Cart,당신은 쇼핑 카트를 활성화해야
+{0} cannot be purchased using Shopping Cart,{0} 쇼핑 카트를 사용하여 구입 할 수 없습니다
+{0} is required,{0}이 필요합니다
+{0} {1} has a common territory {2},{0} {1} 공통의 영토가 {2}
diff --git a/erpnext/translations/nl.csv b/erpnext/translations/nl.csv
index f8bc987..94cab1d 100644
--- a/erpnext/translations/nl.csv
+++ b/erpnext/translations/nl.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} status ontsloten
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: kostenplaats is verplicht voor Item {2}
{0}: {1} not found in Invoice Details table,{0}: {1} niet gevonden in Factuur Details tabel
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> toevoegen / bewerken < / a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> toevoegen / bewerken < / a>"
+Billed,Gefactureerd
+Company,Vennootschap
+Currency is required for Price List {0},Valuta is vereist voor prijslijst {0}
+Default Customer Group,Standaard Klant Groep
+Default Territory,Standaard Territory
+Delivered,Geleverd
+Enable Shopping Cart,Enable Winkelwagen
+Go ahead and add something to your cart.,Ga je gang en iets toe te voegen aan uw winkelwagen.
+Hey! Go ahead and add an address,Hé! Ga je gang en voeg een adres
+Invalid Billing Address,Ongeldig Factuuradres
+Invalid Shipping Address,Ongeldig verzendadres
+Missing Currency Exchange Rates for {0},Ontbrekende wisselkoersen gedurende {0}
+Name is required,Naam is vereist
+Not Allowed,niet toegestaan
+Paid,betaald
+Partially Billed,gedeeltelijk gefactureerde
+Partially Delivered,gedeeltelijk Geleverd
+Please specify a Price List which is valid for Territory,Geef een prijslijst die geldig is voor het grondgebied
+Please specify currency in Company,Specificeer munt in Bedrijf
+Please write something,Iets schrijven aub
+Please write something in subject and message!,Schrijf iets in het onderwerp en een bericht !
+Price List,Prijslijst
+Price List not configured.,Prijslijst niet geconfigureerd.
+Quotation Series,Offerte Series
+Shipping Rule,Verzending Rule
+Shopping Cart,Winkelwagen
+Shopping Cart Price List,Winkelwagen Prijslijst
+Shopping Cart Price Lists,Winkelwagen Prijslijsten
+Shopping Cart Settings,Winkelwagen Instellingen
+Shopping Cart Shipping Rule,Winkelwagen Scheepvaart Rule
+Shopping Cart Shipping Rules,Winkelwagen Scheepvaart Regels
+Shopping Cart Taxes and Charges Master,Winkelwagen en-heffingen Master
+Shopping Cart Taxes and Charges Masters,Winkelwagen en-heffingen Masters
+Something went wrong!,Er ging iets mis!
+Something went wrong.,Er is iets fout gegaan
+Tax Master,Fiscale Master
+To Pay,te betalen
+Updated,Bijgewerkt
+You are not allowed to reply to this ticket.,Het is niet toegestaan om te reageren op dit kaartje .
+You need to be logged in to view your cart.,Je moet ingelogd zijn om uw winkelwagentje te bekijken.
+You need to enable Shopping Cart,U moet Winkelwagen stellen
+{0} cannot be purchased using Shopping Cart,{0} kan niet worden aangeschaft met Winkelwagen
+{0} is required,{0} is verplicht
+{0} {1} has a common territory {2},{0} {1} heeft een gemeenschappelijk grondgebied {2}
diff --git a/erpnext/translations/pt-BR.csv b/erpnext/translations/pt-BR.csv
index df558c5..7796842 100644
--- a/erpnext/translations/pt-BR.csv
+++ b/erpnext/translations/pt-BR.csv
@@ -3377,3 +3377,49 @@
{0} {1} status is Unstopped,{0} {1} status é abrirão
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: Centro de Custo é obrigatória para item {2}
{0}: {1} not found in Invoice Details table,{0}: {1} não foi encontrado na fatura Detalhes Mesa
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer grupo""> Adicionar / Editar </ a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> Adicionar / Editar </ a>"
+Billed,Faturado
+Company,Empresa
+Currency is required for Price List {0},Moeda é necessário para Preço de {0}
+Default Customer Group,Grupo de Clientes padrão
+Default Territory,Território padrão
+Delivered,Entregue
+Enable Shopping Cart,Ativar Carrinho de Compras
+Go ahead and add something to your cart.,Vá em frente e acrescentar algo ao seu carrinho.
+Hey! Go ahead and add an address,Ei! Vá em frente e adicionar um endereço
+Invalid Billing Address,Inválido Endereço de Cobrança
+Invalid Shipping Address,Inválido envio Endereço
+Missing Currency Exchange Rates for {0},Falta de câmbio de moeda para {0}
+Name is required,Nome é obrigatório
+Not Allowed,não Permitido
+Paid,pago
+Partially Billed,parcialmente faturado
+Partially Delivered,parcialmente entregues
+Please specify a Price List which is valid for Territory,"Por favor, especifique uma lista de preços que é válido para o território"
+Please specify currency in Company,"Por favor, especificar a moeda em Empresa"
+Please write something,"Por favor, escreva algo"
+Please write something in subject and message!,"Por favor, escreva algo no assunto e uma mensagem !"
+Price List,Lista de Preços
+Price List not configured.,Lista de Preço não configurado.
+Quotation Series,Série citação
+Shipping Rule,Regra de envio
+Shopping Cart,Carrinho de Compras
+Shopping Cart Price List,Carrinho de Compras Lista de Preços
+Shopping Cart Price Lists,Carrinho listas de preços
+Shopping Cart Settings,Carrinho Configurações
+Shopping Cart Shipping Rule,Carrinho de Compras Rule envio
+Shopping Cart Shipping Rules,Carrinho Regras frete
+Shopping Cart Taxes and Charges Master,Carrinho impostos e taxas Mestre
+Shopping Cart Taxes and Charges Masters,Carrinho Impostos e Taxas de mestrado
+Something went wrong!,Algo deu errado!
+Something went wrong.,Algo deu errado.
+Tax Master,Imposto de Mestre
+To Pay,pagar
+Updated,Atualizado
+You are not allowed to reply to this ticket.,Você não tem permissão para responder a este bilhete .
+You need to be logged in to view your cart.,Você precisa estar logado para ver seu carrinho.
+You need to enable Shopping Cart,Você precisa habilitar o Carrinho de Compras
+{0} cannot be purchased using Shopping Cart,{0} não pode ser comprado usando Carrinho de Compras
+{0} is required,{0} é necessária
+{0} {1} has a common territory {2},{0} {1} tem um território comum {2}
diff --git a/erpnext/translations/pt.csv b/erpnext/translations/pt.csv
index 18c4617..b4d9bd6 100644
--- a/erpnext/translations/pt.csv
+++ b/erpnext/translations/pt.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} status é abrirão
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: Centro de Custo é obrigatória para item {2}
{0}: {1} not found in Invoice Details table,{0}: {1} não foi encontrado na fatura Detalhes Mesa
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> toevoegen / bewerken < / a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> toevoegen / bewerken < / a>"
+Billed,Faturado
+Company,Companhia
+Currency is required for Price List {0},Moeda é necessário para Preço de {0}
+Default Customer Group,Grupo de Clientes padrão
+Default Territory,Território padrão
+Delivered,Entregue
+Enable Shopping Cart,Ativar Carrinho de Compras
+Go ahead and add something to your cart.,Vá em frente e acrescentar algo ao seu carrinho.
+Hey! Go ahead and add an address,Ei! Vá em frente e adicionar um endereço
+Invalid Billing Address,Inválido Endereço de Cobrança
+Invalid Shipping Address,Inválido envio Endereço
+Missing Currency Exchange Rates for {0},Falta de câmbio de moeda para {0}
+Name is required,Nome é obrigatório
+Not Allowed,não Permitido
+Paid,betaald
+Partially Billed,gedeeltelijk gefactureerde
+Partially Delivered,gedeeltelijk Geleverd
+Please specify a Price List which is valid for Territory,"Por favor, especifique uma lista de preços que é válido para o território"
+Please specify currency in Company,"Por favor, especificar a moeda em Empresa"
+Please write something,Iets schrijven aub
+Please write something in subject and message!,Schrijf iets in het onderwerp en een bericht !
+Price List,Lista de Preços
+Price List not configured.,Lista de Preço não configurado.
+Quotation Series,Série citação
+Shipping Rule,Regra de envio
+Shopping Cart,Carrinho de Compras
+Shopping Cart Price List,Carrinho de Compras Lista de Preços
+Shopping Cart Price Lists,Carrinho listas de preços
+Shopping Cart Settings,Carrinho Configurações
+Shopping Cart Shipping Rule,Carrinho de Compras Rule envio
+Shopping Cart Shipping Rules,Carrinho Regras frete
+Shopping Cart Taxes and Charges Master,Carrinho impostos e taxas Mestre
+Shopping Cart Taxes and Charges Masters,Carrinho Impostos e Taxas de mestrado
+Something went wrong!,Algo deu errado!
+Something went wrong.,Algo deu errado.
+Tax Master,Imposto de Mestre
+To Pay,te betalen
+Updated,Atualizado
+You are not allowed to reply to this ticket.,Het is niet toegestaan om te reageren op dit kaartje .
+You need to be logged in to view your cart.,Você precisa estar logado para ver seu carrinho.
+You need to enable Shopping Cart,Você precisa habilitar o Carrinho de Compras
+{0} cannot be purchased using Shopping Cart,{0} não pode ser comprado usando Carrinho de Compras
+{0} is required,{0} é necessária
+{0} {1} has a common territory {2},{0} {1} tem um território comum {2}
diff --git a/erpnext/translations/ro.csv b/erpnext/translations/ro.csv
index fc6d6ce..a5aa7c4 100644
--- a/erpnext/translations/ro.csv
+++ b/erpnext/translations/ro.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} statut este destupate
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: Cost Center este obligatorie pentru postul {2}
{0}: {1} not found in Invoice Details table,{0}: {1} nu a fost găsit în factură Detalii masă
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> Add / Edit </ a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> Add / Edit </ a>"
+Billed,Facturat
+Company,Firma
+Currency is required for Price List {0},Monedă este necesară pentru lista de prețuri {0}
+Default Customer Group,Implicit Client Group
+Default Territory,Implicit Teritoriul
+Delivered,Livrat
+Enable Shopping Cart,Activați Cosul de cumparaturi
+Go ahead and add something to your cart.,Du-te și adaugă ceva la coș.
+Hey! Go ahead and add an address,Hei! Du-te și adăugați o adresă
+Invalid Billing Address,Adresa de facturare invalid
+Invalid Shipping Address,Adresa Transport invalid
+Missing Currency Exchange Rates for {0},Lipsește valutar Curs valutar pentru {0}
+Name is required,Este necesar numele
+Not Allowed,Nu este permis
+Paid,Platit
+Partially Billed,Parțial Taxat
+Partially Delivered,Parțial livrate
+Please specify a Price List which is valid for Territory,"Vă rugăm să specificați o listă de prețuri, care este valabil pentru teritoriul"
+Please specify currency in Company,Vă rugăm să specificați în valută de companie
+Please write something,Vă rugăm să scrieți ceva
+Please write something in subject and message!,Vă rugăm să scrieți ceva în subiect și un mesaj!
+Price List,Lista de prețuri
+Price List not configured.,Lista de prețuri nu a fost configurat.
+Quotation Series,Citat Series
+Shipping Rule,Regula de transport maritim
+Shopping Cart,Cosul de cumparaturi
+Shopping Cart Price List,Cosul de cumparaturi Lista de prețuri
+Shopping Cart Price Lists,Cosul de cumparaturi Liste de prețuri
+Shopping Cart Settings,Setări Cosul de cumparaturi
+Shopping Cart Shipping Rule,Cosul de cumparaturi Regula Transport
+Shopping Cart Shipping Rules,Cosul de cumparaturi Reguli de expediere
+Shopping Cart Taxes and Charges Master,Taxele coș de cumpărături și taxe de Master
+Shopping Cart Taxes and Charges Masters,Cumpărături Impozite și taxe cos Masters
+Something went wrong!,Ceva a mers prost!
+Something went wrong.,Ceva nu a funcționat.
+Tax Master,Taxa de Master
+To Pay,Pentru a Pay
+Updated,Actualizat
+You are not allowed to reply to this ticket.,Nu vi se permite să răspundeți la acest bilet.
+You need to be logged in to view your cart.,Ai nevoie să fii logat pentru a vedea cosul de cumparaturi.
+You need to enable Shopping Cart,Ai nevoie pentru a permite Cosul de cumparaturi
+{0} cannot be purchased using Shopping Cart,{0} nu pot fi achiziționate cu ajutorul Cosul de cumparaturi
+{0} is required,{0} este necesară
+{0} {1} has a common territory {2},{0} {1} are un teritoriu comun {2}
diff --git a/erpnext/translations/ru.csv b/erpnext/translations/ru.csv
index 09d409e..d79039c 100644
--- a/erpnext/translations/ru.csv
+++ b/erpnext/translations/ru.csv
@@ -3332,3 +3332,49 @@
{0} {1} status is Unstopped,{0} {1} статус отверзутся
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: МВЗ является обязательным для п. {2}
{0}: {1} not found in Invoice Details table,{0} {1} не найден в счете-фактуре таблице
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> Добавить / Изменить </>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> Добавить / Изменить </>"
+Billed,Объявленный
+Company,Организация
+Currency is required for Price List {0},Валюта необходима для Прейскурантом {0}
+Default Customer Group,По умолчанию Группа клиентов
+Default Territory,По умолчанию Территория
+Delivered,Доставлено
+Enable Shopping Cart,Включить Корзина
+Go ahead and add something to your cart.,Идем дальше и добавить что-то в корзину.
+Hey! Go ahead and add an address,16.35 Эй! Идем дальше и добавить адрес
+Invalid Billing Address,Неверный Адрес для выставления счета
+Invalid Shipping Address,Неверный адрес пересылки
+Missing Currency Exchange Rates for {0},Отсутствует валютный курс для {0}
+Name is required,Имя обязательно
+Not Allowed,Не разрешены
+Paid,Оплачено
+Partially Billed,Частично Объявленный
+Partially Delivered,Частично Поставляются
+Please specify a Price List which is valid for Territory,"Пожалуйста, сформулируйте прайс-лист, который действителен для территории"
+Please specify currency in Company,"Пожалуйста, сформулируйте валюту в компании"
+Please write something,"Пожалуйста, напишите что-нибудь"
+Please write something in subject and message!,"Пожалуйста, напишите что-нибудь в тему и текст сообщения!"
+Price List,Прайс-лист
+Price List not configured.,Прайс-лист не настроен.
+Quotation Series,Цитата серии
+Shipping Rule,Правило Доставка
+Shopping Cart,Корзина
+Shopping Cart Price List,Корзина Прайс-лист
+Shopping Cart Price Lists,Корзина Прайс-листы
+Shopping Cart Settings,Корзина Настройки
+Shopping Cart Shipping Rule,Корзина Правило Доставка
+Shopping Cart Shipping Rules,Корзина Правила Доставка
+Shopping Cart Taxes and Charges Master,Корзина Налоги и сборы Мастер
+Shopping Cart Taxes and Charges Masters,Налоги Корзина Торговые и сборы Мастера
+Something went wrong!,Что-то пошло не так!
+Something went wrong.,Что-то пошло не так.
+Tax Master,Налоговый Мастер
+To Pay,Платить
+Updated,Обновлено
+You are not allowed to reply to this ticket.,Вы не можете отвечать на этот билет.
+You need to be logged in to view your cart.,"Вы должны войти в систему, чтобы просмотреть свою корзину."
+You need to enable Shopping Cart,Вам необходимо включить Корзина
+{0} cannot be purchased using Shopping Cart,{0} не может быть приобретен с помощью Корзина
+{0} is required,{0} требуется
+{0} {1} has a common territory {2},{0} {1} имеет общую территорию {2}
diff --git a/erpnext/translations/sr.csv b/erpnext/translations/sr.csv
index 8ff80e0..8a84ef7 100644
--- a/erpnext/translations/sr.csv
+++ b/erpnext/translations/sr.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} статус отверзутся
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: Трошкови Центар је обавезан за пункт {2}
{0}: {1} not found in Invoice Details table,{0}: {1} није пронађен у табели Фактура Детаљи
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<а хреф=""#Салес Бровсер/Цустомер Гроуп""> Додај / Уреди < />"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<а хреф=""#Салес Бровсер/Территори""> Додај / Уреди < />"
+Billed,Изграђена
+Company,Компанија
+Currency is required for Price List {0},Валюта необходима для Прейскурантом {0}
+Default Customer Group,Уобичајено групу потрошача
+Default Territory,Уобичајено Територија
+Delivered,Испоручено
+Enable Shopping Cart,Омогући Корпа
+Go ahead and add something to your cart.,Само напред и додати нешто у вашој корпи.
+Hey! Go ahead and add an address,Хеј! Само напред и додај адресу
+Invalid Billing Address,Неверный Адрес для выставления счета
+Invalid Shipping Address,Неверный адрес пересылки
+Missing Currency Exchange Rates for {0},Отсутствует валютный курс для {0}
+Name is required,Име је обавезно
+Not Allowed,Не разрешены
+Paid,плаћен
+Partially Billed,Делимично Изграђена
+Partially Delivered,Делимично Испоручено
+Please specify a Price List which is valid for Territory,Наведите ценовник који важи за територију
+Please specify currency in Company,Наведите валуту у компанији
+Please write something,Молимо вас да напишете нешто
+Please write something in subject and message!,Молимо вас да напишете нешто у теми и поруци !
+Price List,Ценовник
+Price List not configured.,Ценовник није подесио.
+Quotation Series,Цитат серија
+Shipping Rule,Достава Правило
+Shopping Cart,Корпа
+Shopping Cart Price List,Корпа Ценовник
+Shopping Cart Price Lists,Корпа Ценовници
+Shopping Cart Settings,Корпа Подешавања
+Shopping Cart Shipping Rule,Корпа Достава Правило
+Shopping Cart Shipping Rules,Корпа испоруке Правила
+Shopping Cart Taxes and Charges Master,Корпа такси и накнада Мастер
+Shopping Cart Taxes and Charges Masters,Корпа такси и накнада Мастерс
+Something went wrong!,Нешто је пошло наопако!
+Something went wrong.,Нешто је пошло наопако.
+Tax Master,Пореска Мастер
+To Pay,То Паи
+Updated,Ажурирано
+You are not allowed to reply to this ticket.,Нисте дозвољено да одговори на ову карту .
+You need to be logged in to view your cart.,Морате бити пријављени да бисте видели вашу корпу.
+You need to enable Shopping Cart,Вам необходимо включить Корзина
+{0} cannot be purchased using Shopping Cart,{0} не может быть приобретен с помощью Корзина
+{0} is required,{0} требуется
+{0} {1} has a common territory {2},{0} {1} имеет общую территорию {2}
diff --git a/erpnext/translations/ta.csv b/erpnext/translations/ta.csv
index c32864b..7717a7f 100644
--- a/erpnext/translations/ta.csv
+++ b/erpnext/translations/ta.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} நிலையை ஐபோனில் இருக்கிறது
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: செலவு மையம் பொருள் கட்டாய {2}
{0}: {1} not found in Invoice Details table,{0} {1} விலைப்பட்டியல் விவரம் அட்டவணையில் இல்லை
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","மிக href=""#Sales Browser/Customer Group""> சேர் / திருத்து </ a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","மிக href=""#Sales Browser/Territory""> சேர் / திருத்து </ a>"
+Billed,கட்டணம்
+Company,நிறுவனம்
+Currency is required for Price List {0},நாணய விலை பட்டியல் தேவை {0}
+Default Customer Group,முன்னிருப்பு வாடிக்கையாளர் பிரிவு
+Default Territory,முன்னிருப்பு மண்டலம்
+Delivered,வழங்கினார்
+Enable Shopping Cart,வணிக வண்டியில் செயல்படுத்த
+Go ahead and add something to your cart.,முன்னோக்கி சென்று உங்கள் வண்டி ஒன்று சேர்க்க.
+Hey! Go ahead and add an address,ஏய்! போய் ஒரு முகவரியை சேர்க்க
+Invalid Billing Address,தவறான பில்லிங் முகவரி
+Invalid Shipping Address,செல்லாத கப்பல் முகவரி
+Missing Currency Exchange Rates for {0},ஐந்து நாணய மாற்று விகிதங்கள் காணவில்லை {0}
+Name is required,பெயர் தேவை
+Not Allowed,அனுமதி இல்லை
+Paid,பணம்
+Partially Billed,பகுதி கூறப்படுவது
+Partially Delivered,பகுதியளவு வழங்கப்படுகிறது
+Please specify a Price List which is valid for Territory,மண்டலம் செல்லுபடியாகும் ஒரு விலை பட்டியல் குறிப்பிடவும்
+Please specify currency in Company,நிறுவனத்தின் நாணய குறிப்பிடவும்
+Please write something,ஏதாவது எழுத கொள்ளவும்
+Please write something in subject and message!,பொருள் மற்றும் செய்தி ஏதாவது எழுத கொள்ளவும் !
+Price List,விலை பட்டியல்
+Price List not configured.,விலை பட்டியல் கட்டமைக்கப்பட்ட.
+Quotation Series,மேற்கோள் தொடர்
+Shipping Rule,கப்பல் விதி
+Shopping Cart,வணிக வண்டி
+Shopping Cart Price List,வணிக வண்டியில் விலை பட்டியல்
+Shopping Cart Price Lists,வணிக வண்டியில் விலை பட்டியல்கள்
+Shopping Cart Settings,வணிக வண்டியில் அமைப்புகள்
+Shopping Cart Shipping Rule,வணிக வண்டியில் கப்பல் போக்குவரத்து விதி
+Shopping Cart Shipping Rules,வணிக வண்டியில் கப்பல் போக்குவரத்து விதிகள்
+Shopping Cart Taxes and Charges Master,வணிக வண்டியில் வரிகள் மற்றும் கட்டணங்கள் மாஸ்டர்
+Shopping Cart Taxes and Charges Masters,வணிக வண்டியில் வரிகள் மற்றும் கட்டணங்கள் முதுநிலை
+Something went wrong!,ஏதோ தவறு!
+Something went wrong.,ஏதோ தவறு நடந்துவிட்டது.
+Tax Master,வரி மாஸ்டர்
+To Pay,பணம்
+Updated,புதுப்பிக்கப்பட்ட
+You are not allowed to reply to this ticket.,இந்த டிக்கெட் பதில் அனுமதி இல்லை .
+You need to be logged in to view your cart.,உங்கள் வண்டி பார்வையிட உள்நுழைந்திருக்க வேண்டும்.
+You need to enable Shopping Cart,வணிக வண்டியில் செயல்படுத்த வேண்டும்
+{0} cannot be purchased using Shopping Cart,{0} வணிக வண்டியில் பயன்படுத்தி வாங்க முடியாது
+{0} is required,{0} தேவைப்படுகிறது
+{0} {1} has a common territory {2},{0} {1} ஒரு பொதுவான பகுதியில் உள்ளது {2}
diff --git a/erpnext/translations/th.csv b/erpnext/translations/th.csv
index 8043eca..7f59ef7 100644
--- a/erpnext/translations/th.csv
+++ b/erpnext/translations/th.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} สถานะ เบิก
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: ศูนย์ต้นทุนจำเป็นสำหรับรายการ {2}
{0}: {1} not found in Invoice Details table,{0}: {1} ไม่พบในตารางรายละเอียดใบแจ้งหนี้
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> เพิ่ม / แก้ไข </ a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> เพิ่ม / แก้ไข </ a>"
+Billed,เรียกเก็บเงิน
+Company,บริษัท
+Currency is required for Price List {0},สกุลเงิน เป็นสิ่งจำเป็นสำหรับ ราคาตามรายการ {0}
+Default Customer Group,กลุ่มลูกค้าเริ่มต้น
+Default Territory,ดินแดนเริ่มต้น
+Delivered,ส่ง
+Enable Shopping Cart,เปิดใช้งานรถเข็น
+Go ahead and add something to your cart.,ไปข้างหน้าและเพิ่มสิ่งที่รถเข็นของคุณ
+Hey! Go ahead and add an address,นี่ ไปข้างหน้าและเพิ่มที่อยู่
+Invalid Billing Address,ที่อยู่ การเรียกเก็บเงิน ไม่ถูกต้อง
+Invalid Shipping Address,ที่อยู่ ในการจัดส่ง ที่ไม่ถูกต้อง
+Missing Currency Exchange Rates for {0},หายไป สกุลเงิน อัตราแลกเปลี่ยน เพื่อ {0}
+Name is required,ชื่อจะต้อง
+Not Allowed,ไม่อนุญาตให้
+Paid,ต้องจ่าย
+Partially Billed,ในจำนวน บางส่วน
+Partially Delivered,ส่ง บางส่วน
+Please specify a Price List which is valid for Territory,โปรดระบุรายชื่อราคาที่ถูกต้องสำหรับดินแดน
+Please specify currency in Company,โปรดระบุสกุลเงินใน บริษัท
+Please write something,กรุณาเขียน บางสิ่งบางอย่าง
+Please write something in subject and message!,กรุณาเขียน อะไรบางอย่างใน เรื่อง และ ข้อความ !
+Price List,บัญชีแจ้งราคาสินค้า
+Price List not configured.,ราคาไม่ได้กำหนดค่า
+Quotation Series,ชุดใบเสนอราคา
+Shipping Rule,กฎการจัดส่งสินค้า
+Shopping Cart,รถเข็นช้อปปิ้ง
+Shopping Cart Price List,รายการสินค้าราคาสินค้าในรถเข็น
+Shopping Cart Price Lists,ช้อปปิ้งสินค้าราคา Lists
+Shopping Cart Settings,การตั้งค่ารถเข็น
+Shopping Cart Shipping Rule,ช้อปปิ้งรถเข็นกฎการจัดส่งสินค้า
+Shopping Cart Shipping Rules,รถเข็นกฎการจัดส่งสินค้า
+Shopping Cart Taxes and Charges Master,ภาษีรถเข็นและปริญญาโทค่าใช้จ่าย
+Shopping Cart Taxes and Charges Masters,ภาษีรถเข็นช้อปปิ้งและปริญญาโทค่าใช้จ่าย
+Something went wrong!,สิ่งที่ผิดพลาด!
+Something went wrong.,สิ่งที่ผิดพลาด
+Tax Master,ปริญญาโทภาษี
+To Pay,การชำระเงิน
+Updated,อัพเดต
+You are not allowed to reply to this ticket.,คุณยังไม่ได้ รับอนุญาตให้ ตอบกลับ ตั๋ว นี้
+You need to be logged in to view your cart.,คุณต้องเข้าสู่ระบบเพื่อดูรถเข็นของคุณ
+You need to enable Shopping Cart,คุณต้อง เปิดการใช้งาน รถเข็น
+{0} cannot be purchased using Shopping Cart,{0} ไม่สามารถ ซื้อโดยใช้ รถเข็น
+{0} is required,{0} จะต้อง
+{0} {1} has a common territory {2},{0} {1} มีดินแดน ที่พบบ่อย {2}
diff --git a/erpnext/translations/tr.csv b/erpnext/translations/tr.csv
index 174c03f..cf023dd 100644
--- a/erpnext/translations/tr.csv
+++ b/erpnext/translations/tr.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} durumu Unstopped olduğunu
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: Maliyet Merkezi Ürün için zorunludur {2}
{0}: {1} not found in Invoice Details table,{0}: {1} Fatura Ayrıntıları tablosunda bulunamadı
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group""> Ekle / Düzenle </ a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory""> Ekle / Düzenle </ a>"
+Billed,Faturalanmış
+Company,Şirket
+Currency is required for Price List {0},Döviz Fiyat Listesi için gereklidir {0}
+Default Customer Group,Varsayılan Müşteri Grubu
+Default Territory,Standart Bölge
+Delivered,Teslim Edildi
+Enable Shopping Cart,Alışveriş sepeti etkinleştirin
+Go ahead and add something to your cart.,Devam edin ve sepetinize şey eklemek.
+Hey! Go ahead and add an address,Hey! Devam edin ve bir adres eklemek
+Invalid Billing Address,Geçersiz Fatura Adresi
+Invalid Shipping Address,Geçersiz Teslimat Adresi
+Missing Currency Exchange Rates for {0},Döviz Kurların eksik {0}
+Name is required,Adı gerekli
+Not Allowed,İzin Verilmedi
+Paid,Ödendi
+Partially Billed,Kısmen Faturalı
+Partially Delivered,Kısmen Teslim
+Please specify a Price List which is valid for Territory,Territory için geçerli olan bir Fiyat Listesi belirtin
+Please specify currency in Company,Şirket para birimi belirtiniz
+Please write something,Bir şeyler yazınız
+Please write something in subject and message!,Konu ve mesaj bir şeyler yazınız!
+Price List,Fiyat listesi
+Price List not configured.,Fiyat Listesi yapılandırılmamış.
+Quotation Series,Teklif Serisi
+Shipping Rule,Kargo Kural
+Shopping Cart,Alışveriş Sepeti
+Shopping Cart Price List,Alışveriş Sepeti Fiyat Listesi
+Shopping Cart Price Lists,Alışveriş Sepeti Fiyat Listeleri
+Shopping Cart Settings,Alışveriş sepeti Ayarları
+Shopping Cart Shipping Rule,Alışveriş Sepeti Kargo Kural
+Shopping Cart Shipping Rules,Alışveriş Sepeti Nakliye Kuralları
+Shopping Cart Taxes and Charges Master,Alışveriş Sepeti Vergi ve Harçlar Usta
+Shopping Cart Taxes and Charges Masters,Alışveriş Sepeti Vergi ve Harçlar Masters
+Something went wrong!,Bir şeyler yanlış gitti!
+Something went wrong.,Bir şeyler yanlış gitti.
+Tax Master,Vergi Usta
+To Pay,Ödeme
+Updated,Güncellenmiş
+You are not allowed to reply to this ticket.,Bu bilet için cevap izin verilmez.
+You need to be logged in to view your cart.,Eğer sepeti görmek için oturum açmanız gerekir.
+You need to enable Shopping Cart,Sen Alışveriş Sepeti etkinleştirmeniz gerekir
+{0} cannot be purchased using Shopping Cart,{0} sepeti kullanarak satın alınamaz
+{0} is required,{0} gereklidir
+{0} {1} has a common territory {2},"{0} {1}, ortak bir bölge var {2}"
diff --git a/erpnext/translations/vi.csv b/erpnext/translations/vi.csv
index 3e714f5..ab272e9 100644
--- a/erpnext/translations/vi.csv
+++ b/erpnext/translations/vi.csv
@@ -3329,3 +3329,49 @@
{0} {1} status is Unstopped,{0} {1} tình trạng là Unstopped
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}: Trung tâm chi phí là bắt buộc đối với hàng {2}
{0}: {1} not found in Invoice Details table,{0}: {1} không tìm thấy trong hóa đơn chi tiết bảng
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>",{0} là cần thiết
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>",Tiền tệ là cần thiết cho Giá liệt kê {0}
+Billed,Một cái gì đó đã đi sai!
+Company,Giỏ hàng Giá liệt kê
+Currency is required for Price List {0},Danh sách giá
+Default Customer Group,Xin vui lòng viết một cái gì đó trong chủ đề và thông điệp!
+Default Territory,Vui lòng ghi rõ tiền tệ tại Công ty
+Delivered,"Nếu được chỉ định, gửi các bản tin sử dụng địa chỉ email này"
+Enable Shopping Cart,Dòng báo giá
+Go ahead and add something to your cart.,Được quảng cáo một phần
+Hey! Go ahead and add an address,Một cái gì đó đã đi sai.
+Invalid Billing Address,Thuế Thạc sĩ
+Invalid Shipping Address,Để trả tiền
+Missing Currency Exchange Rates for {0},Quy tắc vận chuyển
+Name is required,{0} không thể mua được bằng Giỏ hàng
+Not Allowed,Giỏ hàng Thuế và phí Thạc sĩ
+Paid,Quy định vận chuyển Giỏ hàng
+Partially Billed,Bạn cần phải kích hoạt Giỏ hàng
+Partially Delivered,Địa chỉ thanh toán không hợp lệ
+Please specify a Price List which is valid for Territory,Mặc định Territory
+Please specify currency in Company,Giỏ hàng Vận chuyển Rule
+Please write something,Giỏ hàng Chức năng Giá
+Please write something in subject and message!,{0} {1} có một lãnh thổ chung {2}
+Price List,"<a href=""#Sales Browser/Customer Group""> Add / Edit </ a>"
+Price List not configured.,Một phần Giao
+Quotation Series,Giỏ hàng Thuế và phí Masters
+Shipping Rule,Này ! Đi trước và thêm một địa chỉ
+Shopping Cart,"<a href=""#Sales Browser/Territory""> Add / Edit </ a>"
+Shopping Cart Price List,Đã cập nhật
+Shopping Cart Price Lists,Danh sách giá không được cấu hình.
+Shopping Cart Settings,Mặc định khách hàng Nhóm
+Shopping Cart Shipping Rule,Bạn cần phải đăng nhập để xem giỏ hàng của bạn.
+Shopping Cart Shipping Rules,Không phép
+Shopping Cart Taxes and Charges Master,Công ty
+Shopping Cart Taxes and Charges Masters,Địa chỉ Vận chuyển không hợp lệ
+Something went wrong!,Bạn không được phép trả lời vé này.
+Something went wrong.,Đi trước và thêm một cái gì đó vào giỏ hàng của bạn.
+Tax Master,Giao
+To Pay,Thanh toán
+Updated,Xin vui lòng viết một cái gì đó
+You are not allowed to reply to this ticket.,Vui lòng xác định Bảng giá có giá trị trong lãnh thổ
+You need to be logged in to view your cart.,Giỏ hàng
+You need to enable Shopping Cart,Giỏ hàng mua sắm thiết lập
+{0} cannot be purchased using Shopping Cart,Lập hóa đơn
+{0} is required,Cho phép Giỏ hàng
+{0} {1} has a common territory {2},Yêu cầu nhập tên
diff --git a/erpnext/translations/zh-cn.csv b/erpnext/translations/zh-cn.csv
index faef822..36a4473 100644
--- a/erpnext/translations/zh-cn.csv
+++ b/erpnext/translations/zh-cn.csv
@@ -3377,3 +3377,49 @@
{0} {1} status is Unstopped,{0} {1}状态为开通
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}:成本中心是强制性的项目{2}
{0}: {1} not found in Invoice Details table,{0}:{1}不是在发票明细表中找到
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group"">添加/编辑</a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory"">添加/编辑</a>"
+Billed,计费
+Company,公司
+Currency is required for Price List {0},货币需要价格表{0}
+Default Customer Group,默认用户组
+Default Territory,默认领地
+Delivered,交付
+Enable Shopping Cart,启用的购物车
+Go ahead and add something to your cart.,来吧,讲一下你的车。
+Hey! Go ahead and add an address,嘿!来吧,添加一个地址
+Invalid Billing Address,无效的帐单地址
+Invalid Shipping Address,无效的送货地址
+Missing Currency Exchange Rates for {0},缺少货币汇率的{0}
+Name is required,名称是必需的
+Not Allowed,不允许
+Paid,支付
+Partially Billed,部分帐单
+Partially Delivered,部分交付
+Please specify a Price List which is valid for Territory,请指定一个价格表,有效期为领地
+Please specify currency in Company,请公司指定的货币
+Please write something,请写东西
+Please write something in subject and message!,请写东西的主题和消息!
+Price List,价格表
+Price List not configured.,未配置价格表。
+Quotation Series,系列报价
+Shipping Rule,送货规则
+Shopping Cart,购物车
+Shopping Cart Price List,购物车价格表
+Shopping Cart Price Lists,购物车价目表
+Shopping Cart Settings,购物车设置
+Shopping Cart Shipping Rule,购物车运费规则
+Shopping Cart Shipping Rules,购物车运费规则
+Shopping Cart Taxes and Charges Master,购物车税收和收费硕士
+Shopping Cart Taxes and Charges Masters,购物车税收和收费硕士
+Something went wrong!,出事了!
+Something went wrong.,出事了。
+Tax Master,税务硕士
+To Pay,支付方式
+Updated,更新
+You are not allowed to reply to this ticket.,你不允许回复此票。
+You need to be logged in to view your cart.,您需要登录才能查看您的购物车。
+You need to enable Shopping Cart,您需要启用的购物车
+{0} cannot be purchased using Shopping Cart,{0}不能使用购物车购买
+{0} is required,{0}是必需的
+{0} {1} has a common territory {2},{0} {1}有一个共同的领土{2}
diff --git a/erpnext/translations/zh-tw.csv b/erpnext/translations/zh-tw.csv
index 29522e6..609806b 100644
--- a/erpnext/translations/zh-tw.csv
+++ b/erpnext/translations/zh-tw.csv
@@ -3377,3 +3377,49 @@
{0} {1} status is Unstopped,{0} {1}狀態為開通
{0} {1}: Cost Center is mandatory for Item {2},{0} {1}:成本中心是強制性的項目{2}
{0}: {1} not found in Invoice Details table,{0}:{1}不是在發票明細表中找到
+"<a href=""#Sales Browser/Customer Group"">Add / Edit</a>","<a href=""#Sales Browser/Customer Group"">添加/編輯</a>"
+"<a href=""#Sales Browser/Territory"">Add / Edit</a>","<a href=""#Sales Browser/Territory"">添加/編輯</a>"
+Billed,計費
+Company,公司
+Currency is required for Price List {0},貨幣需要價格表{0}
+Default Customer Group,默認用戶組
+Default Territory,默認領地
+Delivered,交付
+Enable Shopping Cart,啟用的購物車
+Go ahead and add something to your cart.,來吧,講一下你的車。
+Hey! Go ahead and add an address,嘿!來吧,添加一個地址
+Invalid Billing Address,無效的帳單地址
+Invalid Shipping Address,無效的送貨地址
+Missing Currency Exchange Rates for {0},缺少貨幣匯率的{0}
+Name is required,名稱是必需的
+Not Allowed,不允許
+Paid,支付
+Partially Billed,部分帳單
+Partially Delivered,部分交付
+Please specify a Price List which is valid for Territory,請指定一個價格表,有效期為領地
+Please specify currency in Company,請公司指定的貨幣
+Please write something,請寫東西
+Please write something in subject and message!,請寫東西的主題和消息!
+Price List,價格表
+Price List not configured.,未配置價格表。
+Quotation Series,系列報價
+Shipping Rule,送貨規則
+Shopping Cart,購物車
+Shopping Cart Price List,購物車價格表
+Shopping Cart Price Lists,購物車價目表
+Shopping Cart Settings,購物車設置
+Shopping Cart Shipping Rule,購物車運費規則
+Shopping Cart Shipping Rules,購物車運費規則
+Shopping Cart Taxes and Charges Master,購物車稅收和收費碩士
+Shopping Cart Taxes and Charges Masters,購物車稅收和收費碩士
+Something went wrong!,出事了!
+Something went wrong.,出事了。
+Tax Master,稅務碩士
+To Pay,支付方式
+Updated,更新
+You are not allowed to reply to this ticket.,你不允許回复此票。
+You need to be logged in to view your cart.,您需要登錄才能查看您的購物車。
+You need to enable Shopping Cart,您需要啟用的購物車
+{0} cannot be purchased using Shopping Cart,{0}不能使用購物車購買
+{0} is required,{0}是必需的
+{0} {1} has a common territory {2},{0} {1}有一個共同的領土{2}