Merge branch 'develop' into staging

This commit is contained in:
Nabin Hait 2017-11-10 11:46:50 +05:30
commit 29741fee08
67 changed files with 4676 additions and 3675 deletions

View File

@ -132,6 +132,7 @@
"get_url_arg": true, "get_url_arg": true,
"get_server_fields": true, "get_server_fields": true,
"set_multiple": true, "set_multiple": true,
"QUnit": true "QUnit": true,
"Chart": true
} }
} }

View File

@ -205,12 +205,10 @@ class Account(Document):
return new_account return new_account
def after_rename(self, old, new, merge=False): def after_rename(self, old, new, merge=False):
super(Account, self).after_rename(old, new, merge)
if not merge: if not merge:
frappe.db.set_value("Account", new, "account_name", frappe.db.set_value("Account", new, "account_name", " - ".join(new.split(" - ")[:-1]))
" - ".join(new.split(" - ")[:-1]))
else:
from frappe.utils.nestedset import rebuild_tree
rebuild_tree("Account", "parent_account")
def get_parent_account(doctype, txt, searchfield, start, page_len, filters): def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select name from tabAccount return frappe.db.sql("""select name from tabAccount

View File

@ -59,9 +59,8 @@ class CostCenter(NestedSet):
return new_cost_center return new_cost_center
def after_rename(self, olddn, newdn, merge=False): def after_rename(self, olddn, newdn, merge=False):
super(CostCenter, self).after_rename(olddn, newdn, merge)
if not merge: if not merge:
frappe.db.set_value("Cost Center", newdn, "cost_center_name", frappe.db.set_value("Cost Center", newdn, "cost_center_name",
" - ".join(newdn.split(" - ")[:-1])) " - ".join(newdn.split(" - ")[:-1]))
else:
super(CostCenter, self).after_rename(olddn, newdn, merge)

View File

@ -566,17 +566,26 @@ def get_default_bank_cash_account(company, account_type=None, mode_of_payment=No
account = get_bank_cash_account(mode_of_payment, company).get("account") account = get_bank_cash_account(mode_of_payment, company).get("account")
if not account: if not account:
'''
Set the default account first. If the user hasn't set any default account then, he doesn't
want us to set any random account. In this case set the account only if there is single
account (of that type), otherwise return empty dict.
'''
if account_type=="Bank": if account_type=="Bank":
account = frappe.db.get_value("Company", company, "default_bank_account") account = frappe.db.get_value("Company", company, "default_bank_account")
if not account: if not account:
account = frappe.db.get_value("Account", account_list = frappe.get_all("Account", filters = {"company": company,
{"company": company, "account_type": "Bank", "is_group": 0}) "account_type": "Bank", "is_group": 0})
if len(account_list) == 1:
account = account_list[0].name
elif account_type=="Cash": elif account_type=="Cash":
account = frappe.db.get_value("Company", company, "default_cash_account") account = frappe.db.get_value("Company", company, "default_cash_account")
if not account: if not account:
account = frappe.db.get_value("Account", account_list = frappe.get_all("Account", filters = {"company": company,
{"company": company, "account_type": "Cash", "is_group": 0}) "account_type": "Cash", "is_group": 0})
if len(account_list) == 1:
account = account_list[0].name
if account: if account:
account_details = frappe.db.get_value("Account", account, account_details = frappe.db.get_value("Account", account,

View File

@ -294,7 +294,7 @@ def get_gateway_details(args):
if args.get("payment_gateway"): if args.get("payment_gateway"):
return get_payment_gateway_account(args.get("payment_gateway")) return get_payment_gateway_account(args.get("payment_gateway"))
if args.cart: if args.order_type == "Shopping Cart":
payment_gateway_account = frappe.get_doc("Shopping Cart Settings").payment_gateway_account payment_gateway_account = frappe.get_doc("Shopping Cart Settings").payment_gateway_account
return get_payment_gateway_account(payment_gateway_account) return get_payment_gateway_account(payment_gateway_account)

View File

@ -480,7 +480,67 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "", "fieldname": "section_break_15",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Applicable for Users",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "applicable_for_users",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Applicable for Users",
"length": 0,
"no_copy": 0,
"options": "POS Profile User",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_11", "fieldname": "section_break_11",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@ -1471,7 +1531,7 @@
"show_name_in_global_search": 0, "show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"title_field": "user", "title_field": "pos_profile_name",
"track_changes": 0, "track_changes": 0,
"track_seen": 0 "track_seen": 0
} }

View File

@ -11,7 +11,7 @@ from frappe.model.document import Document
class POSProfile(Document): class POSProfile(Document):
def validate(self): def validate(self):
self.check_for_duplicate() # self.check_for_duplicate()
self.validate_all_link_fields() self.validate_all_link_fields()
self.validate_duplicate_groups() self.validate_duplicate_groups()
self.check_default_payment() self.check_default_payment()
@ -94,3 +94,45 @@ class POSProfile(Document):
@frappe.whitelist() @frappe.whitelist()
def get_series(): def get_series():
return frappe.get_meta("Sales Invoice").get_field("naming_series").options or "" return frappe.get_meta("Sales Invoice").get_field("naming_series").options or ""
@frappe.whitelist()
def get_pos_profiles_for_user(user=None):
out = []
if not user:
user = frappe.session.user
res = frappe.db.sql('''
select
parent
from
`tabPOS Profile User`
where
user = %s
''', (user), as_dict=1)
if not res:
company = frappe.defaults.get_user_default('company')
res = frappe.db.sql('''
select
pos_profile_name
from
`tabPOS Profile`
where
company = %s
''', (company), as_dict=1)
out = [r.pos_profile_name for r in res]
return out
for r in res:
name = frappe.db.get_value('POS Profile', r.parent, 'pos_profile_name')
out.append(name)
return out
@frappe.whitelist()
def get_pos_profile(pos_profile_name=None):
if not pos_profile_name: return
name = frappe.db.get_value('POS Profile', { 'pos_profile_name': pos_profile_name })
return frappe.get_doc('POS Profile', name)

View File

@ -0,0 +1,6 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('POS Profile User', {
});

View File

@ -0,0 +1,93 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2017-10-27 16:46:06.060930",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "user",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "User",
"length": 0,
"no_copy": 0,
"options": "User",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-10-27 16:46:12.784244",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Profile User",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}

View File

@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
from frappe.model.document import Document
class POSProfileUser(Document):
pass

View File

@ -16,6 +16,8 @@ def get_pos_data():
doc = frappe.new_doc('Sales Invoice') doc = frappe.new_doc('Sales Invoice')
doc.is_pos = 1; doc.is_pos = 1;
pos_profile = get_pos_profile(doc.company) or {} pos_profile = get_pos_profile(doc.company) or {}
if not pos_profile:
frappe.throw(_("POS Profile is required to use Point-of-Sale"))
if not doc.company: doc.company = pos_profile.get('company') if not doc.company: doc.company = pos_profile.get('company')
doc.update_stock = pos_profile.get('update_stock') doc.update_stock = pos_profile.get('update_stock')

View File

@ -4433,7 +4433,7 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-10-24 12:46:48.331723", "modified": "2017-11-03 05:31:56.636424",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Sales Invoice", "name": "Sales Invoice",
@ -4531,5 +4531,5 @@
"timeline_field": "customer", "timeline_field": "customer",
"title_field": "title", "title_field": "title",
"track_changes": 1, "track_changes": 1,
"track_seen": 0 "track_seen": 1
} }

View File

@ -309,14 +309,16 @@ class ReceivablePayableReport(object):
rows = [] rows = []
for d in data: for d in data:
rows.append(d[self.ageing_col_idx_start : self.ageing_col_idx_start+4]) rows.append(
{
if rows: 'values': d[self.ageing_col_idx_start : self.ageing_col_idx_start+4]
rows.insert(0, [[d.get("label")] for d in ageing_columns]) }
)
return { return {
"data": { "data": {
'labels': rows 'labels': [d.get("label") for d in ageing_columns],
'datasets': rows
}, },
"type": 'percentage' "type": 'percentage'
} }

View File

@ -1,5 +1,5 @@
{ {
"add_total_row": 0, "add_total_row": 1,
"apply_user_permissions": 1, "apply_user_permissions": 1,
"creation": "2013-07-30 17:28:49", "creation": "2013-07-30 17:28:49",
"disabled": 0, "disabled": 0,
@ -7,7 +7,7 @@
"doctype": "Report", "doctype": "Report",
"idx": 3, "idx": 3,
"is_standard": "Yes", "is_standard": "Yes",
"modified": "2017-02-24 20:20:20.613388", "modified": "2017-11-06 13:04:36.338268",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Delivered Items To Be Billed", "name": "Delivered Items To Be Billed",

View File

@ -1,5 +1,5 @@
{ {
"add_total_row": 0, "add_total_row": 1,
"apply_user_permissions": 1, "apply_user_permissions": 1,
"creation": "2013-02-21 14:26:44", "creation": "2013-02-21 14:26:44",
"disabled": 0, "disabled": 0,
@ -7,7 +7,7 @@
"doctype": "Report", "doctype": "Report",
"idx": 3, "idx": 3,
"is_standard": "Yes", "is_standard": "Yes",
"modified": "2017-02-24 20:20:13.972178", "modified": "2017-11-06 13:04:51.559061",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Ordered Items To Be Billed", "name": "Ordered Items To Be Billed",

View File

@ -1,5 +1,5 @@
{ {
"add_total_row": 0, "add_total_row": 1,
"apply_user_permissions": 1, "apply_user_permissions": 1,
"creation": "2013-07-30 18:35:10", "creation": "2013-07-30 18:35:10",
"disabled": 0, "disabled": 0,
@ -7,7 +7,7 @@
"doctype": "Report", "doctype": "Report",
"idx": 3, "idx": 3,
"is_standard": "Yes", "is_standard": "Yes",
"modified": "2017-02-24 19:59:52.887744", "modified": "2017-11-06 13:04:26.094432",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Received Items To Be Billed", "name": "Received Items To Be Billed",

View File

@ -0,0 +1,57 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.query_reports["Sales Payment Summary"] = {
"filters": [
{
"fieldname":"from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.datetime.get_today(),
"width": "80"
},
{
"fieldname":"to_date",
"label": __("To Date"),
"fieldtype": "Date",
"default": frappe.datetime.get_today()
},
{
"fieldname":"company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("Company")
},
{
"fieldname":"mode_of_payment",
"label": __("Mode of Payment"),
"fieldtype": "Link",
"options": "Mode of Payment"
},
{
"fieldname":"owner",
"label": __("Owner"),
"fieldtype": "Link",
"options": "User",
"defaults": user
},
{
"fieldname":"cost_center",
"label": __("Cost Center"),
"fieldtype": "Link",
"options": "Cost Center"
},
{
"fieldname":"warehouse",
"label": __("Warehouse"),
"fieldtype": "Link",
"options": "Warehouse"
},
{
"fieldname":"is_pos",
"label": __("POS?"),
"fieldtype": "Check"
}
]
};

View File

@ -0,0 +1,26 @@
{
"add_total_row": 1,
"apply_user_permissions": 1,
"creation": "2017-11-03 16:31:45.757516",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2017-11-04 05:15:35.892659",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Payment Summary",
"owner": "Administrator",
"ref_doctype": "Sales Invoice",
"report_name": "Sales Payment Summary",
"report_type": "Script Report",
"roles": [
{
"role": "Accounts Manager"
},
{
"role": "Accounts User"
}
]
}

View File

@ -0,0 +1,66 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
def execute(filters=None):
columns, data = [], []
columns=get_columns()
data=get_sales_payment_data(filters, columns)
return columns, data
def get_columns():
return [
_("Date") + ":Date:80",
_("Owner") + "::150",
_("Payment Mode") + "::120",
_("Warehouse") + ":Link/Cost Center:100",
_("Cost Center") + ":Link/Warehouse:100",
_("Sales and Returns") + ":Currency/currency:120",
_("Taxes") + ":Currency/currency:120",
_("Payments") + ":Currency/currency:120",
_("Reconciliation") + ":Currency/currency:120"
]
def get_sales_payment_data(filters, columns):
sales_invoice_data = get_sales_invoice_data(filters)
data = []
for inv in sales_invoice_data:
row = [inv.posting_date, inv.owner, inv.mode_of_payment,inv.warehouse,
inv.cost_center,inv.net_total, inv.total_taxes, inv.paid_amount,
(inv.net_total + inv.total_taxes - inv.paid_amount)]
data.append(row)
return data
def get_conditions(filters):
conditions = ""
if filters.get("company"): conditions += " a.company=%(company)s"
if filters.get("customer"): conditions += " and a.customer = %(customer)s"
if filters.get("owner"): conditions += " and a.owner = %(owner)s"
if filters.get("from_date"): conditions += " and a.posting_date >= %(from_date)s"
if filters.get("to_date"): conditions += " and a.posting_date <= %(to_date)s"
if filters.get("mode_of_payment"): conditions += " and c.mode_of_payment >= %(mode_of_payment)s"
if filters.get("warehouse"): conditions += " and b.warehouse <= %(warehouse)s"
if filters.get("cost_center"): conditions += " and b.cost_center <= %(cost_center)s"
if filters.get("is_pos"): conditions += " and a.is_pos = %(is_pos)s"
return conditions
def get_sales_invoice_data(filters):
conditions = get_conditions(filters)
return frappe.db.sql("""
select
a.owner, a.posting_date, c.mode_of_payment, b.warehouse, b.cost_center,
sum(a.net_total) as "net_total",
sum(a.total_taxes_and_charges) as "total_taxes",
sum(a.base_paid_amount) as "paid_amount"
from `tabSales Invoice` a, `tabSales Invoice Item` b, `tabSales Invoice Payment` c
where
a.name = b.parent
and a.name = c.parent
and {conditions}
group by
a.owner, a.posting_date, c.mode_of_payment, b.warehouse, b.cost_center
""".format(conditions=conditions), filters, as_dict=1)

View File

@ -468,6 +468,12 @@ def get_data():
"name": "Customer Credit Balance", "name": "Customer Credit Balance",
"doctype": "Customer" "doctype": "Customer"
}, },
{
"type": "report",
"is_query_report": True,
"name": "Sales Payment Summary",
"doctype": "Sales Invoice"
}
] ]
}, },
{ {

View File

@ -15,6 +15,7 @@ def get_data():
{ {
"type": "doctype", "type": "doctype",
"name": "Task", "name": "Task",
"route": "Tree/Task",
"description": _("Project activity / task."), "description": _("Project activity / task."),
}, },
{ {

View File

@ -56,6 +56,17 @@ Integer field holds numeric value, without decimal place.
Link field is connected to another master from where it fetches data. For example, in the Quotation master, Customer is a Link field. Link field is connected to another master from where it fetches data. For example, in the Quotation master, Customer is a Link field.
- Geolocation
Use Geolocation field to store GeoJSON <a href="https://tools.ietf.org/html/rfc7946#section-3.3">featurecollection</a>. Stores polygons, lines and points. Internally it uses following custom properties for identifying a circle.
```
{
"point_type": "circle",
"radius": 10.00
}
```
- Password - Password
Password field will have decode value in it. Password field will have decode value in it.
@ -84,4 +95,4 @@ Table will be (sort of) Link field which renders another docytpe within the curr
Text Editor is text field. It has text-formatting options. In ERPNext, this field is generally used for defining Terms and Conditions. Text Editor is text field. It has text-formatting options. In ERPNext, this field is generally used for defining Terms and Conditions.
<!-- markdown --> <!-- markdown -->

View File

@ -15,13 +15,16 @@ def enable_hub():
return hub_settings return hub_settings
@frappe.whitelist() @frappe.whitelist()
def get_items(start=0, limit=20, category=None, order_by=None, text=None): def get_items(start=0, limit=20, category=None, order_by=None, company=None, text=None):
connection = get_connection() connection = get_connection()
filters = { filters = {
'hub_category': category, 'hub_category': category,
} }
if text: if text:
filters.update({'item_name': ('like', '%' + text + '%')}) filters.update({'item_name': ('like', '%' + text + '%')})
if company:
filters.update({'company_name': company})
response = connection.get_list('Hub Item', response = connection.get_list('Hub Item',
limit_start=start, limit_page_length=limit, limit_start=start, limit_page_length=limit,
filters=filters) filters=filters)

View File

@ -215,7 +215,7 @@ erpnext.hub.Hub = class Hub {
.on('click', '.company-link a', function(e) { .on('click', '.company-link a', function(e) {
e.preventDefault(); e.preventDefault();
const company_name = $(this).attr('data-company-name'); const company_name = $(this).attr('data-company-name');
me.get_company_details(company_name); frappe.set_route('hub', 'Company', company_name);
}) })
.on('click', '.breadcrumb li', function(e) { .on('click', '.breadcrumb li', function(e) {
e.preventDefault(); e.preventDefault();
@ -476,26 +476,34 @@ erpnext.hub.Hub = class Hub {
} }
get_company_details(company_id) { get_company_details(company_id) {
// get from cache if exists this.company_cache = this.company_cache || {};
let company_details = this.company_cache[company_id];
if(this.company_cache[company_id]) { return new Promise(resolve => {
this.go_to_company_page(company_details); // get from cache if exists
return; let company_details = this.company_cache[company_id];
} if(company_details) {
frappe.call({ resolve(company_details);
method: 'erpnext.hub_node.get_company_details', return;
args: {hub_sync_id: company_id}
}).then((r) => {
if (r.message) {
const company_details = r.message.company_details;
this.company_cache[company_id] = company_details;
this.go_to_company_page(company_details)
} }
}); frappe.call({
method: 'erpnext.hub_node.get_company_details',
args: {hub_sync_id: company_id}
}).then((r) => {
if (r.message) {
const company_details = r.message;
this.company_cache[company_id] = company_details;
resolve(company_details)
}
});
})
} }
go_to_company_page(company_details) { go_to_company_page(company_id) {
frappe.set_route('hub', 'Company', company_details.company_name); this.get_company_details(company_id)
.then(this.show_company_page.bind(this));
}
show_company_page(company_details) {
this.$hub_main_section.empty(); this.$hub_main_section.empty();
let $company_page = let $company_page =
@ -574,10 +582,10 @@ erpnext.hub.Hub = class Hub {
<h2>${ company_details.company_name }</h2> <h2>${ company_details.company_name }</h2>
</div> </div>
<div class="company"> <div class="company">
<span class="">${ company_details.seller_city }</span> <span class="">${ company_details.country }</span>
</div> </div>
<div class="description"> <div class="description">
<span class="small">${ company_details.seller_description }</span> <span class="small">${ company_details.site_name }</span>
</div> </div>
</div> </div>
@ -836,7 +844,7 @@ erpnext.hub.HubList = class HubList {
</div> </div>
</a> </a>
<div class="company-link"> <div class="company-link">
<a data-company-name="${ item.company_id }" class="">${ item.company_name }</a> <a data-company-name="${ item.company_name }" class="">${ item.company_name }</a>
</div> </div>
<div>${ item.formatted_price ? item.formatted_price : ''}</div> <div>${ item.formatted_price ? item.formatted_price : ''}</div>
</div> </div>

View File

@ -17,6 +17,14 @@ frappe.ui.form.on("Production Order", {
} }
}); });
frm.set_query("source_warehouse", function() {
return {
filters: {
'company': frm.doc.company,
}
}
});
frm.set_query("source_warehouse", "required_items", function() { frm.set_query("source_warehouse", "required_items", function() {
return { return {
filters: { filters: {

View File

@ -1358,7 +1358,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-07-10 14:29:00.457874", "modified": "2017-11-03 05:31:56.636424",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "Production Order", "name": "Production Order",
@ -1412,5 +1412,5 @@
"sort_order": "ASC", "sort_order": "ASC",
"title_field": "production_item", "title_field": "production_item",
"track_changes": 1, "track_changes": 1,
"track_seen": 0 "track_seen": 1
} }

View File

@ -64,7 +64,7 @@ erpnext.ProductionAnalytics = frappe.views.GridReportWithPlot.extend({
var chart_data = this.get_chart_data ? this.get_chart_data() : null; var chart_data = this.get_chart_data ? this.get_chart_data() : null;
this.chart = new frappe.chart.FrappeChart({ this.chart = new Chart({
parent: ".chart", parent: ".chart",
data: chart_data, data: chart_data,
type: 'line' type: 'line'

View File

@ -448,6 +448,7 @@ erpnext.patches.v8_9.remove_employee_from_salary_structure_parent
erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts
erpnext.patches.v8_9.set_default_fields_in_variant_settings erpnext.patches.v8_9.set_default_fields_in_variant_settings
erpnext.patches.v8_9.update_billing_gstin_for_indian_account erpnext.patches.v8_9.update_billing_gstin_for_indian_account
erpnext.patches.v9_0.add_user_to_child_table_in_pos_profile
erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
erpnext.patches.v9_0.student_admission_childtable_migrate erpnext.patches.v9_0.student_admission_childtable_migrate
erpnext.patches.v9_0.fix_subscription_next_date #2017-10-23 erpnext.patches.v9_0.fix_subscription_next_date #2017-10-23
@ -455,5 +456,6 @@ erpnext.patches.v9_0.add_healthcare_domain
erpnext.patches.v9_0.set_variant_item_description erpnext.patches.v9_0.set_variant_item_description
erpnext.patches.v9_0.set_uoms_in_variant_field erpnext.patches.v9_0.set_uoms_in_variant_field
erpnext.patches.v9_0.copy_old_fees_field_data erpnext.patches.v9_0.copy_old_fees_field_data
execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
erpnext.patches.v9_0.set_pos_profile_name erpnext.patches.v9_0.set_pos_profile_name
erpnext.patches.v9_0.remove_non_existing_warehouse_from_stock_settings erpnext.patches.v9_0.remove_non_existing_warehouse_from_stock_settings

View File

@ -1,5 +1,5 @@
import frappe import frappe
from MySQLdb import OperationalError from pymysql import InternalError
def execute(): def execute():
frappe.reload_doctype("Journal Entry Account") frappe.reload_doctype("Journal Entry Account")
@ -15,6 +15,6 @@ def execute():
frappe.db.sql("""update `tabJournal Entry Account` frappe.db.sql("""update `tabJournal Entry Account`
set reference_type=%s, reference_name={0} where ifnull({0}, '') != '' set reference_type=%s, reference_name={0} where ifnull({0}, '') != ''
""".format(fieldname), doctype) """.format(fieldname), doctype)
except OperationalError: except InternalError:
# column not found # column not found
pass pass

View File

@ -3,7 +3,7 @@
from __future__ import print_function, unicode_literals from __future__ import print_function, unicode_literals
import frappe import frappe
import MySQLdb from frappe.exceptions import SQLError
def execute(): def execute():
""" """
@ -31,7 +31,7 @@ def execute():
try: try:
migrate_item_variants() migrate_item_variants()
except MySQLdb.ProgrammingError: except SQLError:
print("`tabItem Variant` not found") print("`tabItem Variant` not found")
def rename_and_reload_doctypes(): def rename_and_reload_doctypes():

View File

@ -0,0 +1,22 @@
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
doctype = 'POS Profile'
frappe.reload_doc('accounts', 'doctype', doctype)
frappe.reload_doc('accounts', 'doctype', 'POS Profile User')
for doc in frappe.get_all(doctype):
_doc = frappe.get_doc(doctype, doc.name)
user = frappe.db.get_value(doctype, doc.name, 'user')
if not user: continue
_doc.append('applicable_for_users', {
'user': user
})
_doc.pos_profile_name = user + ' - ' + _doc.company
_doc.save()

View File

@ -19,38 +19,47 @@ frappe.ui.form.on("Task", {
}, },
refresh: function(frm) { refresh: function(frm) {
var doc = frm.doc; frm.fields_dict['parent_task'].get_query = function() {
if(doc.__islocal) { return {
if(!frm.doc.exp_end_date) { filters: {
frm.set_value("exp_end_date", frappe.datetime.add_days(new Date(), 7)); "is_group": 1,
}
} }
} }
if(!frm.is_group){
if(!doc.__islocal) { var doc = frm.doc;
if(frappe.model.can_read("Timesheet")) { if(doc.__islocal) {
frm.add_custom_button(__("Timesheet"), function() { if(!frm.doc.exp_end_date) {
frappe.route_options = {"project": doc.project, "task": doc.name} frm.set_value("exp_end_date", frappe.datetime.add_days(new Date(), 7));
frappe.set_route("List", "Timesheet"); }
}, __("View"), true);
}
if(frappe.model.can_read("Expense Claim")) {
frm.add_custom_button(__("Expense Claims"), function() {
frappe.route_options = {"project": doc.project, "task": doc.name}
frappe.set_route("List", "Expense Claim");
}, __("View"), true);
} }
if(frm.perm[0].write) { if(!doc.__islocal) {
if(frm.doc.status!=="Closed" && frm.doc.status!=="Cancelled") { if(frappe.model.can_read("Timesheet")) {
frm.add_custom_button(__("Close"), function() { frm.add_custom_button(__("Timesheet"), function() {
frm.set_value("status", "Closed"); frappe.route_options = {"project": doc.project, "task": doc.name}
frm.save(); frappe.set_route("List", "Timesheet");
}); }, __("View"), true);
} else { }
frm.add_custom_button(__("Reopen"), function() { if(frappe.model.can_read("Expense Claim")) {
frm.set_value("status", "Open"); frm.add_custom_button(__("Expense Claims"), function() {
frm.save(); frappe.route_options = {"project": doc.project, "task": doc.name}
}); frappe.set_route("List", "Expense Claim");
}, __("View"), true);
}
if(frm.perm[0].write) {
if(frm.doc.status!=="Closed" && frm.doc.status!=="Cancelled") {
frm.add_custom_button(__("Close"), function() {
frm.set_value("status", "Closed");
frm.save();
});
} else {
frm.add_custom_button(__("Reopen"), function() {
frm.set_value("status", "Open");
frm.save();
});
}
} }
} }
} }
@ -71,6 +80,21 @@ frappe.ui.form.on("Task", {
} }
}, },
is_group: function(frm) {
frappe.call({
method:"erpnext.projects.doctype.task.task.check_if_child_exists",
args: {
name: frm.doc.name
},
callback: function(r){
if(r.message){
frappe.msgprint(__('Cannot convert it to non-group. Child Tasks exist.'));
frm.reload_doc();
}
}
})
},
validate: function(frm) { validate: function(frm) {
frm.doc.project && frappe.model.remove_from_locals("Project", frm.doc.project && frappe.model.remove_from_locals("Project",
frm.doc.project); frm.doc.project);

View File

@ -3,7 +3,7 @@
"allow_guest_to_view": 0, "allow_guest_to_view": 0,
"allow_import": 1, "allow_import": 1,
"allow_rename": 1, "allow_rename": 1,
"autoname": "TASK.#####", "autoname": "field:subject",
"beta": 0, "beta": 0,
"creation": "2013-01-29 19:25:50", "creation": "2013-01-29 19:25:50",
"custom": 0, "custom": 0,
@ -30,9 +30,8 @@
"label": "Subject", "label": "Subject",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"oldfieldname": "subject",
"oldfieldtype": "Data",
"permlevel": 0, "permlevel": 0,
"precision": "",
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
@ -75,6 +74,37 @@
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
"columns": 0,
"default": "0",
"fieldname": "is_group",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Is Group",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -173,9 +203,42 @@
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"fieldname": "parent_task",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Parent Task",
"length": 0,
"no_copy": 0,
"options": "Task",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"collapsible_depends_on": "",
"columns": 0,
"depends_on": "",
"fieldname": "section_break_10", "fieldname": "section_break_10",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@ -205,6 +268,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "exp_start_date", "fieldname": "exp_start_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@ -237,6 +301,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "0", "default": "0",
"depends_on": "",
"description": "", "description": "",
"fieldname": "expected_time", "fieldname": "expected_time",
"fieldtype": "Float", "fieldtype": "Float",
@ -269,6 +334,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "task_weight", "fieldname": "task_weight",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0, "hidden": 0,
@ -328,6 +394,7 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "exp_end_date", "fieldname": "exp_end_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@ -359,6 +426,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "progress", "fieldname": "progress",
"fieldtype": "Percent", "fieldtype": "Percent",
"hidden": 0, "hidden": 0,
@ -389,6 +457,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "is_milestone", "fieldname": "is_milestone",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": 0, "hidden": 0,
@ -418,7 +487,9 @@
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"collapsible_depends_on": "",
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "section_break0", "fieldname": "section_break0",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@ -449,6 +520,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "description", "fieldname": "description",
"fieldtype": "Text Editor", "fieldtype": "Text Editor",
"hidden": 0, "hidden": 0,
@ -481,7 +553,9 @@
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"collapsible_depends_on": "",
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "section_break", "fieldname": "section_break",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@ -512,6 +586,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "depends_on", "fieldname": "depends_on",
"fieldtype": "Table", "fieldtype": "Table",
"hidden": 0, "hidden": 0,
@ -543,6 +618,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "depends_on_tasks", "fieldname": "depends_on_tasks",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": 1, "hidden": 1,
@ -572,7 +648,9 @@
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"collapsible_depends_on": "",
"columns": 0, "columns": 0,
"depends_on": "",
"description": "", "description": "",
"fieldname": "actual", "fieldname": "actual",
"fieldtype": "Section Break", "fieldtype": "Section Break",
@ -606,6 +684,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "act_start_date", "fieldname": "act_start_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@ -638,6 +717,7 @@
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "", "default": "",
"depends_on": "",
"description": "", "description": "",
"fieldname": "actual_time", "fieldname": "actual_time",
"fieldtype": "Float", "fieldtype": "Float",
@ -699,6 +779,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "act_end_date", "fieldname": "act_end_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0, "hidden": 0,
@ -730,6 +811,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "section_break_17", "fieldname": "section_break_17",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": 0, "hidden": 0,
@ -759,6 +841,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "total_costing_amount", "fieldname": "total_costing_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@ -791,6 +874,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "total_expense_claim", "fieldname": "total_expense_claim",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@ -851,6 +935,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fieldname": "total_billing_amount", "fieldname": "total_billing_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@ -1025,6 +1110,96 @@
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "lft",
"fieldtype": "Int",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "lft",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "rgt",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "old_parent",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Old Parent",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
} }
], ],
"has_web_view": 0, "has_web_view": 0,
@ -1039,7 +1214,7 @@
"istable": 0, "istable": 0,
"max_attachments": 5, "max_attachments": 5,
"menu_index": 0, "menu_index": 0,
"modified": "2017-05-23 11:28:28.161600", "modified": "2017-10-06 03:57:37.901446",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Projects", "module": "Projects",
"name": "Task", "name": "Task",

View File

@ -5,13 +5,14 @@ from __future__ import unicode_literals
import frappe, json import frappe, json
from frappe.utils import getdate, date_diff, add_days, cstr from frappe.utils import getdate, date_diff, add_days, cstr
from frappe import _ from frappe import _, throw
from frappe.utils.nestedset import NestedSet, rebuild_tree
from frappe.model.document import Document
class CircularReferenceError(frappe.ValidationError): pass class CircularReferenceError(frappe.ValidationError): pass
class Task(Document): class Task(NestedSet):
nsm_parent_field = 'parent_task'
def get_feed(self): def get_feed(self):
return '{0}: {1}'.format(_(self.status), self.subject) return '{0}: {1}'.format(_(self.status), self.subject)
@ -59,7 +60,11 @@ class Task(Document):
depends_on_tasks += d.task + "," depends_on_tasks += d.task + ","
self.depends_on_tasks = depends_on_tasks self.depends_on_tasks = depends_on_tasks
def update_nsm_model(self):
frappe.utils.nestedset.update_nsm(self)
def on_update(self): def on_update(self):
self.update_nsm_model()
self.check_recursion() self.check_recursion()
self.reschedule_dependent_tasks() self.reschedule_dependent_tasks()
self.update_project() self.update_project()
@ -105,16 +110,20 @@ class Task(Document):
frappe.throw(_("Circular Reference Error"), CircularReferenceError) frappe.throw(_("Circular Reference Error"), CircularReferenceError)
if b[0]: if b[0]:
task_list.append(b[0]) task_list.append(b[0])
if count == 15: if count == 15:
break break
def reschedule_dependent_tasks(self): def reschedule_dependent_tasks(self):
end_date = self.exp_end_date or self.act_end_date end_date = self.exp_end_date or self.act_end_date
if end_date: if end_date:
for task_name in frappe.db.sql("""select name from `tabTask` as parent where parent.project = %(project)s and parent.name in \ for task_name in frappe.db.sql("""
(select parent from `tabTask Depends On` as child where child.task = %(task)s and child.project = %(project)s)""", select name from `tabTask` as parent
{'project': self.project, 'task':self.name }, as_dict=1): where parent.project = %(project)s
and parent.name in (
select parent from `tabTask Depends On` as child
where child.task = %(task)s and child.project = %(project)s)
""", {'project': self.project, 'task':self.name }, as_dict=1):
task = frappe.get_doc("Task", task_name.name) task = frappe.get_doc("Task", task_name.name)
if task.exp_start_date and task.exp_end_date and task.exp_start_date < getdate(end_date) and task.status == "Open": if task.exp_start_date and task.exp_end_date and task.exp_start_date < getdate(end_date) and task.status == "Open":
task_duration = date_diff(task.exp_end_date, task.exp_start_date) task_duration = date_diff(task.exp_end_date, task.exp_start_date)
@ -128,6 +137,17 @@ class Task(Document):
if project_user: if project_user:
return True return True
def on_trash(self):
if check_if_child_exists(self.name):
throw(_("Child Task exists for this Task. You can not delete this Task."))
self.update_nsm_model()
@frappe.whitelist()
def check_if_child_exists(name):
return frappe.db.sql("""select name from `tabTask`
where parent_task = %s""", name)
@frappe.whitelist() @frappe.whitelist()
def get_events(start, end, filters=None): def get_events(start, end, filters=None):
"""Returns events for Gantt / Calendar view rendering. """Returns events for Gantt / Calendar view rendering.
@ -177,4 +197,48 @@ def set_tasks_as_overdue():
and exp_end_date < CURDATE() and exp_end_date < CURDATE()
and `status` not in ('Closed', 'Cancelled')""") and `status` not in ('Closed', 'Cancelled')""")
@frappe.whitelist()
def get_children():
doctype = frappe.local.form_dict.get('doctype')
parent_field = 'parent_' + doctype.lower().replace(' ', '_')
parent = frappe.form_dict.get("parent") or ""
if parent == "task":
parent = ""
tasks = frappe.db.sql("""select name as value,
is_group as expandable
from `tab{doctype}`
where docstatus < 2
and ifnull(`{parent_field}`,'') = %s
order by name""".format(doctype=frappe.db.escape(doctype),
parent_field=frappe.db.escape(parent_field)), (parent), as_dict=1)
# return tasks
return tasks
@frappe.whitelist()
def add_node():
from frappe.desk.treeview import make_tree_args
args = frappe.form_dict
args.update({
"name_field": "subject"
})
args = make_tree_args(**args)
if args.parent_task == 'task':
args.parent_task = None
frappe.get_doc(args).insert()
@frappe.whitelist()
def add_multiple_tasks(data, parent):
data = json.loads(data)['tasks']
tasks = data.split('\n')
new_doc = {'doctype': 'Task', 'parent_task': parent}
for d in tasks:
new_doc['subject'] = d
new_task = frappe.get_doc(new_doc)
new_task.insert()

View File

@ -25,7 +25,9 @@ frappe.listview_settings['Task'] = {
return [__(doc.status), colors[doc.status], "status,=," + doc.status]; return [__(doc.status), colors[doc.status], "status,=," + doc.status];
}, },
gantt_custom_popup_html: function(ganttobj, task) { gantt_custom_popup_html: function(ganttobj, task) {
var html = `<h5>${ganttobj.name}</h5>`; var html = `<h5><a style="text-decoration:underline"\
href="#Form/Task/${ganttobj.id}""> ${ganttobj.name} </a></h5>`;
if(task.project) html += `<p>Project: ${task.project}</p>`; if(task.project) html += `<p>Project: ${task.project}</p>`;
html += `<p>Progress: ${ganttobj.progress}</p>`; html += `<p>Progress: ${ganttobj.progress}</p>`;

View File

@ -0,0 +1,59 @@
frappe.provide("frappe.treeview_settings");
frappe.treeview_settings['Task'] = {
get_tree_nodes: "erpnext.projects.doctype.task.task.get_children",
add_tree_node: "erpnext.projects.doctype.task.task.add_node",
filters: [
{
fieldname: "task",
fieldtype:"Link",
options: "Task",
label: __("Task"),
get_query: function(){
return {
filters: [["Task", 'is_group', '=', 1]]
};
}
}
],
title: "Task",
breadcrumb: "Projects",
get_tree_root: false,
root_label: "task",
ignore_fields:["parent_task"],
get_label: function(node) {
return node.data.value;
},
onload: function(me){
me.make_tree();
me.set_root = true;
},
toolbar: [
{
label:__("Add Multiple"),
condition: function(node) {
return node.expandable;
},
click: function(node) {
var d = new frappe.ui.Dialog({
'fields': [
{'fieldname': 'tasks', 'label': 'Tasks', 'fieldtype': 'Text'},
],
primary_action: function(){
d.hide();
return frappe.call({
method: "erpnext.projects.doctype.task.task.add_multiple_tasks",
args: {
data: d.get_values(),
parent: node.data.value
},
callback: function() { }
});
}
});
d.show();
}
}
],
extend_toolbar: true
};

View File

@ -1,15 +0,0 @@
[
{
"status": "Open",
"subject": "_Test Task",
"name": "task001"
},
{
"status": "Open",
"subject": "_Test Task 1"
},
{
"status": "Open",
"subject": "_Test Task 2"
}
]

View File

@ -5,137 +5,61 @@ import frappe
import unittest import unittest
from frappe.utils import getdate, nowdate, add_days from frappe.utils import getdate, nowdate, add_days
# test_records = frappe.get_test_records('Task')
from erpnext.projects.doctype.task.task import CircularReferenceError from erpnext.projects.doctype.task.task import CircularReferenceError
class TestTask(unittest.TestCase): class TestTask(unittest.TestCase):
def test_circular_reference(self): def test_circular_reference(self):
task1 = create_task("_Test Task 1", nowdate(), add_days(nowdate(), 10))
task2 = create_task("_Test Task 2", add_days(nowdate(), 11), add_days(nowdate(), 15), task1.name)
task3 = create_task("_Test Task 3", add_days(nowdate(), 11), add_days(nowdate(), 15), task2.name)
task1 = frappe.new_doc('Task') task1.reload()
task1.update({
"status": "Open",
"subject": "_Test Task 1",
"project": "_Test Project",
"exp_start_date": "2015-1-1",
"exp_end_date": "2015-1-10"
})
task1.save()
task2 = frappe.new_doc('Task')
task2.update({
"status": "Open",
"subject": "_Test Task 2",
"project": "_Test Project",
"exp_start_date": "2015-1-11",
"exp_end_date": "2015-1-15",
"depends_on":[
{
"task": task1.name
}
]
})
task2.save()
task3 = frappe.new_doc('Task')
task3.update({
"status": "Open",
"subject": "_Test Task 2",
"project": "_Test Project",
"exp_start_date": "2015-1-11",
"exp_end_date": "2015-1-15",
"depends_on":[
{
"task": task2.name
}
]
})
task3.save()
task1.append("depends_on", { task1.append("depends_on", {
"task": task3.name "task": task3.name
}) })
self.assertRaises(CircularReferenceError, task1.save) self.assertRaises(CircularReferenceError, task1.save)
task1.set("depends_on", []) task1.set("depends_on", [])
task1.save() task1.save()
task4 = frappe.new_doc('Task') task4 = create_task("_Test Task 4", nowdate(), add_days(nowdate(), 15), task1.name)
task4.update({
"status": "Open",
"subject": "_Test Task 1",
"exp_start_date": "2015-1-1",
"exp_end_date": "2015-1-15",
"depends_on":[
{
"task": task1.name
}
]
})
task4.save()
task3.append("depends_on", { task3.append("depends_on", {
"task": task4.name "task": task4.name
}) })
def test_reschedule_dependent_task(self): def test_reschedule_dependent_task(self):
task1 = frappe.new_doc('Task') task1 = create_task("_Test Task 1", nowdate(), add_days(nowdate(), 10))
task1.update({
"status": "Open",
"subject": "_Test Task 1",
"project": "_Test Project",
"exp_start_date": "2015-1-1",
"exp_end_date": "2015-1-10"
})
task1.save()
task2 = frappe.new_doc('Task') task2 = create_task("_Test Task 2", add_days(nowdate(), 11), add_days(nowdate(), 15), task1.name)
task2.update({ task2.get("depends_on")[0].project = "_Test Project"
"status": "Open",
"subject": "_Test Task 2",
"project": "_Test Project",
"exp_start_date": "2015-1-11",
"exp_end_date": "2015-1-15",
"depends_on":[
{
"task": task1.name,
"project": "_Test Project"
}
]
})
task2.save() task2.save()
task3 = frappe.new_doc('Task') task3 = create_task("_Test Task 3", add_days(nowdate(), 11), add_days(nowdate(), 15), task2.name)
task3.update({ task3.get("depends_on")[0].project = "_Test Project"
"status": "Open",
"subject": "_Test Task 3",
"project": "_Test Project",
"exp_start_date": "2015-1-16",
"exp_end_date": "2015-1-18",
"depends_on":[
{
"task": task2.name,
"project": "_Test Project"
}
]
})
task3.save() task3.save()
task1.update({ task1.update({
"exp_end_date": "2015-1-20" "exp_end_date": add_days(nowdate(), 20)
}) })
task1.save() task1.save()
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21')) self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"),
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25')) getdate(add_days(nowdate(), 21)))
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"),
getdate(add_days(nowdate(), 25)))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26')) self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"),
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28')) getdate(add_days(nowdate(), 26)))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"),
getdate(add_days(nowdate(), 30)))
def test_close_assignment(self): def test_close_assignment(self):
task = frappe.new_doc("Task") if not frappe.db.exists("Task", "Test Close Assignment"):
task.subject = "Test Close Assignment" task = frappe.new_doc("Task")
task.insert() task.subject = "Test Close Assignment"
task.insert()
def assign(): def assign():
from frappe.desk.form import assign_to from frappe.desk.form import assign_to
@ -147,8 +71,10 @@ class TestTask(unittest.TestCase):
}) })
def get_owner_and_status(): def get_owner_and_status():
return frappe.db.get_value("ToDo", filters={"reference_type": task.doctype, "reference_name": task.name, return frappe.db.get_value("ToDo",
"description": "Close this task"}, fieldname=("owner", "status"), as_dict=True) filters={"reference_type": task.doctype, "reference_name": task.name,
"description": "Close this task"},
fieldname=("owner", "status"), as_dict=True)
assign() assign()
todo = get_owner_and_status() todo = get_owner_and_status()
@ -164,16 +90,29 @@ class TestTask(unittest.TestCase):
self.assertEquals(todo.status, "Closed") self.assertEquals(todo.status, "Closed")
def test_overdue(self): def test_overdue(self):
task = frappe.get_doc({ task = create_task("Testing Overdue", add_days(nowdate(), -10), add_days(nowdate(), -5))
"doctype":"Task",
"subject": "Testing Overdue",
"status": "Open",
"exp_end_date": add_days(nowdate(), -1)
})
task.insert()
from erpnext.projects.doctype.task.task import set_tasks_as_overdue from erpnext.projects.doctype.task.task import set_tasks_as_overdue
set_tasks_as_overdue() set_tasks_as_overdue()
self.assertEquals(frappe.db.get_value("Task", task.name, "status"), "Overdue") self.assertEquals(frappe.db.get_value("Task", task.name, "status"), "Overdue")
def create_task(subject, start=None, end=None, depends_on=None, project=None):
if not frappe.db.exists("Task", subject):
task = frappe.new_doc('Task')
task.status = "Open"
task.subject = subject
task.exp_start_date = start or nowdate()
task.exp_end_date = end or nowdate()
task.project = project or "_Test Project"
task.save()
else:
task = frappe.get_doc("Task", subject)
if depends_on:
task.append("depends_on", {
"task": depends_on
})
task.save()
return task

View File

@ -0,0 +1,99 @@
/* eslint-disable */
// rename this file from _test_[name] to test_[name] to activate
// and remove above this line
QUnit.test("test: Task Tree", function (assert) {
let done = assert.async();
// number of asserts
assert.expect(5);
frappe.run_serially([
// insert a new Task
() => frappe.set_route('Tree', 'Task'),
() => frappe.timeout(0.5),
// Checking adding child without selecting any Node
() => frappe.tests.click_button('New'),
() => frappe.timeout(0.5),
() => {assert.equal($(`.msgprint`).text(), "Select a group node first.", "Error message success");},
() => frappe.tests.click_button('Close'),
() => frappe.timeout(0.5),
// Creating child nodes
() => frappe.tests.click_link('task'),
() => frappe.map_group.make('Test-1'),
() => frappe.map_group.make('Test-2'),
() => frappe.map_group.make('Test-3', 1),
() => frappe.timeout(1),
() => frappe.tests.click_link('Test-3'),
() => frappe.map_group.make('Test-4', 0),
// Checking Edit button
() => frappe.timeout(0.5),
() => frappe.tests.click_link('Test-1'),
() => frappe.tests.click_button('Edit'),
() => frappe.timeout(0.5),
() => {assert.deepEqual(frappe.get_route(), ["Form", "Task", "Test-1"], "Edit route checks");},
// Deleting child Node
() => frappe.set_route('Tree', 'Task'),
() => frappe.timeout(0.5),
() => frappe.tests.click_link('Test-1'),
() => frappe.tests.click_button('Delete'),
() => frappe.timeout(0.5),
() => frappe.tests.click_button('Yes'),
// Deleting Group Node that has child nodes in it
() => frappe.timeout(0.5),
() => frappe.tests.click_link('Test-3'),
() => frappe.tests.click_button('Delete'),
() => frappe.timeout(0.5),
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(1),
() => {assert.equal(cur_dialog.title, 'Message', 'Error thrown correctly');},
() => frappe.tests.click_button('Close'),
// Renaming Child node
() => frappe.timeout(0.5),
() => frappe.tests.click_link('Test-2'),
() => frappe.tests.click_button('Rename'),
() => frappe.timeout(1),
() => cur_dialog.set_value('new_name', 'Test-5'),
() => frappe.timeout(1.5),
() => cur_dialog.get_primary_btn().click(),
() => frappe.timeout(1),
() => {assert.equal($(`a:contains("Test-5"):visible`).length, 1, 'Rename successfull');},
// Add multiple child tasks
() => frappe.tests.click_link('Test-3'),
() => frappe.timeout(0.5),
() => frappe.click_button('Add Multiple'),
() => frappe.timeout(1),
() => cur_dialog.set_value('tasks', 'Test-6\nTest-7'),
() => frappe.timeout(0.5),
() => frappe.click_button('Submit'),
() => frappe.timeout(2),
() => frappe.click_button('Expand All'),
() => frappe.timeout(1),
() => {
let count = $(`a:contains("Test-6"):visible`).length + $(`a:contains("Test-7"):visible`).length;
assert.equal(count, 2, "Multiple Tasks added successfully");
},
() => done()
]);
});
frappe.map_group = {
make:function(subject, is_group = 0){
return frappe.run_serially([
() => frappe.click_button('Add Child'),
() => frappe.timeout(1),
() => cur_dialog.set_value('is_group', is_group),
() => cur_dialog.set_value('subject', subject),
() => frappe.click_button('Create New'),
() => frappe.timeout(1.5)
]);
}
};

View File

@ -8,7 +8,7 @@
<input type="tel" class="form-control cell" disabled value="{%= price_list_rate %}"/> <input type="tel" class="form-control cell" disabled value="{%= price_list_rate %}"/>
</div> </div>
<div class="pos-list-row"> <div class="pos-list-row">
<div class="cell">{{ __("Discount") }}:</div> <div class="cell">{{ __("Discount") }}: %</div>
<input type="tel" class="form-control cell pos-item-disc" value="{%= discount_percentage %}"> <input type="tel" class="form-control cell pos-item-disc" value="{%= discount_percentage %}">
</div> </div>
<div class="pos-list-row"> <div class="pos-list-row">

View File

@ -43,7 +43,7 @@ class AssessmentPlan(Document):
assessment_criteria_list = frappe.db.sql_list(''' select apc.assessment_criteria assessment_criteria_list = frappe.db.sql_list(''' select apc.assessment_criteria
from `tabAssessment Plan` ap , `tabAssessment Plan Criteria` apc from `tabAssessment Plan` ap , `tabAssessment Plan Criteria` apc
where ap.name = apc.parent and ap.course=%s and ap.student_group=%s and ap.assessment_group=%s where ap.name = apc.parent and ap.course=%s and ap.student_group=%s and ap.assessment_group=%s
and ap.name != %s''', (self.course, self.student_group, self.assessment_group, self.name)) and ap.name != %s and ap.docstatus=1''', (self.course, self.student_group, self.assessment_group, self.name))
for d in self.assessment_criteria: for d in self.assessment_criteria:
if d.assessment_criteria in assessment_criteria_list: if d.assessment_criteria in assessment_criteria_list:
frappe.throw(_("You have already assessed for the assessment criteria {}.") frappe.throw(_("You have already assessed for the assessment criteria {}.")

View File

@ -2,7 +2,7 @@
QUnit.module('schools'); QUnit.module('schools');
QUnit.test('Test: Assessment Plan', function(assert){ QUnit.test('Test: Assessment Plan', function(assert){
assert.expect(7); assert.expect(6);
let done = assert.async(); let done = assert.async();
let room_name, instructor_name, assessment_name; let room_name, instructor_name, assessment_name;
@ -49,10 +49,6 @@ QUnit.test('Test: Assessment Plan', function(assert){
assert.equal(cur_frm.doc.assessment_plan, assessment_name, 'Assessment correctly set'); assert.equal(cur_frm.doc.assessment_plan, assessment_name, 'Assessment correctly set');
assert.equal(cur_frm.doc.student_group, 'test-course-wise-group-2', 'Course for Assessment correctly set'); assert.equal(cur_frm.doc.student_group, 'test-course-wise-group-2', 'Course for Assessment correctly set');
}, },
() => cur_frm.print_doc(),
() => frappe.timeout(1),
() => {assert.ok($('.btn-print-print').is(':visible'), "Print Format Available");},
() => done() () => done()
]); ]);
}); });

View File

@ -7,23 +7,25 @@ cur_frm.add_fetch("assessment_plan", "maximum_assessment_score", "maximum_score"
frappe.ui.form.on("Assessment Result", { frappe.ui.form.on("Assessment Result", {
assessment_plan: function(frm) { assessment_plan: function(frm) {
frappe.call({ if (frm.doc.assessment_plan) {
method: "erpnext.schools.api.get_assessment_details", frappe.call({
args: { method: "erpnext.schools.api.get_assessment_details",
assessment_plan: frm.doc.assessment_plan args: {
}, assessment_plan: frm.doc.assessment_plan
callback: function(r) { },
if (r.message) { callback: function(r) {
frm.doc.details = []; if (r.message) {
$.each(r.message, function(i, d) { frm.doc.details = [];
var row = frappe.model.add_child(frm.doc, "Assessment Result Detail", "details"); $.each(r.message, function(i, d) {
row.assessment_criteria = d.assessment_criteria; var row = frappe.model.add_child(frm.doc, "Assessment Result Detail", "details");
row.maximum_score = d.maximum_score; row.assessment_criteria = d.assessment_criteria;
}); row.maximum_score = d.maximum_score;
});
}
refresh_field("details");
} }
refresh_field("details"); });
} }
});
} }
}); });

View File

@ -175,7 +175,7 @@
"issingle": 1, "issingle": 1,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-06-30 08:21:47.184562", "modified": "2017-11-08 11:51:43.247815",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Assessment Result Tool", "name": "Assessment Result Tool",
@ -188,17 +188,17 @@
"cancel": 0, "cancel": 0,
"create": 1, "create": 1,
"delete": 0, "delete": 0,
"email": 1, "email": 0,
"export": 0, "export": 0,
"if_owner": 0, "if_owner": 0,
"import": 0, "import": 0,
"permlevel": 0, "permlevel": 0,
"print": 1, "print": 0,
"read": 1, "read": 1,
"report": 0, "report": 0,
"role": "Academics User", "role": "Academics User",
"set_user_permissions": 0, "set_user_permissions": 0,
"share": 1, "share": 0,
"submit": 0, "submit": 0,
"write": 1 "write": 1
} }

View File

@ -90,7 +90,7 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-06-30 08:21:47.851347", "modified": "2017-11-02 17:57:18.069158",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Fee Category", "name": "Fee Category",
@ -116,6 +116,46 @@
"share": 1, "share": 1,
"submit": 0, "submit": 0,
"write": 1 "write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
} }
], ],
"quick_entry": 1, "quick_entry": 1,

View File

@ -25,7 +25,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 1,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Fee Structure", "label": "Fee Structure",
@ -1029,7 +1029,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-09-19 16:24:17.266071", "modified": "2017-11-02 17:55:22.851581",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Fee Schedule", "name": "Fee Schedule",
@ -1039,7 +1039,7 @@
{ {
"amend": 1, "amend": 1,
"apply_user_permissions": 0, "apply_user_permissions": 0,
"cancel": 1, "cancel": 0,
"create": 1, "create": 1,
"delete": 1, "delete": 1,
"email": 1, "email": 1,
@ -1053,6 +1053,46 @@
"role": "Academics User", "role": "Academics User",
"set_user_permissions": 0, "set_user_permissions": 0,
"share": 1, "share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1, "submit": 1,
"write": 1 "write": 1
} }
@ -1060,6 +1100,7 @@
"quick_entry": 0, "quick_entry": 0,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education",
"show_name_in_global_search": 0, "show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",

View File

@ -165,7 +165,7 @@
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 1, "reqd": 0,
"search_index": 1, "search_index": 1,
"set_only_once": 0, "set_only_once": 0,
"unique": 0, "unique": 0,
@ -197,7 +197,7 @@
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 0, "reqd": 1,
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
@ -577,7 +577,7 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-09-11 15:18:27.975666", "modified": "2017-11-02 17:43:16.796845",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Fee Structure", "name": "Fee Structure",
@ -587,7 +587,7 @@
{ {
"amend": 1, "amend": 1,
"apply_user_permissions": 0, "apply_user_permissions": 0,
"cancel": 1, "cancel": 0,
"create": 1, "create": 1,
"delete": 1, "delete": 1,
"email": 1, "email": 1,
@ -601,6 +601,46 @@
"role": "Academics User", "role": "Academics User",
"set_user_permissions": 0, "set_user_permissions": 0,
"share": 1, "share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1, "submit": 1,
"write": 1 "write": 1
} }
@ -609,6 +649,7 @@
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education", "restrict_to_domain": "Education",
"search_fields": "program, student_category, academic_year",
"show_name_in_global_search": 0, "show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",

View File

@ -1,7 +1,7 @@
{ {
"allow_copy": 0, "allow_copy": 0,
"allow_guest_to_view": 0, "allow_guest_to_view": 0,
"allow_import": 0, "allow_import": 1,
"allow_rename": 0, "allow_rename": 0,
"autoname": "naming_series:", "autoname": "naming_series:",
"beta": 1, "beta": 1,
@ -87,7 +87,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 1,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Student Name", "label": "Student Name",
@ -118,7 +118,7 @@
"ignore_user_permissions": 0, "ignore_user_permissions": 0,
"ignore_xss_filter": 0, "ignore_xss_filter": 0,
"in_filter": 0, "in_filter": 0,
"in_global_search": 0, "in_global_search": 1,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Fee Schedule", "label": "Fee Schedule",
@ -158,7 +158,7 @@
"no_copy": 0, "no_copy": 0,
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -249,7 +249,7 @@
"options": "Company", "options": "Company",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 1, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 1, "remember_last_selected_value": 1,
@ -310,7 +310,7 @@
"no_copy": 1, "no_copy": 1,
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 1, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -494,7 +494,7 @@
"options": "Student Batch Name", "options": "Student Batch Name",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -708,7 +708,7 @@
"options": "Currency", "options": "Currency",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 1, "read_only": 1,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -739,7 +739,7 @@
"options": "Fee Structure", "options": "Fee Structure",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -1011,7 +1011,7 @@
"no_copy": 0, "no_copy": 0,
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -1132,7 +1132,7 @@
"no_copy": 0, "no_copy": 0,
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -1163,7 +1163,7 @@
"options": "Account", "options": "Account",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -1194,7 +1194,7 @@
"options": "Account", "options": "Account",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -1223,7 +1223,7 @@
"no_copy": 0, "no_copy": 0,
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 1,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
@ -1254,6 +1254,35 @@
"options": "Cost Center", "options": "Cost Center",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "data_42",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
@ -1276,13 +1305,53 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-09-20 23:17:09.819606", "modified": "2017-11-02 17:31:47.155873",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Fees", "name": "Fees",
"name_case": "", "name_case": "",
"owner": "Administrator", "owner": "Administrator",
"permissions": [ "permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Academics User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
},
{ {
"amend": 0, "amend": 0,
"apply_user_permissions": 0, "apply_user_permissions": 0,
@ -1297,7 +1366,7 @@
"print": 1, "print": 1,
"read": 1, "read": 1,
"report": 1, "report": 1,
"role": "Academics User", "role": "Accounts Manager",
"set_user_permissions": 0, "set_user_permissions": 0,
"share": 1, "share": 1,
"submit": 1, "submit": 1,
@ -1308,7 +1377,8 @@
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"restrict_to_domain": "Education", "restrict_to_domain": "Education",
"show_name_in_global_search": 0, "search_fields": "student, student_name",
"show_name_in_global_search": 1,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"title_field": "student_name", "title_field": "student_name",

View File

@ -223,67 +223,6 @@
"search_index": 0, "search_index": 0,
"set_only_once": 0, "set_only_once": 0,
"unique": 0 "unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "fee_schedule",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Fee Schedule",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "fees",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Fees",
"length": 0,
"no_copy": 0,
"options": "Program Fee",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
} }
], ],
"has_web_view": 0, "has_web_view": 0,
@ -297,7 +236,7 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-06-30 08:21:49.176708", "modified": "2017-11-02 18:08:20.823972",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Program", "name": "Program",

View File

@ -13,9 +13,12 @@ class StudentApplicant(Document):
from frappe.model.naming import set_name_by_naming_series from frappe.model.naming import set_name_by_naming_series
if self.student_admission: if self.student_admission:
if self.program: if self.program:
# set the naming series from the student admission if provided.
student_admission = get_student_admission_data(self.student_admission, self.program) student_admission = get_student_admission_data(self.student_admission, self.program)
if student_admission: if student_admission:
naming_series = student_admission.get("applicant_naming_series") naming_series = student_admission.get("applicant_naming_series")
else:
naming_series = None
else: else:
frappe.throw(_("Select the program first")) frappe.throw(_("Select the program first"))
@ -40,15 +43,16 @@ class StudentApplicant(Document):
def validation_from_student_admission(self): def validation_from_student_admission(self):
student_admission = get_student_admission_data(self.student_admission, self.program) student_admission = get_student_admission_data(self.student_admission, self.program)
if student_admission:
if (( # different validation for minimum and maximum age so that either min/max can also work independently.
student_admission.minimum_age if student_admission and student_admission.minimum_age and \
and getdate(student_admission.minimum_age) > getdate(self.date_of_birth) getdate(student_admission.minimum_age) < getdate(self.date_of_birth):
) or ( frappe.throw(_("Not eligible for the admission in this program as per DOB"))
student_admission.maximum_age
and getdate(student_admission.maximum_age) < getdate(self.date_of_birth) if student_admission and student_admission.maximum_age and \
)): getdate(student_admission.maximum_age) > getdate(self.date_of_birth):
frappe.throw(_("Not eligible for the admission in this program as per DOB")) frappe.throw(_("Not eligible for the admission in this program as per DOB"))
def on_payment_authorized(self, *args, **kwargs): def on_payment_authorized(self, *args, **kwargs):
self.db_set('paid', 1) self.db_set('paid', 1)

View File

@ -273,7 +273,7 @@
"issingle": 1, "issingle": 1,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-06-30 08:21:51.390809", "modified": "2017-11-08 11:53:27.994112",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Schools", "module": "Schools",
"name": "Student Attendance Tool", "name": "Student Attendance Tool",
@ -306,17 +306,17 @@
"cancel": 0, "cancel": 0,
"create": 1, "create": 1,
"delete": 0, "delete": 0,
"email": 1, "email": 0,
"export": 0, "export": 0,
"if_owner": 0, "if_owner": 0,
"import": 0, "import": 0,
"permlevel": 0, "permlevel": 0,
"print": 1, "print": 0,
"read": 1, "read": 1,
"report": 0, "report": 0,
"role": "Academics User", "role": "Academics User",
"set_user_permissions": 0, "set_user_permissions": 0,
"share": 1, "share": 0,
"submit": 0, "submit": 0,
"write": 1 "write": 1
} }

View File

@ -7,6 +7,7 @@ import frappe
from frappe.model.document import Document from frappe.model.document import Document
from frappe import _ from frappe import _
from erpnext.schools.utils import validate_duplicate_student from erpnext.schools.utils import validate_duplicate_student
from frappe.utils import cint
class StudentGroup(Document): class StudentGroup(Document):
def validate(self): def validate(self):
@ -34,9 +35,13 @@ class StudentGroup(Document):
for d in self.students: for d in self.students:
if not frappe.db.get_value("Student", d.student, "enabled") and d.active: if not frappe.db.get_value("Student", d.student, "enabled") and d.active:
frappe.throw(_("{0} - {1} is inactive student".format(d.group_roll_number, d.student_name))) frappe.throw(_("{0} - {1} is inactive student".format(d.group_roll_number, d.student_name)))
if self.group_based_on == "Batch" and d.student not in students and frappe.defaults.get_defaults().validate_batch:
if (self.group_based_on == "Batch") and cint(frappe.defaults.get_defaults().validate_batch)\
and d.student not in students:
frappe.throw(_("{0} - {1} is not enrolled in the Batch {2}".format(d.group_roll_number, d.student_name, self.batch))) frappe.throw(_("{0} - {1} is not enrolled in the Batch {2}".format(d.group_roll_number, d.student_name, self.batch)))
if self.group_based_on == "Course" and d.student not in students and frappe.defaults.get_defaults().validate_course:
if (self.group_based_on == "Course") and cint(frappe.defaults.get_defaults().validate_course)\
and (d.student not in students):
frappe.throw(_("{0} - {1} is not enrolled in the Course {2}".format(d.group_roll_number, d.student_name, self.course))) frappe.throw(_("{0} - {1} is not enrolled in the Course {2}".format(d.group_roll_number, d.student_name, self.course)))
def validate_and_set_child_table_fields(self): def validate_and_set_child_table_fields(self):
@ -108,14 +113,14 @@ def fetch_students(doctype, txt, searchfield, start, page_len, filters):
students = ([d.student for d in enrolled_students if d.student not in student_group_student] students = ([d.student for d in enrolled_students if d.student not in student_group_student]
if enrolled_students else [""]) or [""] if enrolled_students else [""]) or [""]
return frappe.db.sql("""select name, title from tabStudent return frappe.db.sql("""select name, title from tabStudent
where name in ({0}) and `{1}` LIKE %s where name in ({0}) and (`{1}` LIKE %s or title LIKE %s)
order by idx desc, name order by idx desc, name
limit %s, %s""".format(", ".join(['%s']*len(students)), searchfield), limit %s, %s""".format(", ".join(['%s']*len(students)), searchfield),
tuple(students + ["%%%s%%" % txt, start, page_len])) tuple(students + ["%%%s%%" % txt, "%%%s%%" % txt, start, page_len]))
else: else:
return frappe.db.sql("""select name, title from tabStudent return frappe.db.sql("""select name, title from tabStudent
where `{0}` LIKE %s where `{0}` LIKE %s or title LIKE %s
order by idx desc, name order by idx desc, name
limit %s, %s""".format(searchfield), limit %s, %s""".format(searchfield),
tuple(["%%%s%%" % txt, start, page_len])) tuple(["%%%s%%" % txt, "%%%s%%" % txt, start, page_len]))

View File

@ -173,14 +173,16 @@ def get_column(assessment_criteria, total_maximum_score):
def get_chart_data(grades, assessment_criteria_list, kounter): def get_chart_data(grades, assessment_criteria_list, kounter):
grades = sorted(grades) grades = sorted(grades)
datasets = [] datasets = []
for grade in grades: for grade in grades:
tmp = [] tmp = frappe._dict({"values":[], "title": grade})
for ac in assessment_criteria_list: for criteria in assessment_criteria_list:
if grade in kounter[ac]: if grade in kounter[criteria]:
tmp.append(kounter[ac][grade]) tmp["values"].append(kounter[criteria][grade])
else: else:
tmp.append(0) tmp["values"].append(0)
datasets.append(tmp) datasets.append(tmp)
return { return {
"data": { "data": {
"labels": assessment_criteria_list, "labels": assessment_criteria_list,

View File

@ -3406,7 +3406,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2017-10-24 12:52:28.115742", "modified": "2017-11-03 05:31:56.636424",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Selling", "module": "Selling",
"name": "Sales Order", "name": "Sales Order",
@ -3543,5 +3543,5 @@
"timeline_field": "customer", "timeline_field": "customer",
"title_field": "title", "title_field": "title",
"track_changes": 1, "track_changes": 1,
"track_seen": 0 "track_seen": 1
} }

View File

@ -285,25 +285,67 @@ erpnext.pos.PointOfSale = class PointOfSale {
} }
setup_pos_profile() { setup_pos_profile() {
return new Promise((resolve) => {
const load_default = () => {
this.pos_profile = {
company: this.company,
currency: frappe.defaults.get_default('currency'),
selling_price_list: frappe.defaults.get_default('selling_price_list')
};
resolve();
}
const on_submit = ({ pos_profile }) => {
this.get_pos_profile_doc(pos_profile)
.then(doc => {
this.pos_profile = doc;
if (!this.pos_profile) {
load_default();
}
resolve();
});
}
frappe.call({
method: 'erpnext.accounts.doctype.pos_profile.pos_profile.get_pos_profiles_for_user'
}).then((r) => {
if (r && r.message) {
const pos_profiles = r.message.filter(a => a);
if (pos_profiles.length === 0) {
load_default();
} else if(pos_profiles.length === 1) {
// load profile directly
on_submit({pos_profile: pos_profiles[0]});
} else {
// ask prompt
frappe.prompt(
[{ fieldtype: 'Select', label: 'POS Profile', options: pos_profiles }],
on_submit,
__('Select POS Profile')
);
}
} else {
frappe.dom.unfreeze();
frappe.throw(__("POS Profile is required to use Point-of-Sale"));
}
});
});
}
get_pos_profile_doc(pos_profile_name) {
return new Promise(resolve => { return new Promise(resolve => {
frappe.call({ frappe.call({
method: 'erpnext.stock.get_item_details.get_pos_profile', method: 'erpnext.accounts.doctype.pos_profile.pos_profile.get_pos_profile',
args: { args: {
company: this.company pos_profile_name
},
callback: (r) => {
resolve(r.message);
} }
}).then(r => {
this.pos_profile = r.message;
if (!this.pos_profile) {
this.pos_profile = {
company: this.company,
currency: frappe.defaults.get_default('currency'),
selling_price_list: frappe.defaults.get_default('selling_price_list')
};
}
resolve();
}); });
}) });
} }
setup_company() { setup_company() {

View File

@ -47,9 +47,6 @@ class ItemGroup(NestedSet, WebsiteGenerator):
return self.route return self.route
def after_rename(self, olddn, newdn, merge=False):
NestedSet.after_rename(self, olddn, newdn, merge)
def on_trash(self): def on_trash(self):
NestedSet.on_trash(self) NestedSet.on_trash(self)
WebsiteGenerator.on_trash(self) WebsiteGenerator.on_trash(self)

View File

@ -24,6 +24,11 @@ frappe.ui.form.on('Batch', {
frm.trigger('make_dashboard'); frm.trigger('make_dashboard');
} }
}, },
item: (frm) => {
frappe.db.get_value('Item', {name: frm.doc.item}, 'has_expiry_date', (r) => {
frm.toggle_reqd('expiry_date', r.has_expiry_date);
});
},
make_dashboard: (frm) => { make_dashboard: (frm) => {
if(!frm.is_new()) { if(!frm.is_new()) {
frappe.call({ frappe.call({

View File

@ -3610,7 +3610,7 @@
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"menu_index": 0, "menu_index": 0,
"modified": "2017-09-19 11:21:59.084183", "modified": "2017-11-03 05:31:56.636424",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Delivery Note", "name": "Delivery Note",
@ -3727,5 +3727,5 @@
"timeline_field": "customer", "timeline_field": "customer",
"title_field": "title", "title_field": "title",
"track_changes": 1, "track_changes": 1,
"track_seen": 0 "track_seen": 1
} }

File diff suppressed because it is too large Load Diff

View File

@ -2,11 +2,13 @@
# License: GNU General Public License v3. See license.txt # License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe
from frappe.utils import flt, cint
from frappe import _
import frappe
from frappe import _
from frappe.model import no_value_fields
from frappe.model.document import Document from frappe.model.document import Document
from frappe.utils import cint, flt
class PackingSlip(Document): class PackingSlip(Document):
@ -84,11 +86,12 @@ class PackingSlip(Document):
* No. of Cases of this packing slip * No. of Cases of this packing slip
""" """
# also pick custom fields from delivery note
rows = [d.item_code for d in self.get("items")] rows = [d.item_code for d in self.get("items")]
custom_fields = ', '.join(['dni.`{0}`'.format(d.fieldname) for d in \ # also pick custom fields from delivery note
frappe.get_meta("Delivery Note Item").get_custom_fields()]) custom_fields = ', '.join(['dni.`{0}`'.format(d.fieldname)
for d in frappe.get_meta("Delivery Note Item").get_custom_fields()
if d.fieldtype not in no_value_fields])
if custom_fields: if custom_fields:
custom_fields = ', ' + custom_fields custom_fields = ', ' + custom_fields

View File

@ -64,6 +64,8 @@ class Warehouse(NestedSet):
where parent_warehouse = %s""", self.name) where parent_warehouse = %s""", self.name)
def before_rename(self, old_name, new_name, merge=False): def before_rename(self, old_name, new_name, merge=False):
super(Warehouse, self).before_rename(old_name, new_name, merge)
# Add company abbr if not provided # Add company abbr if not provided
new_warehouse = erpnext.encode_company_abbr(new_name, self.company) new_warehouse = erpnext.encode_company_abbr(new_name, self.company)
@ -77,12 +79,14 @@ class Warehouse(NestedSet):
return new_warehouse return new_warehouse
def after_rename(self, old_name, new_name, merge=False): def after_rename(self, old_name, new_name, merge=False):
super(Warehouse, self).after_rename(old_name, new_name, merge)
new_warehouse_name = self.get_new_warehouse_name_without_abbr(new_name) new_warehouse_name = self.get_new_warehouse_name_without_abbr(new_name)
self.db_set("warehouse_name", new_warehouse_name) self.db_set("warehouse_name", new_warehouse_name)
if merge: if merge:
self.recalculate_bin_qty(new_name) self.recalculate_bin_qty(new_name)
def get_new_warehouse_name_without_abbr(self, name): def get_new_warehouse_name_without_abbr(self, name):
company_abbr = frappe.db.get_value("Company", self.company, "abbr") company_abbr = frappe.db.get_value("Company", self.company, "abbr")
parts = name.rsplit(" - ", 1) parts = name.rsplit(" - ", 1)

View File

@ -1,5 +1,5 @@
{ {
"add_total_row": 0, "add_total_row": 1,
"apply_user_permissions": 1, "apply_user_permissions": 1,
"creation": "2013-02-22 18:01:55", "creation": "2013-02-22 18:01:55",
"disabled": 0, "disabled": 0,
@ -7,7 +7,7 @@
"doctype": "Report", "doctype": "Report",
"idx": 3, "idx": 3,
"is_standard": "Yes", "is_standard": "Yes",
"modified": "2017-09-18 12:28:49.322622", "modified": "2017-11-06 13:05:38.965229",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Ordered Items To Be Delivered", "name": "Ordered Items To Be Delivered",

View File

@ -4,7 +4,7 @@ frappe.ui.form.on("Issue", {
}, },
"refresh": function(frm) { "refresh": function(frm) {
if(frm.doc.status==="Open") { if(frm.doc.status!=="Closed") {
frm.add_custom_button(__("Close"), function() { frm.add_custom_button(__("Close"), function() {
frm.set_value("status", "Closed"); frm.set_value("status", "Closed");
frm.save(); frm.save();

View File

@ -50,8 +50,8 @@ erpnext/schools/doctype/room/test_room.js
erpnext/schools/doctype/instructor/test_instructor.js erpnext/schools/doctype/instructor/test_instructor.js
erpnext/stock/doctype/warehouse/test_warehouse.js erpnext/stock/doctype/warehouse/test_warehouse.js
erpnext/manufacturing/doctype/production_order/test_production_order.js #long erpnext/manufacturing/doctype/production_order/test_production_order.js #long
erpnext/selling/page/point_of_sale/tests/test_point_of_sale.js
erpnext/accounts/page/pos/test_pos.js erpnext/accounts/page/pos/test_pos.js
erpnext/selling/page/point_of_sale/tests/test_point_of_sale.js
erpnext/selling/doctype/product_bundle/test_product_bundle.js erpnext/selling/doctype/product_bundle/test_product_bundle.js
erpnext/stock/doctype/delivery_note/test_delivery_note.js erpnext/stock/doctype/delivery_note/test_delivery_note.js
erpnext/stock/doctype/material_request/tests/test_material_request.js erpnext/stock/doctype/material_request/tests/test_material_request.js
@ -133,3 +133,4 @@ erpnext/restaurant/doctype/restaurant/test_restaurant.js
erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.js erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.js
erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js
erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.js erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.js
erpnext/projects/doctype/task/tests/test_task_tree.js