Merge pull request #1382 from akhileshdarjee/4.0-hotfix
Newsletter can also be sent to employees
diff --git a/.travis.yml b/.travis.yml
index ee64b6d..41ba344 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,4 @@
-anguage: python
+language: python
python:
- "2.7"
@@ -7,7 +7,7 @@
- mysql
install:
- - pip install https://github.com/webnotes/wnframework/archive/4.0.0-wip.tar.gz &&
+ - pip install git+https://github.com/webnotes/wnframework.git@4.0.0-wip &&
- pip install --editable .
script:
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index 19fda8e..9fa972d 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -113,9 +113,8 @@
if not hasattr(self, "account_map"):
self.account_map = dict(((r.name, r) for r in webnotes.conn.sql("""select
acc.name, cust.name as customer, cust.customer_name, cust.territory
- from `tabAccount` acc, `tabCustomer` cust
- where acc.master_type="Customer"
- and cust.name=acc.master_name""", as_dict=True)))
+ from `tabAccount` acc left join `tabCustomer` cust
+ on cust.name=acc.master_name where acc.master_type="Customer" """, as_dict=True)))
return self.account_map
@@ -134,7 +133,6 @@
self.gl_entries = webnotes.conn.sql("""select * from `tabGL Entry`
where docstatus < 2 {0} order by posting_date, account""".format(conditions),
values, as_dict=True)
-
return self.gl_entries
def prepare_conditions(self):
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 941c2ae..495284a 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -355,20 +355,23 @@
and fiscal_year='%(fiscal_year)s' and company='%(company)s' %(condition)s
""" % (args))[0][0]
-def rename_account_for(dt, olddn, newdn, merge):
+def rename_account_for(dt, olddn, newdn, merge, company):
old_account = get_account_for(dt, olddn)
if old_account:
new_account = None
if not merge:
- if old_account == olddn:
- new_account = webnotes.rename_doc("Account", olddn, newdn)
+ if old_account == add_abbr_if_missing(olddn, company):
+ new_account = webnotes.rename_doc("Account", old_account, newdn)
else:
existing_new_account = get_account_for(dt, newdn)
new_account = webnotes.rename_doc("Account", old_account,
existing_new_account or newdn, merge=True if existing_new_account else False)
- if new_account:
- webnotes.conn.set_value("Account", new_account, "master_name", newdn)
+ webnotes.conn.set_value("Account", new_account or old_account, "master_name", newdn)
+
+def add_abbr_if_missing(dn, company):
+ from setup.doctype.company.company import get_name_with_abbr
+ return get_name_with_abbr(dn, company)
def get_account_for(account_for_doctype, account_for):
if account_for_doctype in ["Customer", "Supplier"]:
diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.py b/erpnext/buying/doctype/purchase_common/purchase_common.py
index d967b24..2ec67fd 100644
--- a/erpnext/buying/doctype/purchase_common/purchase_common.py
+++ b/erpnext/buying/doctype/purchase_common/purchase_common.py
@@ -93,7 +93,7 @@
if not item:
webnotes.throw("Item %s does not exist in Item Master." % cstr(d.item_code))
- from erpnext.stock.utils import validate_end_of_life
+ from erpnext.stock.doctype.item.item import validate_end_of_life
validate_end_of_life(d.item_code, item[0][3])
# validate stock item
diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py
index 9fe52c8..94a16f5 100644
--- a/erpnext/buying/doctype/supplier/supplier.py
+++ b/erpnext/buying/doctype/supplier/supplier.py
@@ -92,7 +92,7 @@
def before_rename(self, olddn, newdn, merge=False):
from erpnext.accounts.utils import rename_account_for
- rename_account_for("Supplier", olddn, newdn, merge)
+ rename_account_for("Supplier", olddn, newdn, merge, self.doc.company)
def after_rename(self, olddn, newdn, merge=False):
set_field = ''
@@ -126,5 +126,4 @@
out["total_billing"] = billing[0][0]
out["total_unpaid"] = billing[0][1]
- return out
-
\ No newline at end of file
+ return out
\ No newline at end of file
diff --git a/erpnext/home/__init__.py b/erpnext/home/__init__.py
index e092a71..f809dde 100644
--- a/erpnext/home/__init__.py
+++ b/erpnext/home/__init__.py
@@ -82,9 +82,9 @@
f.full_name = get_fullname(owner)
f.save()
-def update_feed(controller, method=None):
+def update_feed(bean, method=None):
"adds a new feed"
- doc = controller.doc
+ doc = bean.doc
if method in ['on_update', 'on_submit']:
subject, color = feed_dict.get(doc.doctype, [None, None])
if subject:
diff --git a/erpnext/hooks.txt b/erpnext/hooks.txt
index a52ea2d..23e0c0f 100644
--- a/erpnext/hooks.txt
+++ b/erpnext/hooks.txt
@@ -22,19 +22,19 @@
on_session_creation = erpnext.startup.event_handlers.on_session_creation
-# Boot Events
+# Bean Events
# -------------------------
-bean_event = *:on_update:erpnext.home.update_feed
-bean_event = *:on_submit:erpnext.home.update_feed
-bean_event = Comment:on_update:erpnext.home.make_comment_feed
+bean_event:*:on_update = erpnext.home.update_feed
+bean_event:*:on_submit = erpnext.home.update_feed
+bean_event:Comment:on_update = erpnext.home.make_comment_feed
-bean_event = *:on_update:webnotes.core.doctype.notification_count.notification_count.clear_doctype_notifications
-bean_event = *:on_cancel:webnotes.core.doctype.notification_count.notification_count.clear_doctype_notifications
-bean_event = *:on_trash:webnotes.core.doctype.notification_count.notification_count.clear_doctype_notifications
+bean_event:*:on_update = webnotes.core.doctype.notification_count.notification_count.clear_doctype_notifications
+bean_event:*:on_cancel = webnotes.core.doctype.notification_count.notification_count.clear_doctype_notifications
+bean_event:*:on_trash = webnotes.core.doctype.notification_count.notification_count.clear_doctype_notifications
-bean_event = Stock Entry:on_submit:erpnext.stock.doctype.material_request.material_request.update_completed_qty
-bean_event = Stock Entry:on_cancel:erpnext.stock.doctype.material_request.material_request.update_completed_qty
+bean_event:Stock Entry:on_submit = erpnext.stock.doctype.material_request.material_request.update_completed_qty
+bean_event:Stock Entry:on_cancel = erpnext.stock.doctype.material_request.material_request.update_completed_qty
standard_queries = Customer:erpnext.selling.utils.get_customer_list
diff --git a/patches/1401/fix_planned_qty.py b/erpnext/patches/1401/fix_planned_qty.py
similarity index 100%
rename from patches/1401/fix_planned_qty.py
rename to erpnext/patches/1401/fix_planned_qty.py
diff --git a/patches/1401/fix_serial_no_status_and_warehouse.py b/erpnext/patches/1401/fix_serial_no_status_and_warehouse.py
similarity index 100%
rename from patches/1401/fix_serial_no_status_and_warehouse.py
rename to erpnext/patches/1401/fix_serial_no_status_and_warehouse.py
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 85d8a49..a811562 100644
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -16,11 +16,10 @@
self.doclist = doclist
def get_project_details(self):
- cust = webnotes.conn.sql("select customer, customer_name from `tabProject` where name = %s", self.doc.project)
- if cust:
- ret = {'customer': cust and cust[0][0] or '', 'customer_name': cust and cust[0][1] or ''}
- return ret
-
+ return {
+ "project": self.doc.project
+ }
+
def get_customer_details(self):
cust = webnotes.conn.sql("select customer_name from `tabCustomer` where name=%s", self.doc.customer)
if cust:
diff --git a/erpnext/public/build.json b/erpnext/public/build.json
index d089178..7c049ab 100644
--- a/erpnext/public/build.json
+++ b/erpnext/public/build.json
@@ -1,6 +1,6 @@
{
"css/erpnext.css": [
- "public/js/startup.css"
+ "public/css/erpnext.css"
],
"js/erpnext-web.min.js": [
"public/js/website_utils.js"
diff --git a/erpnext/public/js/startup.css b/erpnext/public/css/erpnext.css
similarity index 100%
rename from erpnext/public/js/startup.css
rename to erpnext/public/css/erpnext.css
diff --git a/erpnext/public/css/splash.css b/erpnext/public/css/splash.css
deleted file mode 100644
index 522c0b1..0000000
--- a/erpnext/public/css/splash.css
+++ /dev/null
@@ -1,52 +0,0 @@
-@-webkit-keyframes pulse {
- from {
- opacity: 0.7;
- }
-
- to {
- opacity: 1;
- }
-}
-
-@keyframes pulse {
- from {
- opacity: 0.7;
- }
-
- to {
- opacity: 1;
- }
-}
-
-
-.splash {
- margin: auto;
- position: absolute;
- top: 0px;
- left: 0px;
- right: 0px;
- bottom: 30px;
- width: 160px;
- height: 160px;
- text-align: center;
- color: #888;
-
- animation-duration: 1s;
- animation-name: pulse;
- animation-iteration-count: infinite;
- animation-direction: alternate;
-
- -webkit-animation-duration: 1s;
- -webkit-animation-name: pulse;
- -webkit-animation-iteration-count: infinite;
- -webkit-animation-direction: alternate;
-}
-
-.splash:after {
- content: "erpnext";
- font-size: 30px;
- font-weight: 300;
- font-family: Helvetica, Arial, sans-serif;
- position: relative;
- top: -30px;
-}
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index f51cd55..df17689 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -3,15 +3,12 @@
from __future__ import unicode_literals
import webnotes
-from webnotes.utils import cstr
from webnotes.model.doc import Document, make_autoname
from webnotes import msgprint, _
import webnotes.defaults
from erpnext.utilities.transaction_base import TransactionBase
-from erpnext.utilities.doctype.address.address import get_address_display
-from erpnext.utilities.doctype.contact.contact import get_contact_details
from erpnext.accounts.party import create_party_account
class DocType(TransactionBase):
@@ -128,7 +125,7 @@
def before_rename(self, olddn, newdn, merge=False):
from erpnext.accounts.utils import rename_account_for
- rename_account_for("Customer", olddn, newdn, merge)
+ rename_account_for("Customer", olddn, newdn, merge, self.doc.company)
def after_rename(self, olddn, newdn, merge=False):
set_field = ''
diff --git a/erpnext/selling/doctype/lead/get_leads.py b/erpnext/selling/doctype/lead/get_leads.py
index 898ee0e..ccb691c 100644
--- a/erpnext/selling/doctype/lead/get_leads.py
+++ b/erpnext/selling/doctype/lead/get_leads.py
@@ -5,7 +5,7 @@
import webnotes
from webnotes.utils import cstr, cint
from webnotes.utils.email_lib.receive import POP3Mailbox
-from webnotes.core.doctype.communication.communication import make
+from webnotes.core.doctype.communication.communication import _make
def add_sales_communication(subject, content, sender, real_name, mail=None,
status="Open", date=None):
@@ -28,7 +28,7 @@
parent_doctype = "Contact" if contact_name else "Lead"
parent_name = contact_name or lead_name
- message = make(content=content, sender=sender, subject=subject,
+ message = _make(content=content, sender=sender, subject=subject,
doctype = parent_doctype, name = parent_name, date=date, sent_or_received="Received")
if mail:
diff --git a/erpnext/setup/doctype/item_group/item_group.txt b/erpnext/setup/doctype/item_group/item_group.txt
index 71be225..953d7b8 100644
--- a/erpnext/setup/doctype/item_group/item_group.txt
+++ b/erpnext/setup/doctype/item_group/item_group.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-03-28 10:35:29",
"docstatus": 0,
- "modified": "2014-01-20 17:48:49",
+ "modified": "2014-02-05 17:36:23",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -113,6 +113,14 @@
},
{
"depends_on": "show_in_website",
+ "doctype": "DocField",
+ "fieldname": "parent_website_sitemap",
+ "fieldtype": "Link",
+ "label": "Parent Website Page",
+ "options": "Website Sitemap"
+ },
+ {
+ "depends_on": "show_in_website",
"description": "Show this slideshow at the top of the page",
"doctype": "DocField",
"fieldname": "slideshow",
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 16938b4..dcb6c0f 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -260,3 +260,47 @@
webnotes.conn.set_default("allow_negative_stock",
webnotes.conn.get_value("Stock Settings", None, "allow_negative_stock"))
webnotes.conn.auto_commit_on_many_writes = 0
+
+def validate_end_of_life(item_code, end_of_life=None, verbose=1):
+ if not end_of_life:
+ end_of_life = webnotes.conn.get_value("Item", item_code, "end_of_life")
+
+ from webnotes.utils import getdate, now_datetime, formatdate
+ if end_of_life and getdate(end_of_life) <= now_datetime().date():
+ msg = (_("Item") + " %(item_code)s: " + _("reached its end of life on") + \
+ " %(date)s. " + _("Please check") + ": %(end_of_life_label)s " + \
+ "in Item master") % {
+ "item_code": item_code,
+ "date": formatdate(end_of_life),
+ "end_of_life_label": webnotes.get_doctype("Item").get_label("end_of_life")
+ }
+
+ _msgprint(msg, verbose)
+
+def validate_is_stock_item(item_code, is_stock_item=None, verbose=1):
+ if not is_stock_item:
+ is_stock_item = webnotes.conn.get_value("Item", item_code, "is_stock_item")
+
+ if is_stock_item != "Yes":
+ msg = (_("Item") + " %(item_code)s: " + _("is not a Stock Item")) % {
+ "item_code": item_code,
+ }
+
+ _msgprint(msg, verbose)
+
+def validate_cancelled_item(item_code, docstatus=None, verbose=1):
+ if docstatus is None:
+ docstatus = webnotes.conn.get_value("Item", item_code, "docstatus")
+
+ if docstatus == 2:
+ msg = (_("Item") + " %(item_code)s: " + _("is a cancelled Item")) % {
+ "item_code": item_code,
+ }
+
+ _msgprint(msg, verbose)
+
+def _msgprint(msg, verbose):
+ if verbose:
+ msgprint(msg, raise_exception=True)
+ else:
+ raise webnotes.ValidationError, msg
\ No newline at end of file
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index d3262c5..4450af7 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -168,15 +168,13 @@
self.doc.per_ordered = flt((per_ordered / flt(len(item_doclist))) * 100.0, 2)
webnotes.conn.set_value(self.doc.doctype, self.doc.name, "per_ordered", self.doc.per_ordered)
-def update_completed_qty(controller, caller_method):
- if controller.doc.doctype == "Stock Entry":
+def update_completed_qty(bean, method):
+ if bean.doc.doctype == "Stock Entry":
material_request_map = {}
- for d in controller.doclist.get({"parentfield": "mtn_details"}):
+ for d in bean.doclist.get({"parentfield": "mtn_details"}):
if d.material_request:
- if d.material_request not in material_request_map:
- material_request_map[d.material_request] = []
- material_request_map[d.material_request].append(d.material_request_item)
+ material_request_map.setdefault(d.material_request, []).append(d.material_request_item)
for mr_name, mr_items in material_request_map.items():
mr_obj = webnotes.get_obj("Material Request", mr_name, with_children=1)
@@ -187,17 +185,17 @@
+ _(mr_doctype.get_label("status")) + " = %s. " % _(mr_obj.doc.status)
+ _("Cannot continue."), exc=webnotes.InvalidStatusError)
- _update_requested_qty(controller, mr_obj, mr_items)
+ _update_requested_qty(bean, mr_obj, mr_items)
# update ordered percentage and qty
mr_obj.update_completed_qty(mr_items)
-def _update_requested_qty(controller, mr_obj, mr_items):
+def _update_requested_qty(bean, mr_obj, mr_items):
"""update requested qty (before ordered_qty is updated)"""
from erpnext.stock.utils import update_bin
for mr_item_name in mr_items:
mr_item = mr_obj.doclist.getone({"parentfield": "indent_details", "name": mr_item_name})
- se_detail = controller.doclist.getone({"parentfield": "mtn_details",
+ se_detail = bean.doclist.getone({"parentfield": "mtn_details",
"material_request": mr_obj.doc.name, "material_request_item": mr_item_name})
mr_item.ordered_qty = flt(mr_item.ordered_qty)
@@ -217,7 +215,7 @@
"item_code": se_detail.item_code,
"warehouse": se_detail.t_warehouse,
"indented_qty": (se_detail.docstatus==2 and 1 or -1) * add_indented_qty,
- "posting_date": controller.doc.posting_date,
+ "posting_date": bean.doc.posting_date,
})
def set_missing_values(source, target_doclist):
@@ -369,4 +367,4 @@
}
}, target_doclist, set_missing_values)
- return [d.fields for d in doclist]
\ No newline at end of file
+ return [d.fields for d in doclist]
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index f219aa0..f61bd40 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -90,8 +90,8 @@
raise webnotes.ValidationError
def validate_item(self, item_code, row_num):
- from erpnext.stock.utils import validate_end_of_life, validate_is_stock_item, \
- validate_cancelled_item
+ from erpnext.stock.doctype.item.item import validate_end_of_life, \
+ validate_is_stock_item, validate_cancelled_item
# using try except to catch all validation msgs and display together
diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py
index 0f2d138..68dea05 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.py
+++ b/erpnext/stock/doctype/warehouse/warehouse.py
@@ -106,7 +106,7 @@
webnotes.conn.sql("delete from `tabBin` where warehouse=%s", olddn)
from erpnext.accounts.utils import rename_account_for
- rename_account_for("Warehouse", olddn, new_warehouse, merge)
+ rename_account_for("Warehouse", olddn, newdn, merge, self.doc.company)
return new_warehouse
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 69a024b..f203023 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -63,50 +63,6 @@
msgprint("[Stock Update] Ignored %s since it is not a stock item"
% args.get("item_code"))
-def validate_end_of_life(item_code, end_of_life=None, verbose=1):
- if not end_of_life:
- end_of_life = webnotes.conn.get_value("Item", item_code, "end_of_life")
-
- from webnotes.utils import getdate, now_datetime, formatdate
- if end_of_life and getdate(end_of_life) <= now_datetime().date():
- msg = (_("Item") + " %(item_code)s: " + _("reached its end of life on") + \
- " %(date)s. " + _("Please check") + ": %(end_of_life_label)s " + \
- "in Item master") % {
- "item_code": item_code,
- "date": formatdate(end_of_life),
- "end_of_life_label": webnotes.get_doctype("Item").get_label("end_of_life")
- }
-
- _msgprint(msg, verbose)
-
-def validate_is_stock_item(item_code, is_stock_item=None, verbose=1):
- if not is_stock_item:
- is_stock_item = webnotes.conn.get_value("Item", item_code, "is_stock_item")
-
- if is_stock_item != "Yes":
- msg = (_("Item") + " %(item_code)s: " + _("is not a Stock Item")) % {
- "item_code": item_code,
- }
-
- _msgprint(msg, verbose)
-
-def validate_cancelled_item(item_code, docstatus=None, verbose=1):
- if docstatus is None:
- docstatus = webnotes.conn.get_value("Item", item_code, "docstatus")
-
- if docstatus == 2:
- msg = (_("Item") + " %(item_code)s: " + _("is a cancelled Item")) % {
- "item_code": item_code,
- }
-
- _msgprint(msg, verbose)
-
-def _msgprint(msg, verbose):
- if verbose:
- msgprint(msg, raise_exception=True)
- else:
- raise webnotes.ValidationError, msg
-
def get_incoming_rate(args):
"""Get Incoming Rate based on valuation method"""
from erpnext.stock.stock_ledger import get_previous_sle
diff --git a/erpnext/templates/utils.py b/erpnext/templates/utils.py
index d75499f..bcd23ab 100644
--- a/erpnext/templates/utils.py
+++ b/erpnext/templates/utils.py
@@ -6,8 +6,7 @@
@webnotes.whitelist(allow_guest=True)
def send_message(subject="Website Query", message="", sender="", status="Open"):
- from webnotes.website.doctype.contact_us_settings.templates.pages.contact \
- import send_message as website_send_message
+ from webnotes.templates.pages.contact import send_message as website_send_message
if not website_send_message(subject, message, sender):
return
diff --git a/erpnext/utilities/doctype/sms_control/sms_control.py b/erpnext/utilities/doctype/sms_control/sms_control.py
index 41ff2a1..5c08a41 100644
--- a/erpnext/utilities/doctype/sms_control/sms_control.py
+++ b/erpnext/utilities/doctype/sms_control/sms_control.py
@@ -8,7 +8,7 @@
from webnotes.model.code import get_obj
from webnotes.model.doc import Document
from webnotes import msgprint, throw, _
-from webnotes.model.bean import getlist, copy_doclist
+from webnotes.model.bean import getlist
class DocType:
def __init__(self, doc, doclist=[]):
@@ -55,7 +55,7 @@
def send_form_sms(self, arg):
"called from client side"
args = json.loads(arg)
- self.send_sms([str(args['number'])], str(args['message']))
+ self.send_sms([cstr(args['number'])], cstr(args['message']))
def send_sms(self, receiver_list, msg, sender_name = ''):
receiver_list = self.validate_receiver_nos(receiver_list)
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index 098a4bd..83a3857 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -201,14 +201,6 @@
"from_currency": currency,
"to_currency": company_currency
}, raise_exception=True)
-
-def validate_item_fetch(args, item):
- from erpnext.stock.utils import validate_end_of_life
- validate_end_of_life(item.name, item.end_of_life)
-
- # validate company
- if not args.company:
- msgprint(_("Please specify Company"), raise_exception=True)
def validate_currency(args, item, meta=None):
from webnotes.model.meta import get_field_precision