Merge remote-tracking branch 'frappe/develop' into wip-4.1
diff --git a/erpnext/accounts/doctype/account/account.json b/erpnext/accounts/doctype/account/account.json
index 4c24199..f909ef6 100644
--- a/erpnext/accounts/doctype/account/account.json
+++ b/erpnext/accounts/doctype/account/account.json
@@ -288,6 +288,7 @@
},
{
"amend": 0,
+ "apply_user_permissions": 0,
"create": 1,
"delete": 1,
"email": 1,
diff --git a/erpnext/accounts/doctype/chart_of_accounts/import_charts.py b/erpnext/accounts/doctype/chart_of_accounts/import_charts.py
index 9e60551..7a47f6e 100644
--- a/erpnext/accounts/doctype/chart_of_accounts/import_charts.py
+++ b/erpnext/accounts/doctype/chart_of_accounts/import_charts.py
@@ -5,6 +5,7 @@
import frappe, os, json
def import_charts():
+ print "Importing Chart of Accounts"
frappe.db.sql("""delete from `tabChart of Accounts`""")
charts_dir = os.path.join(os.path.dirname(__file__), "charts")
for fname in os.listdir(charts_dir):
@@ -19,8 +20,8 @@
"source_file": fname,
"country": country
}).insert()
- print doc.name.encode("utf-8")
- else:
- print "No chart for: " + chart.get("name").encode("utf-8")
-
- frappe.db.commit()
\ No newline at end of file
+ #print doc.name.encode("utf-8")
+ #else:
+ #print "No chart for: " + chart.get("name").encode("utf-8")
+
+ frappe.db.commit()
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.html b/erpnext/accounts/report/general_ledger/general_ledger.html
new file mode 100644
index 0000000..dda1e61
--- /dev/null
+++ b/erpnext/accounts/report/general_ledger/general_ledger.html
@@ -0,0 +1,38 @@
+<h2 class="text-center">{%= __("Statement of Account") %}</h2>
+<h4 class="text-center">{%= filters.account || "General Ledger" %}</h3>
+<hr>
+<table class="table table-bordered">
+ <thead>
+ <tr>
+ <th style="width: 10%">{%= __("Date") %}</th>
+ <th style="width: 15%">{%= __("Ref") %}</th>
+ <th style="width: 45%">{%= __("Party") %}</th>
+ <th style="width: 15%">{%= __("Debit") %}</th>
+ <th style="width: 15%">{%= __("Credit") %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for(var i=0, l=data.length; i<l; i++) { %}
+ <tr>
+ {% if(data[i].posting_date) { %}
+ <td>{%= dateutil.str_to_user(data[i].posting_date) %}</td>
+ <td>{%= data[i].voucher_no %}</td>
+ <td>{%= data[i].account %}
+ <br>{%= __("Against") %}: {%= data[i].account %}
+ <br>{%= __("Remarks") %}: {%= data[i].remarks %}</td>
+ <td style="text-align: right">{%= fmt_money(data[i].debit) %}</td>
+ <td style="text-align: right">{%= fmt_money(data[i].credit) %}</td>
+ {% } else { %}
+ <td></td>
+ <td></td>
+ <td><b>{%= data[i].account || " " %}</b></td>
+ <td style="text-align: right">
+ {%= data[i].account && fmt_money(data[i].debit) %}</td>
+ <td style="text-align: right">
+ {%= data[i].account && fmt_money(data[i].credit) %}</td>
+ {% } %}
+ </tr>
+ {% } %}
+ </tbody>
+</table>
+<p class="text-right text-muted">Printed On {%= dateutil.get_datetime_as_string() %}</p>
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 8b147b0..1dde638 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -19,11 +19,11 @@
dump_report_map = "erpnext.startup.report_data_map.data_map"
update_website_context = "erpnext.startup.webutils.update_website_context"
-mail_footer = "erpnext.startup.mail_footer"
-
on_session_creation = "erpnext.startup.event_handlers.on_session_creation"
before_tests = "erpnext.setup.utils.before_tests"
+website_generators = ["Item Group", "Item", "Sales Partner"]
+
standard_queries = "Customer:erpnext.selling.doctype.customer.customer.get_customer_list"
permission_query_conditions = {
@@ -74,3 +74,4 @@
"erpnext.setup.doctype.backup_manager.backup_manager.take_backups_weekly"
]
}
+
diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py
index 63bf3b4..94cd3ec 100644
--- a/erpnext/setup/doctype/item_group/item_group.py
+++ b/erpnext/setup/doctype/item_group/item_group.py
@@ -7,6 +7,10 @@
from frappe.utils.nestedset import NestedSet
from frappe.website.website_generator import WebsiteGenerator
from frappe.website.render import clear_cache
+from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow
+
+condition_field = "show_in_website"
+template = "templates/generators/item_group.html"
class ItemGroup(NestedSet, WebsiteGenerator):
nsm_parent_field = 'parent_item_group'
@@ -39,6 +43,53 @@
if frappe.db.exists("Item", self.name):
frappe.throw(frappe._("An item exists with same name ({0}), please change the item group name or rename the item").format(self.name))
+ def get_context(self, context):
+ context.update({
+ "items": get_product_list_for_group(product_group = self.name, limit=100),
+ "parent_groups": get_parent_item_groups(self.name),
+ "title": self.name
+ })
+
+ if self.slideshow:
+ context.update(get_slideshow(self))
+
+ return context
+
+def get_product_list_for_group(product_group=None, start=0, limit=10):
+ child_groups = ", ".join(['"' + i[0] + '"' for i in get_child_groups(product_group)])
+
+ # base query
+ query = """select t1.name, t1.item_name, t1.page_name, t1.website_image, t1.item_group,
+ t1.web_long_description as website_description, t2.name as route
+ from `tabItem` t1, `tabWebsite Route` t2
+ where t1.show_in_website = 1 and (item_group in (%s)
+ or t1.name in (select parent from `tabWebsite Item Group` where item_group in (%s)))
+ and t1.name = t2.docname and t2.ref_doctype='Item' """ % (child_groups, child_groups)
+
+ query += """order by t1.weightage desc, t1.modified desc limit %s, %s""" % (start, limit)
+
+ data = frappe.db.sql(query, {"product_group": product_group}, as_dict=1)
+
+ return [get_item_for_list_in_html(r) for r in data]
+
+def get_child_groups(item_group_name):
+ item_group = frappe.get_doc("Item Group", item_group_name)
+ return frappe.db.sql("""select name
+ from `tabItem Group` where lft>=%(lft)s and rgt<=%(rgt)s
+ and show_in_website = 1""", {"lft": item_group.lft, "rgt": item_group.rgt})
+
+def get_item_for_list_in_html(context):
+ return frappe.get_template("templates/includes/product_in_grid.html").render(context)
+
+def get_group_item_count(item_group):
+ child_groups = ", ".join(['"' + i[0] + '"' for i in get_child_groups(item_group)])
+ return frappe.db.sql("""select count(*) from `tabItem`
+ where docstatus = 0 and show_in_website = 1
+ and (item_group in (%s)
+ or name in (select parent from `tabWebsite Item Group`
+ where item_group in (%s))) """ % (child_groups, child_groups))[0][0]
+
+
def get_parent_item_groups(item_group_name):
item_group = frappe.get_doc("Item Group", item_group_name)
return frappe.db.sql("""select name, page_name from `tabItem Group`
diff --git a/erpnext/setup/doctype/sales_partner/sales_partner.py b/erpnext/setup/doctype/sales_partner/sales_partner.py
index b90b65e..6969519 100644
--- a/erpnext/setup/doctype/sales_partner/sales_partner.py
+++ b/erpnext/setup/doctype/sales_partner/sales_partner.py
@@ -3,9 +3,12 @@
from __future__ import unicode_literals
import frappe
-from frappe.utils import cint, cstr, filter_strip_join
+from frappe.utils import cstr, filter_strip_join
from frappe.website.website_generator import WebsiteGenerator
+condition_field = "show_in_website"
+template = "templates/generators/sales_partner.html"
+
class SalesPartner(WebsiteGenerator):
def autoname(self):
self.name = self.partner_name
@@ -25,3 +28,21 @@
def get_page_title(self):
return self.partner_name
+
+ def get_context(self, context):
+ address = frappe.db.get_value("Address",
+ {"sales_partner": self.name, "is_primary_address": 1},
+ "*", as_dict=True)
+ if address:
+ city_state = ", ".join(filter(None, [address.city, address.state]))
+ address_rows = [address.address_line1, address.address_line2,
+ city_state, address.pincode, address.country]
+
+ context.update({
+ "email": address.email_id,
+ "partner_address": filter_strip_join(address_rows, "\n<br>"),
+ "phone": filter_strip_join(cstr(address.phone).split(","), "\n<br>")
+ })
+
+ return context
+
diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py
index ba1dfb7..344a89e 100644
--- a/erpnext/setup/install.py
+++ b/erpnext/setup/install.py
@@ -7,6 +7,9 @@
from frappe import _
+default_mail_footer = """<div style="padding: 7px; text-align: right; color: #888"><small>Sent via
+ <a style="color: #888" href="http://erpnext.org">ERPNext</a></div>"""
+
def after_install():
frappe.get_doc({'doctype': "Role", "role_name": "Analytics"}).insert()
set_single_defaults()
@@ -79,3 +82,6 @@
pass
frappe.db.set_default("date_format", "dd-mm-yyyy")
+
+ frappe.db.set_value("Outgoing Email Settings", "Outgoing Email Settings", "footer",
+ default_mail_footer)
diff --git a/erpnext/startup/__init__.py b/erpnext/startup/__init__.py
index e20ece3..576ab05 100644
--- a/erpnext/startup/__init__.py
+++ b/erpnext/startup/__init__.py
@@ -27,10 +27,6 @@
"Territory": "territory"
}
-# add startup propertes
-mail_footer = """<div style="padding: 7px; text-align: right; color: #888"><small>Sent via
- <a style="color: #888" href="http://erpnext.org">ERPNext</a></div>"""
-
def get_monthly_bulk_mail_limit():
import frappe
# if global settings, then 500 or unlimited
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index f43b531..f68f0e9 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -6,11 +6,15 @@
from frappe import msgprint, _
from frappe.utils import cstr, flt, getdate, now_datetime, formatdate
from frappe.website.website_generator import WebsiteGenerator
-from erpnext.setup.doctype.item_group.item_group import invalidate_cache_for
+from erpnext.setup.doctype.item_group.item_group import invalidate_cache_for, get_parent_item_groups
from frappe.website.render import clear_cache
+from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow
class WarehouseNotSet(frappe.ValidationError): pass
+condition_field = "show_in_website"
+template = "templates/generators/item.html"
+
class Item(WebsiteGenerator):
def onload(self):
super(Item, self).onload()
@@ -55,6 +59,14 @@
self.validate_name_with_item_group()
self.update_item_price()
+ def get_context(self, context):
+ context["parent_groups"] = get_parent_item_groups(self.item_group) + \
+ [{"name": self.name}]
+ if self.slideshow:
+ context.update(get_slideshow(self))
+
+ return context
+
def check_warehouse_is_set_for_stock_item(self):
if self.is_stock_item=="Yes" and not self.default_warehouse:
frappe.msgprint(_("Default Warehouse is mandatory for stock Item."),
diff --git a/erpnext/templates/generators/item.py b/erpnext/templates/generators/item.py
deleted file mode 100644
index 1ad070e..0000000
--- a/erpnext/templates/generators/item.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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.setup.doctype.item_group.item_group import get_parent_item_groups
-from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow
-
-doctype = "Item"
-condition_field = "show_in_website"
-
-def get_context(context):
- item_context = context.doc.as_dict()
- item_context["parent_groups"] = get_parent_item_groups(context.doc.item_group) + \
- [{"name":context.doc.name}]
- if context.doc.slideshow:
- item_context.update(get_slideshow(context.doc))
-
- return item_context
diff --git a/erpnext/templates/generators/item_group.py b/erpnext/templates/generators/item_group.py
deleted file mode 100644
index 8e09dbc..0000000
--- a/erpnext/templates/generators/item_group.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# 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.website.doctype.website_slideshow.website_slideshow import get_slideshow
-from erpnext.setup.doctype.item_group.item_group import get_parent_item_groups
-
-doctype = "Item Group"
-condition_field = "show_in_website"
-
-def get_context(context):
- item_group_context = context.doc.as_dict()
- item_group_context.update({
- "items": get_product_list_for_group(product_group = context.docname, limit=100),
- "parent_groups": get_parent_item_groups(context.docname),
- "title": context.docname
- })
-
- if context.doc.slideshow:
- item_group_context.update(get_slideshow(context.doc))
-
- return item_group_context
-
-def get_product_list_for_group(product_group=None, start=0, limit=10):
- child_groups = ", ".join(['"' + i[0] + '"' for i in get_child_groups(product_group)])
-
- # base query
- query = """select t1.name, t1.item_name, t1.page_name, t1.website_image, t1.item_group,
- t1.web_long_description as website_description, t2.name as route
- from `tabItem` t1, `tabWebsite Route` t2
- where t1.show_in_website = 1 and (item_group in (%s)
- or t1.name in (select parent from `tabWebsite Item Group` where item_group in (%s)))
- and t1.name = t2.docname and t2.ref_doctype='Item' """ % (child_groups, child_groups)
-
- query += """order by t1.weightage desc, t1.modified desc limit %s, %s""" % (start, limit)
-
- data = frappe.db.sql(query, {"product_group": product_group}, as_dict=1)
-
- return [get_item_for_list_in_html(r) for r in data]
-
-def get_child_groups(item_group_name):
- item_group = frappe.get_doc("Item Group", item_group_name)
- return frappe.db.sql("""select name
- from `tabItem Group` where lft>=%(lft)s and rgt<=%(rgt)s
- and show_in_website = 1""", {"lft": item_group.lft, "rgt": item_group.rgt})
-
-def get_item_for_list_in_html(context):
- return frappe.get_template("templates/includes/product_in_grid.html").render(context)
-
-def get_group_item_count(item_group):
- child_groups = ", ".join(['"' + i[0] + '"' for i in get_child_groups(item_group)])
- return frappe.db.sql("""select count(*) from `tabItem`
- where docstatus = 0 and show_in_website = 1
- and (item_group in (%s)
- or name in (select parent from `tabWebsite Item Group`
- where item_group in (%s))) """ % (child_groups, child_groups))[0][0]
-
diff --git a/erpnext/templates/generators/partner.py b/erpnext/templates/generators/partner.py
deleted file mode 100644
index 2079309..0000000
--- a/erpnext/templates/generators/partner.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# 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 filter_strip_join
-
-doctype = "Sales Partner"
-condition_field = "show_in_website"
-
-def get_context(context):
- partner_context = context.doc.as_dict()
-
- address = frappe.db.get_value("Address",
- {"sales_partner": context.doc.name, "is_primary_address": 1},
- "*", as_dict=True)
- if address:
- city_state = ", ".join(filter(None, [address.city, address.state]))
- address_rows = [address.address_line1, address.address_line2,
- city_state, address.pincode, address.country]
-
- partner_context.update({
- "email": address.email_id,
- "partner_address": filter_strip_join(address_rows, "\n<br>"),
- "phone": filter_strip_join(cstr(address.phone).split(","), "\n<br>")
- })
-
- return partner_context
diff --git a/erpnext/templates/includes/footer_powered.html b/erpnext/templates/includes/footer_powered.html
index 0abf2e4..9661181 100644
--- a/erpnext/templates/includes/footer_powered.html
+++ b/erpnext/templates/includes/footer_powered.html
@@ -1 +1 @@
-<a href="http://erpnext.org" style="color: #aaa;">ERPNext Powered</a>
\ No newline at end of file
+<a href="http://erpnext.com" style="color: #aaa; font-size: 11px;">ERPNext Powered</a>
diff --git a/erpnext/templates/pages/product_search.py b/erpnext/templates/pages/product_search.py
index 8b454ce..8464b25 100644
--- a/erpnext/templates/pages/product_search.py
+++ b/erpnext/templates/pages/product_search.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr
-from erpnext.templates.generators.item_group import get_item_for_list_in_html
+from erpnext.setup.doctype.item_group.item_group import get_item_for_list_in_html
no_cache = 1
no_sitemap = 1