\n\t{{ company }}
\n\t{{ __(\"POS No : \") }}{{offline_pos_name}}
\n
\n\t{{ __(\"Date\") }}: {{ dateutil.global_date_format(posting_date) }}
\n
| {{ __(\"Item\") }} | \n\t\t\t{{ __(\"Qty\") }} | \n\t\t\t{{ __(\"Amount\") }} | \n\t\t
|---|---|---|
| \n\t\t\t\t{{ item.item_name }}\n\t\t\t | \n\t\t\t{{ format_number(item.qty, precision(\"difference\")) }} @ {{ format_currency(item.rate, currency) }} | \n\t\t\t{{ format_currency(item.amount, currency) }} | \n\t\t
| \n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t | \n\t\t
| \n\t\t\t\t{{ row.description }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t | \n\t\t
| \n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t | \n\t\t
| \n\t\t\t\t{{ __(\"Grand Total\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t | \n\t\t
| \n\t\t\t\t{{ __(\"Paid Amount\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t | \n\t\t
{{ __(\"Thank you, please visit again.\") }}
", + "html": "\n\n\n\t{{ company }}
\n\t{{ __(\"POS No : \") }}{{offline_pos_name}}
\n
\n\t{{ __(\"Date\") }}: {{ dateutil.global_date_format(posting_date) }}
\n
| {{ __(\"Item\") }} | \n\t\t\t{{ __(\"Qty\") }} | \n\t\t\t{{ __(\"Amount\") }} | \n\t\t
|---|---|---|
| \n\t\t\t\t{{ item.item_name }}\n\t\t\t | \n\t\t\t{{ format_number(item.qty, precision(\"difference\")) }} @ {{ format_currency(item.rate, currency) }} | \n\t\t\t{{ format_currency(item.amount, currency) }} | \n\t\t
| \n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t | \n\t\t
| \n\t\t\t\t{{ row.description }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t | \n\t\t
| \n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t | \n\t\t
| \n\t\t\t\t{{ __(\"Grand Total\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t | \n\t\t
| \n\t\t\t\t{{ __(\"Paid Amount\") }}\n\t\t\t | \n\t\t\t\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t | \n\t\t
{{ terms }}
\n{{ __(\"Thank you, please visit again.\") }}
", "idx": 0, "line_breaks": 0, - "modified": "2016-12-27 17:22:17.391673", + "modified": "2017-01-12 14:56:12.571032", "modified_by": "Administrator", "module": "Accounts", "name": "Point of Sale", diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py index 182878af37a..7a776f57e16 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.py +++ b/erpnext/accounts/report/cash_flow/cash_flow.py @@ -10,7 +10,8 @@ from erpnext.accounts.utils import get_fiscal_year def execute(filters=None): - period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, filters.periodicity) + period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year, + filters.periodicity) operation_accounts = { "section_name": "Operations", @@ -103,7 +104,7 @@ def get_account_type_based_data(company, account_type, period_list, accumulated_ data = {} total = 0 for period in period_list: - start_date = get_start_date(period, accumulated_values) + start_date = get_start_date(period, accumulated_values, company) gl_sum = frappe.db.sql_list(""" select sum(credit) - sum(debit) from `tabGL Entry` @@ -126,10 +127,10 @@ def get_account_type_based_data(company, account_type, period_list, accumulated_ data["total"] = total return data -def get_start_date(period, accumulated_values): +def get_start_date(period, accumulated_values, company): start_date = period["year_start_date"] if accumulated_values: - start_date = get_fiscal_year(period.to_date)[1] + start_date = get_fiscal_year(period.to_date, company=company)[1] return start_date diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index bc4a220faa1..c897d1ca61e 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -3,10 +3,8 @@ from __future__ import unicode_literals import frappe -import math from frappe import _ -from frappe.utils import (flt, getdate, get_first_day, get_last_day, date_diff, - add_months, add_days, formatdate, cint) +from frappe.utils import flt, getdate, get_first_day, add_months, add_days, formatdate def get_period_list(from_fiscal_year, to_fiscal_year, periodicity): """Get a list of dict {"from_date": from_date, "to_date": to_date, "key": key, "label": label} @@ -149,7 +147,6 @@ def calculate_values(accounts_by_name, gl_entries_by_account, period_list, accum def get_date_fiscal_year(date): from erpnext.accounts.utils import get_fiscal_year - return get_fiscal_year(date)[0] def accumulate_values_into_parents(accounts, accounts_by_name, period_list, accumulated_values): diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 8e59d8f99ba..c35ca8222b2 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -20,32 +20,63 @@ def get_fiscal_year(date=None, fiscal_year=None, label="Date", verbose=1, compan return get_fiscal_years(date, fiscal_year, label, verbose, company, as_dict=as_dict)[0] def get_fiscal_years(transaction_date=None, fiscal_year=None, label="Date", verbose=1, company=None, as_dict=False): - # if year start date is 2012-04-01, year end date should be 2013-03-31 (hence subdate) - cond = " disabled = 0" - if fiscal_year: - cond += " and fy.name = %(fiscal_year)s" - else: - cond += " and %(transaction_date)s >= fy.year_start_date and %(transaction_date)s <= fy.year_end_date" + fiscal_years = frappe.cache().hget("fiscal_years", company) or [] + + if not fiscal_years: + # if year start date is 2012-04-01, year end date should be 2013-03-31 (hence subdate) + cond = "" + if fiscal_year: + cond += " and fy.name = {0}".format(frappe.db.escape(fiscal_year)) + if company: + cond += """ + and (not exists (select name + from `tabFiscal Year Company` fyc + where fyc.parent = fy.name) + or exists(select company + from `tabFiscal Year Company` fyc + where fyc.parent = fy.name + and fyc.company=%(company)s) + ) + """ - if company: - cond += """ and (not exists(select name from `tabFiscal Year Company` fyc where fyc.parent = fy.name) - or exists(select company from `tabFiscal Year Company` fyc where fyc.parent = fy.name and fyc.company=%(company)s ))""" + fiscal_years = frappe.db.sql(""" + select + fy.name, fy.year_start_date, fy.year_end_date + from + `tabFiscal Year` fy + where + disabled = 0 {0} + order by + fy.year_start_date desc""".format(cond), { + "company": company + }, as_dict=True) + + frappe.cache().hset("fiscal_years", company, fiscal_years) - fy = frappe.db.sql("""select fy.name, fy.year_start_date, fy.year_end_date from `tabFiscal Year` fy - where %s order by fy.year_start_date desc""" % cond, { - "fiscal_year": fiscal_year, - "transaction_date": transaction_date, - "company": company - }, as_dict=as_dict) + if transaction_date: + transaction_date = getdate(transaction_date) - if not fy: - error_msg = _("""{0} {1} not in any active Fiscal Year. For more details check {2}.""").format(label, formatdate(transaction_date), "https://frappe.github.io/erpnext/user/manual/en/accounts/articles/fiscal-year-error") - if verbose==1: frappe.msgprint(error_msg) - raise FiscalYearError, error_msg - return fy + for fy in fiscal_years: + matched = False + if fiscal_year and fy.name == fiscal_year: + matched = True -def validate_fiscal_year(date, fiscal_year, label=_("Date"), doc=None): - years = [f[0] for f in get_fiscal_years(date, label=label)] + if (transaction_date and getdate(fy.year_start_date) <= transaction_date + and getdate(fy.year_end_date) >= transaction_date): + matched = True + + if matched: + if as_dict: + return (fy,) + else: + return ((fy.name, fy.year_start_date, fy.year_end_date),) + + error_msg = _("""{0} {1} not in any active Fiscal Year.""").format(label, formatdate(transaction_date)) + if verbose==1: frappe.msgprint(error_msg) + raise FiscalYearError, error_msg + +def validate_fiscal_year(date, fiscal_year, company, label=_("Date"), doc=None): + years = [f[0] for f in get_fiscal_years(date, label=label, company=company)] if fiscal_year not in years: if doc: doc.fiscal_year = years[0] @@ -206,9 +237,12 @@ def get_count_on(account, fieldname, date): @frappe.whitelist() def add_ac(args=None): + from frappe.desk.treeview import make_tree_args + if not args: args = frappe.local.form_dict - args.pop("cmd") + + args = make_tree_args(**args) ac = frappe.new_doc("Account") @@ -233,9 +267,12 @@ def add_ac(args=None): @frappe.whitelist() def add_cc(args=None): + from frappe.desk.treeview import make_tree_args + if not args: args = frappe.local.form_dict - args.pop("cmd") + + args = make_tree_args(**args) cc = frappe.new_doc("Cost Center") cc.update(args) diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js index 5d74760392b..921c3b57eac 100644 --- a/erpnext/buying/doctype/purchase_common/purchase_common.js +++ b/erpnext/buying/doctype/purchase_common/purchase_common.js @@ -50,13 +50,9 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ }); } - $.each([["supplier", "supplier"], - ["contact_person", "supplier_filter"], - ["supplier_address", "supplier_filter"]], - function(i, opts) { - if(me.frm.fields_dict[opts[0]]) - me.frm.set_query(opts[0], erpnext.queries[opts[1]]); - }); + me.frm.set_query('supplier', erpnext.queries.supplier); + me.frm.set_query('contact_person', erpnext.queries.contact_query); + me.frm.set_query('supplier_address', erpnext.queries.address_query); if(this.frm.fields_dict.supplier) { this.frm.set_query("supplier", function() { @@ -79,6 +75,8 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ }, refresh: function(doc) { + frappe.contact_link = {doc: this.frm.doc, fieldname: 'supplier', doctype: 'Supplier'}; + this.frm.toggle_display("supplier_name", (this.frm.doc.supplier_name && this.frm.doc.supplier_name!==this.frm.doc.supplier)); diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index 15356fd471b..f2f04fe88cc 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -226,18 +226,6 @@ cur_frm.cscript.update_status= function(label, status){ }) } -cur_frm.fields_dict['supplier_address'].get_query = function(doc, cdt, cdn) { - return { - filters: {'supplier': doc.supplier} - } -} - -cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) { - return { - filters: {'supplier': doc.supplier} - } -} - cur_frm.fields_dict['items'].grid.get_field('project').get_query = function(doc, cdt, cdn) { return { filters:[ diff --git a/erpnext/buying/doctype/supplier/supplier.js b/erpnext/buying/doctype/supplier/supplier.js index b176e000cd8..98087184468 100644 --- a/erpnext/buying/doctype/supplier/supplier.js +++ b/erpnext/buying/doctype/supplier/supplier.js @@ -16,6 +16,8 @@ frappe.ui.form.on("Supplier", { }); }, refresh: function(frm) { + frappe.contact_link = {doc: frm.doc, fieldname: 'name', doctype: 'Supplier'} + if(frappe.defaults.get_default("supp_master_name")!="Naming Series") { frm.toggle_display("naming_series", false); } else { diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py index 3677ee296b5..9eaaad1e61f 100644 --- a/erpnext/buying/doctype/supplier/supplier.py +++ b/erpnext/buying/doctype/supplier/supplier.py @@ -6,7 +6,9 @@ import frappe import frappe.defaults from frappe import msgprint, _ from frappe.model.naming import make_autoname -from erpnext.utilities.address_and_contact import load_address_and_contact +from erpnext.utilities.address_and_contact import (load_address_and_contact, + delete_contact_and_address) + from erpnext.utilities.transaction_base import TransactionBase from erpnext.accounts.party import validate_party_accounts, get_timeline_data # keep this from erpnext.accounts.party_status import get_party_status @@ -46,21 +48,10 @@ class Supplier(TransactionBase): else: self.name = make_autoname(self.naming_series + '.#####') - def update_address(self): - frappe.db.sql("""update `tabAddress` set supplier_name=%s, modified=NOW() - where supplier=%s""", (self.supplier_name, self.name)) - - def update_contact(self): - frappe.db.sql("""update `tabContact` set supplier_name=%s, modified=NOW() - where supplier=%s""", (self.supplier_name, self.name)) - def on_update(self): if not self.naming_series: self.naming_series = '' - self.update_address() - self.update_contact() - def validate(self): #validation for Naming Series mandatory field... if frappe.defaults.get_global_default('supp_master_name') == 'Naming Series': @@ -78,28 +69,9 @@ class Supplier(TransactionBase): else: return '' - def delete_supplier_address(self): - for rec in frappe.db.sql("select * from `tabAddress` where supplier=%s", (self.name,), as_dict=1): - frappe.db.sql("delete from `tabAddress` where name=%s",(rec['name'])) - - def delete_supplier_contact(self): - for contact in frappe.db.sql_list("""select name from `tabContact` - where supplier=%s""", self.name): - frappe.delete_doc("Contact", contact) - def on_trash(self): - self.delete_supplier_address() - self.delete_supplier_contact() + delete_contact_and_address('Supplier', self.name) def after_rename(self, olddn, newdn, merge=False): - set_field = '' if frappe.defaults.get_global_default('supp_master_name') == 'Supplier Name': frappe.db.set(self, "supplier_name", newdn) - self.update_contact() - set_field = ", supplier_name=%(newdn)s" - self.update_supplier_address(newdn, set_field) - - def update_supplier_address(self, newdn, set_field): - frappe.db.sql("""update `tabAddress` set address_title=%(newdn)s - {set_field} where supplier=%(newdn)s"""\ - .format(set_field=set_field), ({"newdn": newdn})) \ No newline at end of file diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js index fc9cc3bc28c..b3bdeb01a7a 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js @@ -59,15 +59,3 @@ cur_frm.fields_dict['items'].grid.get_field('project').get_query = ] } } - -cur_frm.fields_dict['supplier_address'].get_query = function(doc, cdt, cdn) { - return { - filters:{'supplier': doc.supplier} - } -} - -cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) { - return { - filters:{'supplier': doc.supplier} - } -} diff --git a/erpnext/config/hr.py b/erpnext/config/hr.py index 55363abe802..75ebd27cd48 100644 --- a/erpnext/config/hr.py +++ b/erpnext/config/hr.py @@ -232,7 +232,7 @@ def get_data(): { "type": "report", "is_query_report": True, - "name": "Monthly Salary Register", + "name": "Salary Register", "doctype": "Salary Slip" }, { diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 554529c6f6c..da0591134e0 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -113,7 +113,7 @@ class AccountsController(TransactionBase): date_field = "transaction_date" if date_field and self.get(date_field): - validate_fiscal_year(self.get(date_field), self.fiscal_year, + validate_fiscal_year(self.get(date_field), self.fiscal_year, self.company, self.meta.get_label(date_field), self) def validate_due_date(self): diff --git a/erpnext/controllers/js/contact_address_common.js b/erpnext/controllers/js/contact_address_common.js deleted file mode 100644 index c51ff468c34..00000000000 --- a/erpnext/controllers/js/contact_address_common.js +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt - -cur_frm.cscript.onload = function(doc, cdt, cdn) { - cur_frm.add_fetch('customer', 'customer_name', 'customer_name'); - cur_frm.add_fetch('supplier', 'supplier_name', 'supplier_name'); - - cur_frm.fields_dict.customer.get_query = erpnext.queries.customer; - cur_frm.fields_dict.supplier.get_query = erpnext.queries.supplier; - - if(cur_frm.fields_dict.lead) { - cur_frm.fields_dict.lead.get_query = erpnext.queries.lead; - cur_frm.add_fetch('lead', 'lead_name', 'lead_name'); - } - - if(doc.__islocal) { - var last_route = frappe.route_history.slice(-2, -1)[0]; - if(last_route && last_route[0]==="Form") { - var doctype = last_route[1], - docname = last_route.slice(2).join("/"); - - if(["Customer", "Quotation", "Sales Order", "Sales Invoice", "Delivery Note", - "Installation Note", "Opportunity", "Warranty Claim", "Maintenance Visit", - "Maintenance Schedule"] - .indexOf(doctype)!==-1) { - var refdoc = frappe.get_doc(doctype, docname); - if((refdoc.doctype == "Quotation" && refdoc.quotation_to=="Customer") || - (refdoc.doctype == "Opportunity" && refdoc.enquiry_from=="Customer") || - !in_list(["Opportunity", "Quotation"], doctype)) { - cur_frm.set_value("customer", refdoc.customer || refdoc.name); - cur_frm.set_value("customer_name", refdoc.customer_name); - if(cur_frm.doc.doctype==="Address") - cur_frm.set_value("address_title", cur_frm.doc.customer_name); - } - } - else if(["Supplier", "Supplier Quotation", "Purchase Order", "Purchase Invoice", "Purchase Receipt"] - .indexOf(doctype)!==-1) { - var refdoc = frappe.get_doc(doctype, docname); - cur_frm.set_value("supplier", refdoc.supplier || refdoc.name); - cur_frm.set_value("supplier_name", refdoc.supplier_name); - if(cur_frm.doc.doctype==="Address") - cur_frm.set_value("address_title", cur_frm.doc.supplier_name); - } - else if(["Lead", "Opportunity", "Quotation"] - .indexOf(doctype)!==-1) { - var refdoc = frappe.get_doc(doctype, docname); - - if((refdoc.doctype == "Quotation" && refdoc.quotation_to=="Lead") || - (refdoc.doctype == "Opportunity" && refdoc.enquiry_from=="Lead") || (doctype=="Lead")) { - cur_frm.set_value("lead", refdoc.lead || refdoc.name); - cur_frm.set_value("lead_name", refdoc.customer_name || refdoc.company_name || refdoc.lead_name); - if(cur_frm.doc.doctype==="Address") - cur_frm.set_value("address_title", cur_frm.doc.lead_name); - } - } - else if(doctype == "Sales Partner") { - cur_frm.set_value("sales_partner", docname); - } - } - } -} diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 98390ff2d21..cc3f27724e2 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -3,32 +3,9 @@ from __future__ import unicode_literals import frappe -from frappe.desk.reportview import get_match_cond -from frappe.model.db_query import DatabaseQuery +from frappe.desk.reportview import get_match_cond, get_filters_cond from frappe.utils import nowdate -def get_filters_cond(doctype, filters, conditions): - if filters: - flt = filters - if isinstance(filters, dict): - filters = filters.items() - flt = [] - for f in filters: - if isinstance(f[1], basestring) and f[1][0] == '!': - flt.append([doctype, f[0], '!=', f[1][1:]]) - else: - value = frappe.db.escape(f[1]) if isinstance(f[1], basestring) else f[1] - flt.append([doctype, f[0], '=', value]) - - query = DatabaseQuery(doctype) - query.filters = flt - query.conditions = conditions - query.build_filter_conditions(flt, conditions) - - cond = ' and ' + ' and '.join(query.conditions) - else: - cond = '' - return cond # searches for active employees def employee_query(doctype, txt, searchfield, start, page_len, filters): @@ -88,7 +65,7 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters): fields = ["name", "customer_group", "territory"] else: fields = ["name", "customer_name", "customer_group", "territory"] - + meta = frappe.get_meta("Customer") fields = fields + [f for f in meta.get_search_fields() if not f in fields] diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 096bb2df71b..4fbee58c842 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -103,6 +103,8 @@ class StatusUpdater(Document): def set_status(self, update=False, status=None, update_modified=True): if self.is_new(): + if self.get('amended_from'): + self.status = 'Draft' return if self.doctype in status_map: diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index f0c8dbfc164..3e900b28140 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cint, flt, cstr +from frappe.utils import cint, flt, cstr, now from frappe import msgprint, _ import frappe.defaults from erpnext.accounts.utils import get_fiscal_year @@ -15,7 +15,7 @@ class StockController(AccountsController): super(StockController, self).validate() self.validate_inspection() - def make_gl_entries(self, repost_future_gle=True): + def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False): if self.docstatus == 2: delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name) @@ -23,8 +23,9 @@ class StockController(AccountsController): warehouse_account = get_warehouse_account() if self.docstatus==1: - gl_entries = self.get_gl_entries(warehouse_account) - make_gl_entries(gl_entries) + if not gl_entries: + gl_entries = self.get_gl_entries(warehouse_account) + make_gl_entries(gl_entries, from_repost=from_repost) if repost_future_gle: items, warehouses = self.get_items_and_warehouses() @@ -224,7 +225,7 @@ class StockController(AccountsController): def make_gl_entries_on_cancel(self, repost_future_gle=True): if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s and voucher_no=%s""", (self.doctype, self.name)): - self.make_gl_entries(repost_future_gle) + self.make_gl_entries(repost_future_gle=repost_future_gle) def get_serialized_items(self): serialized_items = [] @@ -308,7 +309,7 @@ def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for if expected_gle: if not existing_gle or not compare_existing_and_expected_gle(existing_gle, expected_gle): _delete_gl_entries(voucher_type, voucher_no) - voucher_obj.make_gl_entries(repost_future_gle=False) + voucher_obj.make_gl_entries(gl_entries=expected_gle, repost_future_gle=False, from_repost=True) else: _delete_gl_entries(voucher_type, voucher_no) @@ -363,10 +364,14 @@ def get_voucherwise_gl_entries(future_stock_vouchers, posting_date): return gl_entries def get_warehouse_account(): - warehouse_account = frappe._dict() + if not frappe.flags.warehouse_account_map: + warehouse_account = frappe._dict() - for d in frappe.db.sql("""select warehouse, name, account_currency from tabAccount - where account_type = 'Stock' and (warehouse is not null and warehouse != '' - and is_group != 1) and is_group=0 """, as_dict=1): - warehouse_account.setdefault(d.warehouse, d) - return warehouse_account + for d in frappe.db.sql("""select warehouse, name, account_currency from tabAccount + where account_type = 'Stock' and (warehouse is not null and warehouse != '' + and is_group != 1) and is_group=0 """, as_dict=1): + warehouse_account.setdefault(d.warehouse, d) + + frappe.flags.warehouse_account_map = warehouse_account + + return frappe.flags.warehouse_account_map diff --git a/erpnext/crm/doctype/opportunity/opportunity.js b/erpnext/crm/doctype/opportunity/opportunity.js index 21fba7b1e72..d7d412a1e12 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.js +++ b/erpnext/crm/doctype/opportunity/opportunity.js @@ -6,9 +6,14 @@ frappe.provide("erpnext.crm"); cur_frm.email_field = "contact_email"; frappe.ui.form.on("Opportunity", { customer: function(frm) { + frm.trigger('set_contact_link'); erpnext.utils.get_party_details(frm); }, + lead: function(frm) { + frm.trigger('set_contact_link'); + }, + customer_address: function(frm, cdt, cdn) { erpnext.utils.get_address_display(frm, 'customer_address', 'address_display', false); }, @@ -23,6 +28,8 @@ frappe.ui.form.on("Opportunity", { refresh: function(frm) { var doc = frm.doc; frm.events.enquiry_from(frm); + frm.trigger('set_contact_link'); + if(doc.status!=="Lost") { if(doc.with_items){ frm.add_custom_button(__('Supplier Quotation'), @@ -35,7 +42,7 @@ frappe.ui.form.on("Opportunity", { cur_frm.cscript.create_quotation, __("Make")); frm.page.set_inner_btn_group_as_primary(__("Make")); - + if(doc.status!=="Quotation") { frm.add_custom_button(__('Lost'), cur_frm.cscript['Declare Opportunity Lost']); @@ -43,6 +50,14 @@ frappe.ui.form.on("Opportunity", { } }, + set_contact_link: function(frm) { + if(frm.doc.customer) { + frappe.contact_link = {doc: frm.doc, fieldname: 'customer', doctype: 'Customer'} + } else if(frm.doc.lead) { + frappe.contact_link = {doc: frm.doc, fieldname: 'lead', doctype: 'Lead'} + } + }, + make_supplier_quotation: function(frm) { frappe.model.open_mapped_doc({ method: "erpnext.crm.doctype.opportunity.opportunity.make_supplier_quotation", @@ -62,7 +77,7 @@ erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({ if(!this.frm.doc.status) set_multiple(this.frm.doc.doctype, this.frm.doc.name, { status:'Open' }); if(!this.frm.doc.company && frappe.defaults.get_user_default("Company")) - set_multiple(this.frm.doc.doctype, this.frm.doc.name, + set_multiple(this.frm.doc.doctype, this.frm.doc.name, { company:frappe.defaults.get_user_default("Company") }); this.setup_queries(); @@ -75,10 +90,7 @@ erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({ this.frm.set_query("contact_by", erpnext.queries.user); } - this.frm.set_query("customer_address", function() { - if(me.frm.doc.lead) return {filters: { lead: me.frm.doc.lead } }; - else if(me.frm.doc.customer) return {filters: { customer: me.frm.doc.customer } }; - }); + me.frm.set_query('customer_address', erpnext.queries.address_query); this.frm.set_query("item_code", "items", function() { return { diff --git a/erpnext/demo/data/address.json b/erpnext/demo/data/address.json index be4d5ecc410..7618c2cf337 100644 --- a/erpnext/demo/data/address.json +++ b/erpnext/demo/data/address.json @@ -1,245 +1,218 @@ [ { - "address_line1": "254 Theotokopoulou Str.", - "address_type": "Office", - "city": "Larnaka", - "country": "Cyprus", - "customer": "Adaptas", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "254 Theotokopoulou Str.", + "address_type": "Office", + "city": "Larnaka", + "country": "Cyprus", + "links": [{"link_doctype": "Customer", "link_name": "Adaptas"}], + "phone": "23566775757" + }, { - "address_line1": "R Patr\u00e3o Caramelho 116", - "address_type": "Office", - "city": "Fajozes", - "country": "Portugal", - "customer": "Asian Fusion", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "R Patr\u00e3o Caramelho 116", + "address_type": "Office", + "city": "Fajozes", + "country": "Portugal", + "links": [{"link_doctype": "Customer", "link_name": "Asian Fusion"}], + "phone": "23566775757" + }, { - "address_line1": "30 Fulford Road", - "address_type": "Office", - "city": "PENTRE-PIOD", - "country": "United Kingdom", - "customer": "Asian Junction", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "30 Fulford Road", + "address_type": "Office", + "city": "PENTRE-PIOD", + "country": "United Kingdom", + "links": [{"link_doctype": "Customer", "link_name": "Asian Junction"}], + "phone": "23566775757" + }, { - "address_line1": "Schoenebergerstrasse 13", - "address_type": "Office", - "city": "Raschau", - "country": "Germany", - "customer": "Big D Supermarkets", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "Schoenebergerstrasse 13", + "address_type": "Office", + "city": "Raschau", + "country": "Germany", + "links": [{"link_doctype": "Customer", "link_name": "Big D Supermarkets"}], + "phone": "23566775757" + }, { - "address_line1": "Hoheluftchaussee 43", - "address_type": "Office", - "city": "Kieritzsch", - "country": "Germany", - "customer": "Buttrey Food & Drug", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "Hoheluftchaussee 43", + "address_type": "Office", + "city": "Kieritzsch", + "country": "Germany", + "links": [{"link_doctype": "Customer", "link_name": "Buttrey Food & Drug"}], + "phone": "23566775757" + }, { - "address_line1": "R Cimo Vila 6", - "address_type": "Office", - "city": "Rebordosa", - "country": "Portugal", - "customer": "Chi-Chis", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "R Cimo Vila 6", + "address_type": "Office", + "city": "Rebordosa", + "country": "Portugal", + "links": [{"link_doctype": "Customer", "link_name": "Chi-Chis"}], + "phone": "23566775757" + }, { - "address_line1": "R 5 Outubro 9", - "address_type": "Office", - "city": "Quinta Nova S\u00e3o Domingos", - "country": "Portugal", - "customer": "Choices", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "R 5 Outubro 9", + "address_type": "Office", + "city": "Quinta Nova S\u00e3o Domingos", + "country": "Portugal", + "links": [{"link_doctype": "Customer", "link_name": "Choices"}], + "phone": "23566775757" + }, { - "address_line1": "Avenida Macambira 953", - "address_type": "Office", - "city": "Goi\u00e2nia", - "country": "Brazil", - "customer": "Consumers and Consumers Express", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "Avenida Macambira 953", + "address_type": "Office", + "city": "Goi\u00e2nia", + "country": "Brazil", + "links": [{"link_doctype": "Customer", "link_name": "Consumers and Consumers Express"}], + "phone": "23566775757" + }, { - "address_line1": "2342 Goyeau Ave", - "address_type": "Office", - "city": "Windsor", - "country": "Canada", - "customer": "Crafts Canada", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "2342 Goyeau Ave", + "address_type": "Office", + "city": "Windsor", + "country": "Canada", + "links": [{"link_doctype": "Customer", "link_name": "Crafts Canada"}], + "phone": "23566775757" + }, { - "address_line1": "Laukaantie 82", - "address_type": "Office", - "city": "KOKKOLA", - "country": "Finland", - "customer": "Endicott Shoes", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "Laukaantie 82", + "address_type": "Office", + "city": "KOKKOLA", + "country": "Finland", + "links": [{"link_doctype": "Customer", "link_name": "Endicott Shoes"}], + "phone": "23566775757" + }, { - "address_line1": "9 Brown Street", - "address_type": "Office", - "city": "PETERSHAM", - "country": "Australia", - "customer": "Fayva", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "9 Brown Street", + "address_type": "Office", + "city": "PETERSHAM", + "country": "Australia", + "links": [{"link_doctype": "Customer", "link_name": "Fayva"}], + "phone": "23566775757" + }, { - "address_line1": "Via Donnalbina 41", - "address_type": "Office", - "city": "Cala Gonone", - "country": "Italy", - "customer": "Intelacard", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "Via Donnalbina 41", + "address_type": "Office", + "city": "Cala Gonone", + "country": "Italy", + "links": [{"link_doctype": "Customer", "link_name": "Intelacard"}], + "phone": "23566775757" + }, { - "address_line1": "Liljerum Grenadj\u00e4rtorpet 69", - "address_type": "Office", - "city": "TOMTEBODA", - "country": "Sweden", - "customer": "Landskip Yard Care", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "Liljerum Grenadj\u00e4rtorpet 69", + "address_type": "Office", + "city": "TOMTEBODA", + "country": "Sweden", + "links": [{"link_doctype": "Customer", "link_name": "Landskip Yard Care"}], + "phone": "23566775757" + }, { - "address_line1": "72 Bishopgate Street", - "address_type": "Office", - "city": "SEAHAM", - "country": "United Kingdom", - "customer": "Life Plan Counselling", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "72 Bishopgate Street", + "address_type": "Office", + "city": "SEAHAM", + "country": "United Kingdom", + "links": [{"link_doctype": "Customer", "link_name": "Life Plan Counselling"}], + "phone": "23566775757" + }, { - "address_line1": "\u03a3\u03ba\u03b1\u03c6\u03af\u03b4\u03b9\u03b1 105", - "address_type": "Office", - "city": "\u03a0\u0391\u03a1\u0395\u039a\u039a\u039b\u0397\u03a3\u0399\u0391", - "country": "Cyprus", - "customer": "Mr Fables", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "\u03a3\u03ba\u03b1\u03c6\u03af\u03b4\u03b9\u03b1 105", + "address_type": "Office", + "city": "\u03a0\u0391\u03a1\u0395\u039a\u039a\u039b\u0397\u03a3\u0399\u0391", + "country": "Cyprus", + "links": [{"link_doctype": "Customer", "link_name": "Mr Fables"}], + "phone": "23566775757" + }, { - "address_line1": "Mellemvej 7", - "address_type": "Office", - "city": "Aabybro", - "country": "Denmark", - "customer": "Nelson Brothers", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "Mellemvej 7", + "address_type": "Office", + "city": "Aabybro", + "country": "Denmark", + "links": [{"link_doctype": "Customer", "link_name": "Nelson Brothers"}], + "phone": "23566775757" + }, { - "address_line1": "Plougg\u00e5rdsvej 98", - "address_type": "Office", - "city": "Karby", - "country": "Denmark", - "customer": "Netobill", - "phone": "23566775757", - "supplier": null - }, + "address_line1": "Plougg\u00e5rdsvej 98", + "address_type": "Office", + "city": "Karby", + "country": "Denmark", + "links": [{"link_doctype": "Customer", "link_name": "Netobill"}], + "phone": "23566775757" + }, { - "address_line1": "176 Michalakopoulou Street", - "address_type": "Office", - "city": "Agio Georgoudi", - "country": "Cyprus", - "customer": null, - "phone": "23566775757", - "supplier": "Helios Air" - }, + "address_line1": "176 Michalakopoulou Street", + "address_type": "Office", + "city": "Agio Georgoudi", + "country": "Cyprus", + "phone": "23566775757", + "links": [{"link_doctype": "Supplier", "link_name": "Helios Air"}] + }, { - "address_line1": "Fibichova 1102", - "address_type": "Office", - "city": "Kokor\u00edn", - "country": "Czech Republic", - "customer": null, - "phone": "23566775757", - "supplier": "Ks Merchandise" - }, + "address_line1": "Fibichova 1102", + "address_type": "Office", + "city": "Kokor\u00edn", + "country": "Czech Republic", + "phone": "23566775757", + "links": [{"link_doctype": "Supplier", "link_name": "Ks Merchandise"}] + }, { - "address_line1": "Zahradn\u00ed 888", - "address_type": "Office", - "city": "Cecht\u00edn", - "country": "Czech Republic", - "customer": null, - "phone": "23566775757", - "supplier": "HomeBase" - }, + "address_line1": "Zahradn\u00ed 888", + "address_type": "Office", + "city": "Cecht\u00edn", + "country": "Czech Republic", + "phone": "23566775757", + "links": [{"link_doctype": "Supplier", "link_name": "HomeBase"}] + }, { - "address_line1": "ul. Grochowska 94", - "address_type": "Office", - "city": "Warszawa", - "country": "Poland", - "customer": null, - "phone": "23566775757", - "supplier": "Scott Ties" - }, + "address_line1": "ul. Grochowska 94", + "address_type": "Office", + "city": "Warszawa", + "country": "Poland", + "phone": "23566775757", + "links": [{"link_doctype": "Supplier", "link_name": "Scott Ties"}] + }, { - "address_line1": "Norra Esplanaden 87", - "address_type": "Office", - "city": "HELSINKI", - "country": "Finland", - "customer": null, - "phone": "23566775757", - "supplier": "Reliable Investments" - }, + "address_line1": "Norra Esplanaden 87", + "address_type": "Office", + "city": "HELSINKI", + "country": "Finland", + "phone": "23566775757", + "links": [{"link_doctype": "Supplier", "link_name": "Reliable Investments"}] + }, { - "address_line1": "2038 Fallon Drive", - "address_type": "Office", - "city": "Dresden", - "country": "Canada", - "customer": null, - "phone": "23566775757", - "supplier": "Nan Duskin" - }, + "address_line1": "2038 Fallon Drive", + "address_type": "Office", + "city": "Dresden", + "country": "Canada", + "phone": "23566775757", + "links": [{"link_doctype": "Supplier", "link_name": "Nan Duskin"}] + }, { - "address_line1": "77 cours Franklin Roosevelt", - "address_type": "Office", - "city": "MARSEILLE", - "country": "France", - "customer": null, - "phone": "23566775757", - "supplier": "Rainbow Records" - }, + "address_line1": "77 cours Franklin Roosevelt", + "address_type": "Office", + "city": "MARSEILLE", + "country": "France", + "phone": "23566775757", + "links": [{"link_doctype": "Supplier", "link_name": "Rainbow Records"}] + }, { - "address_line1": "ul. Tuwima Juliana 85", - "address_type": "Office", - "city": "\u0141\u00f3d\u017a", - "country": "Poland", - "customer": null, - "phone": "23566775757", - "supplier": "New World Realty" - }, + "address_line1": "ul. Tuwima Juliana 85", + "address_type": "Office", + "city": "\u0141\u00f3d\u017a", + "country": "Poland", + "phone": "23566775757", + "links": [{"link_doctype": "Supplier", "link_name": "New World Realty"}] + }, { - "address_line1": "Gl. Sygehusvej 41", - "address_type": "Office", - "city": "Narsaq", - "country": "Greenland", - "customer": null, - "phone": "23566775757", - "supplier": "Asiatic Solutions" - }, + "address_line1": "Gl. Sygehusvej 41", + "address_type": "Office", + "city": "Narsaq", + "country": "Greenland", + "phone": "23566775757", + "links": [{"link_doctype": "Supplier", "link_name": "Asiatic Solutions"}] + }, { - "address_line1": "Gosposka ulica 50", - "address_type": "Office", - "city": "Nova Gorica", - "country": "Slovenia", - "customer": null, - "phone": "23566775757", - "supplier": "Eagle Hardware" + "address_line1": "Gosposka ulica 50", + "address_type": "Office", + "city": "Nova Gorica", + "country": "Slovenia", + "phone": "23566775757", + "links": [{"link_doctype": "Supplier", "link_name": "Eagle Hardware"}] } ] \ No newline at end of file diff --git a/erpnext/demo/data/contact.json b/erpnext/demo/data/contact.json index 130845b2585..113b561ce5a 100644 --- a/erpnext/demo/data/contact.json +++ b/erpnext/demo/data/contact.json @@ -1,191 +1,164 @@ [ { - "customer": "Adaptas", - "email_id": "JanVaclavik@example.com", - "first_name": "January", - "last_name": "V\u00e1clav\u00edk", - "supplier": null - }, + "email_id": "JanVaclavik@example.com", + "first_name": "January", + "last_name": "V\u00e1clav\u00edk", + "links": [{"link_doctype": "Customer", "link_name": "Adaptas"}] + }, { - "customer": "Asian Fusion", - "email_id": "ChidumagaTobeolisa@example.com", - "first_name": "Chidumaga", - "last_name": "Tobeolisa", - "supplier": null - }, + "email_id": "ChidumagaTobeolisa@example.com", + "first_name": "Chidumaga", + "last_name": "Tobeolisa", + "links": [{"link_doctype": "Customer", "link_name": "Asian Fusion"}] + }, { - "customer": "Asian Junction", - "email_id": "JanaKubanova@example.com", - "first_name": "Jana", - "last_name": "Kub\u00e1\u0148ov\u00e1", - "supplier": null - }, + "email_id": "JanaKubanova@example.com", + "first_name": "Jana", + "last_name": "Kub\u00e1\u0148ov\u00e1", + "links": [{"link_doctype": "Customer", "link_name": "Asian Junction"}] + }, { - "customer": "Big D Supermarkets", - "email_id": "XuChaoXuan@example.com", - "first_name": "\u7d39\u8431", - "last_name": "\u4e8e", - "supplier": null - }, + "email_id": "XuChaoXuan@example.com", + "first_name": "\u7d39\u8431", + "last_name": "\u4e8e", + "links": [{"link_doctype": "Customer", "link_name": "Big D Supermarkets"}] + }, { - "customer": "Buttrey Food & Drug", - "email_id": "OzlemVerwijmeren@example.com", - "first_name": "\u00d6zlem", - "last_name": "Verwijmeren", - "supplier": null - }, + "email_id": "OzlemVerwijmeren@example.com", + "first_name": "\u00d6zlem", + "last_name": "Verwijmeren", + "links": [{"link_doctype": "Customer", "link_name": "Buttrey Food & Drug"}] + }, { - "customer": "Chi-Chis", - "email_id": "HansRasmussen@example.com", - "first_name": "Hans", - "last_name": "Rasmussen", - "supplier": null - }, + "email_id": "HansRasmussen@example.com", + "first_name": "Hans", + "last_name": "Rasmussen", + "links": [{"link_doctype": "Customer", "link_name": "Chi-Chis"}] + }, { - "customer": "Choices", - "email_id": "SatomiShigeki@example.com", - "first_name": "Satomi", - "last_name": "Shigeki", - "supplier": null - }, + "email_id": "SatomiShigeki@example.com", + "first_name": "Satomi", + "last_name": "Shigeki", + "links": [{"link_doctype": "Customer", "link_name": "Choices"}] + }, { - "customer": "Consumers and Consumers Express", - "email_id": "SimonVJessen@example.com", - "first_name": "Simon", - "last_name": "Jessen", - "supplier": null - }, + "email_id": "SimonVJessen@example.com", + "first_name": "Simon", + "last_name": "Jessen", + "links": [{"link_doctype": "Customer", "link_name": "Consumers and Consumers Express"}] + }, { - "customer": "Crafts Canada", - "email_id": "NeguaranShahsaah@example.com", - "first_name": "\u0646\u06af\u0627\u0631\u06cc\u0646", - "last_name": "\u0634\u0627\u0647 \u0633\u06cc\u0627\u0647", - "supplier": null - }, + "email_id": "NeguaranShahsaah@example.com", + "first_name": "\u0646\u06af\u0627\u0631\u06cc\u0646", + "last_name": "\u0634\u0627\u0647 \u0633\u06cc\u0627\u0647", + "links": [{"link_doctype": "Customer", "link_name": "Crafts Canada"}] + }, { - "customer": "Endicott Shoes", - "email_id": "Lom-AliBataev@example.com", - "first_name": "Lom-Ali", - "last_name": "Bataev", - "supplier": null - }, + "email_id": "Lom-AliBataev@example.com", + "first_name": "Lom-Ali", + "last_name": "Bataev", + "links": [{"link_doctype": "Customer", "link_name": "Endicott Shoes"}] + }, { - "customer": "Fayva", - "email_id": "VanNgocTien@example.com", - "first_name": "Ti\u00ean", - "last_name": "V\u0103n", - "supplier": null - }, + "email_id": "VanNgocTien@example.com", + "first_name": "Ti\u00ean", + "last_name": "V\u0103n", + "links": [{"link_doctype": "Customer", "link_name": "Fayva"}] + }, { - "customer": "Intelacard", - "email_id": "QuimeyOsorioRuelas@example.com", - "first_name": "Quimey", - "last_name": "Osorio", - "supplier": null - }, + "email_id": "QuimeyOsorioRuelas@example.com", + "first_name": "Quimey", + "last_name": "Osorio", + "links": [{"link_doctype": "Customer", "link_name": "Intelacard"}] + }, { - "customer": "Landskip Yard Care", - "email_id": "EdgardaSalcedoRaya@example.com", - "first_name": "Edgarda", - "last_name": "Salcedo", - "supplier": null - }, + "email_id": "EdgardaSalcedoRaya@example.com", + "first_name": "Edgarda", + "last_name": "Salcedo", + "links": [{"link_doctype": "Customer", "link_name": "Landskip Yard Care"}] + }, { - "customer": "Life Plan Counselling", - "email_id": "HafsteinnBjarnarsonar@example.com", - "first_name": "Hafsteinn", - "last_name": "Bjarnarsonar", - "supplier": null - }, + "email_id": "HafsteinnBjarnarsonar@example.com", + "first_name": "Hafsteinn", + "last_name": "Bjarnarsonar", + "links": [{"link_doctype": "Customer", "link_name": "Life Plan Counselling"}] + }, { - "customer": "Mr Fables", - "email_id": "\u0434\u0430\u043d\u0438\u0438\u043b@example.com", - "first_name": "\u0414\u0430\u043d\u0438\u0438\u043b", - "last_name": "\u041a\u043e\u043d\u043e\u0432\u0430\u043b\u043e\u0432", - "supplier": null - }, + "email_id": "\u0434\u0430\u043d\u0438\u0438\u043b@example.com", + "first_name": "\u0414\u0430\u043d\u0438\u0438\u043b", + "last_name": "\u041a\u043e\u043d\u043e\u0432\u0430\u043b\u043e\u0432", + "links": [{"link_doctype": "Customer", "link_name": "Mr Fables"}] + }, { - "customer": "Nelson Brothers", - "email_id": "SelmaMAndersen@example.com", - "first_name": "Selma", - "last_name": "Andersen", - "supplier": null - }, + "email_id": "SelmaMAndersen@example.com", + "first_name": "Selma", + "last_name": "Andersen", + "links": [{"link_doctype": "Customer", "link_name": "Nelson Brothers"}] + }, { - "customer": "Netobill", - "email_id": "LadislavKolaja@example.com", - "first_name": "Ladislav", - "last_name": "Kolaja", - "supplier": null - }, + "email_id": "LadislavKolaja@example.com", + "first_name": "Ladislav", + "last_name": "Kolaja", + "links": [{"link_doctype": "Customer", "link_name": "Netobill"}] + }, { - "customer": null, - "email_id": "TewoldeAbaalom@example.com", - "first_name": "Tewolde", - "last_name": "Abaalom", - "supplier": "Helios Air" - }, + "links": [{"link_doctype": "Supplier", "link_name": "Helios Air"}], + "email_id": "TewoldeAbaalom@example.com", + "first_name": "Tewolde", + "last_name": "Abaalom" + }, { - "customer": null, - "email_id": "LeilaFernandesRodrigues@example.com", - "first_name": "Leila", - "last_name": "Rodrigues", - "supplier": "Ks Merchandise" - }, + "links": [{"link_doctype": "Supplier", "link_name": "Ks Merchandise"}], + "email_id": "LeilaFernandesRodrigues@example.com", + "first_name": "Leila", + "last_name": "Rodrigues" + }, { - "customer": null, - "email_id": "DmitryBulgakov@example.com", - "first_name": "Dmitry", - "last_name": "Bulgakov", - "supplier": "HomeBase" - }, + "links": [{"link_doctype": "Supplier", "link_name": "HomeBase"}], + "email_id": "DmitryBulgakov@example.com", + "first_name": "Dmitry", + "last_name": "Bulgakov" + }, { - "customer": null, - "email_id": "HaiducWhitfoot@example.com", - "first_name": "Haiduc", - "last_name": "Whitfoot", - "supplier": "Scott Ties" - }, + "links": [{"link_doctype": "Supplier", "link_name": "Scott Ties"}], + "email_id": "HaiducWhitfoot@example.com", + "first_name": "Haiduc", + "last_name": "Whitfoot" + }, { - "customer": null, - "email_id": "SesseljaPetursdottir@example.com", - "first_name": "Sesselja", - "last_name": "P\u00e9tursd\u00f3ttir", - "supplier": "Reliable Investments" - }, + "links": [{"link_doctype": "Supplier", "link_name": "Reliable Investments"}], + "email_id": "SesseljaPetursdottir@example.com", + "first_name": "Sesselja", + "last_name": "P\u00e9tursd\u00f3ttir" + }, { - "customer": null, - "email_id": "HajdarPignar@example.com", - "first_name": "Hajdar", - "last_name": "Pignar", - "supplier": "Nan Duskin" - }, + "links": [{"link_doctype": "Supplier", "link_name": "Nan Duskin"}], + "email_id": "HajdarPignar@example.com", + "first_name": "Hajdar", + "last_name": "Pignar" + }, { - "customer": null, - "email_id": "GustavaLorenzo@example.com", - "first_name": "Gustava", - "last_name": "Lorenzo", - "supplier": "Rainbow Records" - }, + "links": [{"link_doctype": "Supplier", "link_name": "Rainbow Records"}], + "email_id": "GustavaLorenzo@example.com", + "first_name": "Gustava", + "last_name": "Lorenzo" + }, { - "customer": null, - "email_id": "BethanyWood@example.com", - "first_name": "Bethany", - "last_name": "Wood", - "supplier": "New World Realty" - }, + "links": [{"link_doctype": "Supplier", "link_name": "New World Realty"}], + "email_id": "BethanyWood@example.com", + "first_name": "Bethany", + "last_name": "Wood" + }, { - "customer": null, - "email_id": "GlorianaBrownlock@example.com", - "first_name": "Gloriana", - "last_name": "Brownlock", - "supplier": "Asiatic Solutions" - }, + "links": [{"link_doctype": "Supplier", "link_name": "Asiatic Solutions"}], + "email_id": "GlorianaBrownlock@example.com", + "first_name": "Gloriana", + "last_name": "Brownlock" + }, { - "customer": null, - "email_id": "JensonFraser@gustr.com", - "first_name": "Jenson", - "last_name": "Fraser", - "supplier": "Eagle Hardware" + "links": [{"link_doctype": "Supplier", "link_name": "Eagle Hardware"}], + "email_id": "JensonFraser@gustr.com", + "first_name": "Jenson", + "last_name": "Fraser" } ] \ No newline at end of file diff --git a/erpnext/demo/setup/setup_data.py b/erpnext/demo/setup/setup_data.py index 902bbabd1e1..21ac6484d98 100644 --- a/erpnext/demo/setup/setup_data.py +++ b/erpnext/demo/setup/setup_data.py @@ -32,7 +32,7 @@ def setup(domain): import_json('Contact') import_json('Lead') setup_currency_exchange() - setup_mode_of_payment() + #setup_mode_of_payment() setup_account_to_expense_type() setup_budget() setup_pos_profile() diff --git a/erpnext/fleet_management/report/vehicle_expenses/vehicle_expenses.py b/erpnext/fleet_management/report/vehicle_expenses/vehicle_expenses.py index 717a94f271c..a03b7f3e132 100644 --- a/erpnext/fleet_management/report/vehicle_expenses/vehicle_expenses.py +++ b/erpnext/fleet_management/report/vehicle_expenses/vehicle_expenses.py @@ -15,7 +15,7 @@ def execute(filters=None): columns=get_columns() data=get_log_data(filters) chart=get_chart_data(data,period_list) - return columns,data,None,chart + return columns, data, None, chart def get_columns(): columns = [_("License") + ":Link/Vehicle:100", _("Make") + ":data:50", diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 0a07e76d89d..8443cdf7e10 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -48,7 +48,7 @@ website_generators = ["Item Group", "Item", "Sales Partner", "Job Opening", "Stu website_context = { "favicon": "/assets/erpnext/images/favicon.png", - "splash_image": "/assets/erpnext/images/splash.png" + "splash_image": "/assets/erpnext/images/erp-icon.svg" } website_route_rules = [ @@ -112,10 +112,8 @@ portal_menu_items = [ ] default_roles = [ - {'role': 'Customer', 'doctype':'Contact', 'email_field': 'email_id', - 'filters': {'ifnull(customer, "")': ('!=', '')}}, - {'role': 'Supplier', 'doctype':'Contact', 'email_field': 'email_id', - 'filters': {'ifnull(supplier, "")': ('!=', '')}}, + {'role': 'Customer', 'doctype':'Contact', 'email_field': 'email_id'}, + {'role': 'Supplier', 'doctype':'Contact', 'email_field': 'email_id'}, {'role': 'Student', 'doctype':'Student', 'email_field': 'student_email_id'} ] @@ -125,7 +123,6 @@ has_website_permission = { "Supplier Quotation": "erpnext.controllers.website_list_for_contact.has_website_permission", "Delivery Note": "erpnext.controllers.website_list_for_contact.has_website_permission", "Issue": "erpnext.support.doctype.issue.issue.has_website_permission", - "Address": "erpnext.utilities.doctype.address.address.has_website_permission", "Discussion": "erpnext.schools.web_form.discussion.discussion.has_website_permission" } @@ -153,16 +150,14 @@ doc_events = { "on_cancel": "erpnext.stock.doctype.material_request.material_request.update_completed_and_requested_qty" }, "User": { + "after_insert": "frappe.email.doctype.contact.contact.update_contact", "validate": "erpnext.hr.doctype.employee.employee.validate_employee_role", "on_update": "erpnext.hr.doctype.employee.employee.update_user_permissions", - "on_update": "erpnext.utilities.doctype.contact.contact.update_contact" + "on_update": "erpnext.utilities.address_and_contact.set_default_role" }, ("Sales Taxes and Charges Template", 'Price List'): { "on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings" }, - "Address": { - "validate": "erpnext.shopping_cart.cart.set_customer_in_address" - }, # bubble transaction notification on master ('Opportunity', 'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice', diff --git a/erpnext/hr/doctype/process_payroll/process_payroll.js b/erpnext/hr/doctype/process_payroll/process_payroll.js index 0ad8cec549d..cfb646d033f 100644 --- a/erpnext/hr/doctype/process_payroll/process_payroll.js +++ b/erpnext/hr/doctype/process_payroll/process_payroll.js @@ -7,6 +7,7 @@ frappe.ui.form.on("Process Payroll", { frm.doc.start_date = ''; frm.doc.end_date = ''; frm.doc.payroll_frequency = ''; + frm.toggle_reqd(['payroll_frequency'], !frm.doc.salary_slip_based_on_timesheet); }, refresh: function(frm) { @@ -25,6 +26,10 @@ frappe.ui.form.on("Process Payroll", { frm.trigger("set_start_end_dates"); }, + salary_slip_based_on_timesheet: function(frm) { + frm.toggle_reqd(['payroll_frequency'], !frm.doc.salary_slip_based_on_timesheet); + }, + payment_account: function(frm) { frm.toggle_display(['make_bank_entry'], (frm.doc.payment_account!="" && frm.doc.payment_account!="undefined")); }, diff --git a/erpnext/hr/doctype/process_payroll/process_payroll.py b/erpnext/hr/doctype/process_payroll/process_payroll.py index 343ccdba379..6794a319eac 100644 --- a/erpnext/hr/doctype/process_payroll/process_payroll.py +++ b/erpnext/hr/doctype/process_payroll/process_payroll.py @@ -68,7 +68,7 @@ class ProcessPayroll(Document): def check_mandatory(self): - for fieldname in ['company', 'payroll_frequency', 'start_date', 'end_date']: + for fieldname in ['company', 'start_date', 'end_date']: if not self.get(fieldname): frappe.throw(_("Please set {0}").format(self.meta.get_label(fieldname))) @@ -296,17 +296,18 @@ class ProcessPayroll(Document): frappe.db.set_value("Salary Slip", ss_obj.name, "journal_entry", jv_name) def set_start_end_dates(self): - self.update(get_start_end_dates(self.payroll_frequency, self.start_date or self.posting_date)) + self.update(get_start_end_dates(self.payroll_frequency, + self.start_date or self.posting_date, self.company)) @frappe.whitelist() -def get_start_end_dates(payroll_frequency, start_date=None): +def get_start_end_dates(payroll_frequency, start_date=None, company=None): '''Returns dict of start and end dates for given payroll frequency based on start_date''' if not payroll_frequency: frappe.throw(_("Please set Payroll Frequency first")) if payroll_frequency == "Monthly" or payroll_frequency == "Bimonthly": - fiscal_year = get_fiscal_year(start_date)[0] + fiscal_year = get_fiscal_year(start_date, company=company)[0] month = "%02d" % getdate(start_date).month m = get_month_details(fiscal_year, month) if payroll_frequency == "Bimonthly": diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.py b/erpnext/hr/doctype/salary_slip/test_salary_slip.py index 3eec6869e43..3d119c3e383 100644 --- a/erpnext/hr/doctype/salary_slip/test_salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.py @@ -134,7 +134,7 @@ class TestSalarySlip(unittest.TestCase): self.assertTrue(email_queue) def test_payroll_frequency(self): - fiscal_year = get_fiscal_year(nowdate())[0] + fiscal_year = get_fiscal_year(nowdate(), company="_Test Company")[0] month = "%02d" % getdate(nowdate()).month m = get_month_details(fiscal_year, month) @@ -185,7 +185,7 @@ class TestSalarySlip(unittest.TestCase): }).insert() def make_holiday_list(self): - fiscal_year = get_fiscal_year(nowdate()) + fiscal_year = get_fiscal_year(nowdate(), company="_Test Company") if not frappe.db.get_value("Holiday List", "Salary Slip Test Holiday List"): holiday_list = frappe.get_doc({ "doctype": "Holiday List", diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.json b/erpnext/hr/doctype/salary_structure/salary_structure.json index 8db8e93ef77..ca59ded9405 100644 --- a/erpnext/hr/doctype/salary_structure/salary_structure.json +++ b/erpnext/hr/doctype/salary_structure/salary_structure.json @@ -1,7 +1,7 @@ { "allow_copy": 0, "allow_import": 1, - "allow_rename": 0, + "allow_rename": 1, "autoname": "Prompt", "beta": 0, "creation": "2013-03-07 18:50:29", @@ -894,7 +894,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-12-14 02:02:10.848614", + "modified": "2017-01-11 02:02:10.848614", "modified_by": "Administrator", "module": "HR", "name": "Salary Structure", @@ -951,4 +951,4 @@ "timeline_field": "", "title_field": "", "track_seen": 0 -} \ No newline at end of file +} diff --git a/erpnext/hr/report/monthly_salary_register/monthly_salary_register.js b/erpnext/hr/report/monthly_salary_register/monthly_salary_register.js deleted file mode 100644 index a879b39a6c1..00000000000 --- a/erpnext/hr/report/monthly_salary_register/monthly_salary_register.js +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt - -frappe.query_reports["Monthly Salary Register"] = { - "filters": [ - { - "fieldname":"from_date", - "label": __("From"), - "fieldtype": "Date", - "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1), - "reqd": 1 - }, - { - "fieldname":"to_date", - "label": __("To"), - "fieldtype": "Date", - "default": frappe.datetime.get_today(), - "reqd": 1 - }, - { - "fieldname":"employee", - "label": __("Employee"), - "fieldtype": "Link", - "options": "Employee" - }, - { - "fieldname":"company", - "label": __("Company"), - "fieldtype": "Link", - "options": "Company", - "default": frappe.defaults.get_user_default("Company") - } - ] -} \ No newline at end of file diff --git a/erpnext/hr/report/monthly_salary_register/__init__.py b/erpnext/hr/report/salary_register/__init__.py similarity index 100% rename from erpnext/hr/report/monthly_salary_register/__init__.py rename to erpnext/hr/report/salary_register/__init__.py diff --git a/erpnext/hr/report/monthly_salary_register/monthly_salary_register.html b/erpnext/hr/report/salary_register/salary_register.html similarity index 89% rename from erpnext/hr/report/monthly_salary_register/monthly_salary_register.html rename to erpnext/hr/report/salary_register/salary_register.html index c77e4e58b8b..2a9cd3ebdb5 100644 --- a/erpnext/hr/report/monthly_salary_register/monthly_salary_register.html +++ b/erpnext/hr/report/salary_register/salary_register.html @@ -2,8 +2,7 @@ {%= frappe.boot.letter_heads[filters.letter_head || frappe.defaults.get_default("letter_head")] %}Printed On {%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}
- diff --git a/erpnext/hr/report/salary_register/salary_register.js b/erpnext/hr/report/salary_register/salary_register.js new file mode 100644 index 00000000000..8b0faf5219b --- /dev/null +++ b/erpnext/hr/report/salary_register/salary_register.js @@ -0,0 +1,27 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.query_reports["Salary Register"] = { + "filters": [ + { + "fieldname":"date_range", + "label": __("Date Range"), + "fieldtype": "DateRange", + "default": [frappe.datetime.add_months(get_today(),-1), frappe.datetime.get_today()], + "reqd": 1 + }, + { + "fieldname":"employee", + "label": __("Employee"), + "fieldtype": "Link", + "options": "Employee" + }, + { + "fieldname":"company", + "label": __("Company"), + "fieldtype": "Link", + "options": "Company", + "default": frappe.defaults.get_user_default("Company") + } + ] +} diff --git a/erpnext/hr/report/monthly_salary_register/monthly_salary_register.json b/erpnext/hr/report/salary_register/salary_register.json similarity index 59% rename from erpnext/hr/report/monthly_salary_register/monthly_salary_register.json rename to erpnext/hr/report/salary_register/salary_register.json index d32e71e6ffc..116691509e3 100644 --- a/erpnext/hr/report/monthly_salary_register/monthly_salary_register.json +++ b/erpnext/hr/report/salary_register/salary_register.json @@ -1,17 +1,18 @@ { "add_total_row": 1, "apply_user_permissions": 1, - "creation": "2013-05-07 18:09:42", + "creation": "2017-01-10 17:36:58.153863", + "disabled": 0, "docstatus": 0, "doctype": "Report", - "idx": 1, + "idx": 0, "is_standard": "Yes", - "modified": "2014-06-03 07:18:17.187018", + "modified": "2017-01-10 17:38:00.832224", "modified_by": "Administrator", "module": "HR", - "name": "Monthly Salary Register", + "name": "Salary Register", "owner": "Administrator", "ref_doctype": "Salary Slip", - "report_name": "Monthly Salary Register", + "report_name": "Salary Register", "report_type": "Script Report" } \ No newline at end of file diff --git a/erpnext/hr/report/monthly_salary_register/monthly_salary_register.py b/erpnext/hr/report/salary_register/salary_register.py similarity index 92% rename from erpnext/hr/report/monthly_salary_register/monthly_salary_register.py rename to erpnext/hr/report/salary_register/salary_register.py index e8d0a0bf2f7..1e36b92e22a 100644 --- a/erpnext/hr/report/monthly_salary_register/monthly_salary_register.py +++ b/erpnext/hr/report/salary_register/salary_register.py @@ -3,12 +3,11 @@ from __future__ import unicode_literals import frappe -from frappe.utils import flt, cstr -from frappe import msgprint, _ +from frappe.utils import flt +from frappe import _ def execute(filters=None): if not filters: filters = {} - salary_slips = get_salary_slips(filters) columns, earning_types, ded_types = get_columns(salary_slips) ss_earning_map = get_ss_earning_map(salary_slips) @@ -58,6 +57,7 @@ def get_columns(salary_slips): return columns, salary_components[_("Earning")], salary_components[_("Deduction")] def get_salary_slips(filters): + filters.update({"from_date": filters.get("date_range")[0], "to_date":filters.get("date_range")[1]}) conditions, filters = get_conditions(filters) salary_slips = frappe.db.sql("""select * from `tabSalary Slip` where docstatus = 1 %s order by employee""" % conditions, filters, as_dict=1) @@ -65,13 +65,12 @@ def get_salary_slips(filters): if not salary_slips: frappe.throw(_("No salary slip found between {0} and {1}").format( filters.get("from_date"), filters.get("to_date"))) - return salary_slips def get_conditions(filters): conditions = "" - if filters.get("from_date"): conditions += " and start_date >= %(from_date)s" - if filters.get("to_date"): conditions += " and end_date <= %(to_date)s" + if filters.get("date_range"): conditions += " and start_date >= %(from_date)s" + if filters.get("date_range"): conditions += " and end_date <= %(to_date)s" if filters.get("company"): conditions += " and company = %(company)s" if filters.get("employee"): conditions += " and employee = %(employee)s" diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js index bcf1ae6932d..b5d1ad320f6 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js +++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js @@ -3,18 +3,28 @@ frappe.provide("erpnext.maintenance"); -frappe.ui.form.on_change("Maintenance Schedule", "customer", function(frm) { - erpnext.utils.get_party_details(frm) }); -frappe.ui.form.on_change("Maintenance Schedule", "customer_address", function(){ - erpnext.utils.get_address_display(cur_frm, 'customer_address', 'address_display'); -}); -frappe.ui.form.on_change("Maintenance Schedule", "contact_person", function(){ - erpnext.utils.get_contact_details(cur_frm); -}); +frappe.ui.form.on('Maintenance Schedule', { + setup: function(frm) { + frm.set_query('contact_person', erpnext.queries.contact_query); + frm.set_query('customer_address', erpnext.queries.address_query); + }, + customer: function(frm) { + erpnext.utils.get_party_details(frm) + }, + customer_address: function(frm) { + erpnext.utils.get_address_display(frm, 'customer_address', 'address_display'); + }, + contact_person: function(frm) { + erpnext.utils.get_contact_details(frm); + } + +}) // TODO commonify this code erpnext.maintenance.MaintenanceSchedule = frappe.ui.form.Controller.extend({ refresh: function() { + frappe.contact_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'} + var me = this; if (this.frm.doc.docstatus === 0) { @@ -94,18 +104,6 @@ cur_frm.cscript.onload = function(doc, dt, dn) { } -cur_frm.fields_dict['customer_address'].get_query = function(doc, cdt, cdn) { - return { - filters:{ 'customer': doc.customer } - } -} - -cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) { - return { - filters:{ 'customer': doc.customer } - } -} - cur_frm.cscript.generate_schedule = function(doc, cdt, cdn) { if (!doc.__islocal) { return $c('runserverobj', args={'method':'generate_schedule', 'docs':doc}, diff --git a/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.json b/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.json index e9192f77a2d..1e68fab4d64 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.json +++ b/erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.json @@ -10,11 +10,13 @@ "doctype": "DocType", "document_type": "Document", "editable_grid": 1, + "engine": "InnoDB", "fields": [ { "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "item_code", "fieldtype": "Link", "hidden": 0, @@ -32,6 +34,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, "search_index": 1, @@ -42,6 +45,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "item_name", "fieldtype": "Data", "hidden": 0, @@ -58,6 +62,7 @@ "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, @@ -68,8 +73,9 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "description", - "fieldtype": "Data", + "fieldtype": "Text Editor", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -85,6 +91,7 @@ "print_hide_if_no_value": 0, "print_width": "300px", "read_only": 1, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -96,6 +103,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "schedule_details", "fieldtype": "Section Break", "hidden": 0, @@ -110,6 +118,7 @@ "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, @@ -120,6 +129,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "start_date", "fieldtype": "Date", "hidden": 0, @@ -136,6 +146,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, "search_index": 1, @@ -146,6 +157,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "end_date", "fieldtype": "Date", "hidden": 0, @@ -162,6 +174,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, "search_index": 1, @@ -172,6 +185,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "periodicity", "fieldtype": "Select", "hidden": 0, @@ -189,6 +203,7 @@ "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, @@ -199,6 +214,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "no_of_visits", "fieldtype": "Int", "hidden": 0, @@ -215,6 +231,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, "search_index": 0, @@ -225,6 +242,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "sales_person", "fieldtype": "Link", "hidden": 0, @@ -242,6 +260,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, "search_index": 0, @@ -252,6 +271,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "reference", "fieldtype": "Section Break", "hidden": 0, @@ -266,6 +286,7 @@ "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, @@ -276,6 +297,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "serial_no", "fieldtype": "Small Text", "hidden": 0, @@ -292,6 +314,7 @@ "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, @@ -302,6 +325,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, + "columns": 0, "fieldname": "sales_order", "fieldtype": "Link", "hidden": 0, @@ -320,6 +344,7 @@ "print_hide_if_no_value": 0, "print_width": "150px", "read_only": 1, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 1, @@ -338,7 +363,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-07-11 03:28:02.260189", + "modified": "2017-01-11 12:02:38.449129", "modified_by": "Administrator", "module": "Maintenance", "name": "Maintenance Schedule Item", diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js index 38c20dadd45..1a3c35cc06e 100644 --- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js +++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js @@ -2,20 +2,31 @@ // License: GNU General Public License v3. See license.txt frappe.provide("erpnext.maintenance"); +me.frm.set_query('contact_person', erpnext.queries.contact_query); -frappe.ui.form.on_change("Maintenance Visit", "customer", function(frm) { - erpnext.utils.get_party_details(frm) }); -frappe.ui.form.on_change("Maintenance Visit", "customer_address", function(frm){ - erpnext.utils.get_address_display(frm, 'customer_address', 'address_display') -}); -frappe.ui.form.on_change("Maintenance Visit", "contact_person", function(frm){ - erpnext.utils.get_contact_details(frm) -}); +frappe.ui.form.on('Maintenance Visit', { + setup: function(frm) { + frm.set_query('contact_person', erpnext.queries.contact_query); + frm.set_query('customer_address', erpnext.queries.address_query); + }, + customer: function(frm) { + erpnext.utils.get_party_details(frm) + }, + customer_address: function(frm) { + erpnext.utils.get_address_display(frm, 'customer_address', 'address_display'); + }, + contact_person: function(frm) { + erpnext.utils.get_contact_details(frm); + } + +}) // TODO commonify this code erpnext.maintenance.MaintenanceVisit = frappe.ui.form.Controller.extend({ refresh: function() { + frappe.contact_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'} + if (this.frm.doc.docstatus===0) { cur_frm.add_custom_button(__('Maintenance Schedule'), function() { @@ -69,18 +80,6 @@ cur_frm.cscript.onload = function(doc, dt, dn) { cur_frm.add_fetch('item_code', 'description', 'description'); } -cur_frm.fields_dict['customer_address'].get_query = function(doc, cdt, cdn) { - return{ - filters:{'customer': doc.customer} - } -} - -cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) { - return{ - filters:{'customer': doc.customer} - } -} - cur_frm.fields_dict.customer.get_query = function(doc,cdt,cdn) { return {query: "erpnext.controllers.queries.customer_query" } } diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 1221a4f2304..14be6853113 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -361,4 +361,5 @@ erpnext.patches.v7_1.repost_stock_for_deleted_bins_for_merging_items execute:frappe.delete_doc('Desktop Icon', {'module_name': 'Profit and Loss Statment'}) erpnext.patches.v7_2.update_website_for_variant erpnext.patches.v7_2.update_assessment_modules - +erpnext.patches.v7_2.update_doctype_status +erpnext.patches.v7_2.update_salary_slips \ No newline at end of file diff --git a/erpnext/patches/v7_2/contact_address_links.py b/erpnext/patches/v7_2/contact_address_links.py new file mode 100644 index 00000000000..490834b2ee3 --- /dev/null +++ b/erpnext/patches/v7_2/contact_address_links.py @@ -0,0 +1,24 @@ +import frappe + +def execute(): + frappe.reload_doctype('Contact') + frappe.reload_doctype('Address') + map_fields = ( + ('Customer', 'customer'), + ('Supplier', 'supplier'), + ('Load', 'lead'), + ('Sales Partner', 'sales_partner') + ) + for doctype in ('Contact', 'Address'): + if frappe.db.has_column(doctype, 'customer'): + for doc in frappe.get_all(doctype, fields='*'): + doc.doctype = doctype + doc = frappe.get_doc(doc) + dirty = False + for field in map_fields: + if doc.get(field[1]): + doc.append('links', dict(link_doctype=field[0], link_name=doc.get(field[1]))) + dirty = True + + if dirty: + doc.save() diff --git a/erpnext/patches/v7_2/update_doctype_status.py b/erpnext/patches/v7_2/update_doctype_status.py new file mode 100644 index 00000000000..c66f3f2e73a --- /dev/null +++ b/erpnext/patches/v7_2/update_doctype_status.py @@ -0,0 +1,11 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + doctypes = ["Opportunity", "Quotation", "Sales Order", "Sales Invoice", "Purchase Invoice", "Purchase Order", "Delivery Note", "Purchase Receipt"] + for doctype in doctypes: + frappe.db.sql(""" update `tab{doctype}` set status = 'Draft' + where status = 'Cancelled' and docstatus = 0 """.format(doctype = doctype)) \ No newline at end of file diff --git a/erpnext/patches/v7_2/update_salary_slips.py b/erpnext/patches/v7_2/update_salary_slips.py new file mode 100644 index 00000000000..612b9002569 --- /dev/null +++ b/erpnext/patches/v7_2/update_salary_slips.py @@ -0,0 +1,19 @@ +import frappe +from erpnext.hr.doctype.process_payroll.process_payroll import get_month_details + +def execute(): + frappe.reload_doctype('Salary Slip') + if not frappe.db.has_column('Salary Slip', 'fiscal_year'): + return + + salary_slips = frappe.db.sql("""select month, name from `tabSalary Slip` + where (month is not null and month != '') and + (start_date is null or start_date = '') and + (end_date is null or end_date = '') and docstatus != 2""", as_dict=True) + + for salary_slip in salary_slips: + get_start_end_date = get_month_details(salary_slip.fiscal_year, salary_slip.month) + start_date = get_start_end_date['month_start_date'] + end_date = get_start_end_date['month_end_date'] + frappe.db.sql("""update `tabSalary Slip` set start_date = %s, end_date = %s where name = %s""", + (start_date, end_date, salary_slip.name)) \ No newline at end of file diff --git a/erpnext/projects/doctype/project/project.json b/erpnext/projects/doctype/project/project.json index 37ca968ae95..38ebbcb4f88 100644 --- a/erpnext/projects/doctype/project/project.json +++ b/erpnext/projects/doctype/project/project.json @@ -10,6 +10,7 @@ "doctype": "DocType", "document_type": "Setup", "editable_grid": 0, + "engine": "InnoDB", "fields": [ { "allow_on_submit": 0, @@ -24,7 +25,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Project Name", "length": 0, "no_copy": 0, @@ -53,7 +53,6 @@ "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, - "in_standard_filter": 1, "label": "Status", "length": 0, "no_copy": 1, @@ -83,7 +82,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 1, "label": "Project Type", "length": 0, "no_copy": 0, @@ -113,7 +111,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 1, "label": "Is Active", "length": 0, "no_copy": 0, @@ -144,7 +141,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "% Complete Method", "length": 0, "no_copy": 0, @@ -173,7 +169,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -200,7 +195,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 1, "label": "Priority", "length": 0, "no_copy": 0, @@ -230,7 +224,6 @@ "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, - "in_standard_filter": 0, "label": "Expected Start Date", "length": 0, "no_copy": 0, @@ -259,7 +252,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Expected End Date", "length": 0, "no_copy": 0, @@ -288,7 +280,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "% Completed", "length": 0, "no_copy": 1, @@ -315,7 +306,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Customer Details", "length": 0, "no_copy": 0, @@ -344,7 +334,6 @@ "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, - "in_standard_filter": 0, "label": "Customer", "length": 0, "no_copy": 0, @@ -374,7 +363,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -401,7 +389,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Sales Order", "length": 0, "no_copy": 0, @@ -430,7 +417,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Users", "length": 0, "no_copy": 0, @@ -459,7 +445,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Users", "length": 0, "no_copy": 0, @@ -488,7 +473,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Tasks", "length": 0, "no_copy": 0, @@ -517,7 +501,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Tasks", "length": 0, "no_copy": 0, @@ -546,7 +529,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Notes", "length": 0, "no_copy": 0, @@ -575,7 +557,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Notes", "length": 0, "no_copy": 0, @@ -604,7 +585,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Start and End Dates", "length": 0, "no_copy": 0, @@ -632,7 +612,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Actual Start Date", "length": 0, "no_copy": 0, @@ -660,7 +639,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Actual Time (in Hours)", "length": 0, "no_copy": 0, @@ -688,7 +666,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -715,7 +692,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Actual End Date", "length": 0, "no_copy": 0, @@ -744,7 +720,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Costing and Billing", "length": 0, "no_copy": 0, @@ -773,7 +748,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 1, - "in_standard_filter": 0, "label": "Estimated Cost", "length": 0, "no_copy": 0, @@ -804,7 +778,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Total Costing Amount (via Time Logs)", "length": 0, "no_copy": 0, @@ -833,7 +806,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Total Expense Claim (via Expense Claims)", "length": 0, "no_copy": 0, @@ -861,7 +833,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Company", "length": 0, "no_copy": 0, @@ -889,7 +860,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Cost Center", "length": 0, "no_copy": 0, @@ -917,7 +887,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -945,7 +914,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Total Billing Amount (via Time Logs)", "length": 0, "no_copy": 0, @@ -973,7 +941,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Total Purchase Cost (via Purchase Invoice)", "length": 0, "no_copy": 0, @@ -1001,7 +968,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Margin", "length": 0, "no_copy": 0, @@ -1030,7 +996,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Gross Margin", "length": 0, "no_copy": 0, @@ -1060,7 +1025,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -1087,7 +1051,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Gross Margin %", "length": 0, "no_copy": 0, @@ -1117,7 +1080,7 @@ "issingle": 0, "istable": 0, "max_attachments": 4, - "modified": "2016-11-07 05:55:56.179455", + "modified": "2017-01-10 16:33:54.691885", "modified_by": "Administrator", "module": "Projects", "name": "Project", @@ -1164,6 +1127,27 @@ "share": 0, "submit": 0, "write": 0 + }, + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "is_custom": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Projects Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 } ], "quick_entry": 1, diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 388f43e93dc..276259b5aed 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -30,7 +30,7 @@ class Project(Document): """Load `tasks` from the database""" self.tasks = [] for task in self.get_tasks(): - self.append("tasks", { + task_map = { "title": task.subject, "status": task.status, "start_date": task.exp_start_date, @@ -38,7 +38,11 @@ class Project(Document): "description": task.description, "task_id": task.name, "task_weight": task.task_weight - }) + } + + self.map_custom_fields(task, task_map) + + self.append("tasks", task_map) def get_tasks(self): return frappe.get_all("Task", "*", {"project": self.name}, order_by="exp_start_date asc") @@ -66,7 +70,6 @@ class Project(Document): def sync_tasks(self): """sync tasks and remove table""" if self.flags.dont_sync_tasks: return - task_names = [] for t in self.tasks: if t.task_id: @@ -83,6 +86,8 @@ class Project(Document): "task_weight": t.task_weight }) + self.map_custom_fields(t, task) + task.flags.ignore_links = True task.flags.from_project = True task.flags.ignore_feed = True @@ -96,6 +101,14 @@ class Project(Document): self.update_percent_complete() self.update_costing() + def map_custom_fields(self, source, target): + project_task_custom_fields = frappe.get_all("Custom Field", {"dt": "Project Task"}, "fieldname") + + for field in project_task_custom_fields: + target.update({ + field.fieldname: source.get(field.fieldname) + }) + def update_project(self): self.update_percent_complete() self.update_costing() diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index bd907f64b7a..490a70721ab 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -199,13 +199,22 @@ class Timesheet(Document): (%(to_time)s > tsd.from_time and %(to_time)s < tsd.to_time) or (%(from_time)s <= tsd.from_time and %(to_time)s >= tsd.to_time)) and tsd.name!=%(name)s + and ts.name!=%(parent)s and ts.docstatus < 2""".format(cond), { "val": value, "from_time": args.from_time, "to_time": args.to_time, - "name": args.name or "No Name" + "name": args.name or "No Name", + "parent": args.parent or "No Name" }, as_dict=True) + # check internal overlap + for time_log in self.time_logs: + if (fieldname != 'workstation' or args.get(fieldname) == time_log.get(fieldname)) and \ + args.idx != time_log.idx and ((args.from_time > time_log.from_time and args.from_time < time_log.to_time) or + (args.to_time > time_log.from_time and args.to_time < time_log.to_time) or + (args.from_time <= time_log.from_time and args.to_time >= time_log.to_time)): + return self return existing[0] if existing else None diff --git a/erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.js b/erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.js index d085a330fd2..93cb9402fa8 100644 --- a/erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.js +++ b/erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.js @@ -4,12 +4,16 @@ frappe.query_reports["Daily Timesheet Summary"] = { "filters": [ { - "fieldname":"date", - "label": __("Date"), - "fieldtype": "DateRange", - "start_with_value": true, - "default_from":frappe.datetime.get_today(), - "default_to":frappe.datetime.get_today(), + "fieldname":"from_date", + "label": __("From Date"), + "fieldtype": "Date", + "default": frappe.datetime.get_today() + }, + { + "fieldname":"to_date", + "label": __("To Date"), + "fieldtype": "Date", + "default": frappe.datetime.get_today() }, ] } diff --git a/erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.py b/erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.py index 6ed3b5801fc..682fb2e09dc 100644 --- a/erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.py +++ b/erpnext/projects/report/daily_timesheet_summary/daily_timesheet_summary.py @@ -9,9 +9,7 @@ from frappe.desk.reportview import build_match_conditions def execute(filters=None): if not filters: filters = {} - elif filters.get("date") : - filters["from_date"] = filters["date"][0] - filters["to_date"] = filters["date"][1] + elif filters.get("from_date") or filters.get("to_date"): filters["from_time"] = "00:00:00" filters["to_time"] = "24:00:00" diff --git a/erpnext/public/css/website.css b/erpnext/public/css/website.css index 6a1d311e982..1617ea7bd13 100644 --- a/erpnext/public/css/website.css +++ b/erpnext/public/css/website.css @@ -78,7 +78,6 @@ font-weight: inherit; color: #8D99A6; } -.transaction-list-item .items-preview, .transaction-list-item .transaction-time { margin-top: 5px; } diff --git a/erpnext/public/js/pos/pos_bill_item.html b/erpnext/public/js/pos/pos_bill_item.html index d8833bb8359..f5d1a7652e8 100644 --- a/erpnext/public/js/pos/pos_bill_item.html +++ b/erpnext/public/js/pos/pos_bill_item.html @@ -2,7 +2,7 @@- -
- - - -Some functionality is disabled for the demo app. The demo data will be cleared regulary.
-
- To start your free ERPNext account, click here
Some functionality is disabled for the demo and the data will be cleared regulary.
+Sign up for a Free ERPNext.com account here +
+ {% endblock %} diff --git a/erpnext/templates/utils.py b/erpnext/templates/utils.py index 94f924243cc..c1405c374fd 100644 --- a/erpnext/templates/utils.py +++ b/erpnext/templates/utils.py @@ -34,6 +34,8 @@ def send_message(subject="Website Query", message="", sender="", status="Open"): if customer: opportunity.customer = customer + elif lead: + opportunity.lead = lead else: opportunity.lead = new_lead.name diff --git a/erpnext/utilities/address_and_contact.py b/erpnext/utilities/address_and_contact.py index 36879d216d0..eaa71f9b1fc 100644 --- a/erpnext/utilities/address_and_contact.py +++ b/erpnext/utilities/address_and_contact.py @@ -6,17 +6,46 @@ import frappe def load_address_and_contact(doc, key): """Loads address list and contact list in `__onload`""" - from erpnext.utilities.doctype.address.address import get_address_display + from frappe.geo.doctype.address.address import get_address_display - doc.get("__onload")["addr_list"] = [a.update({"display": get_address_display(a)}) \ - for a in frappe.get_all("Address", - fields="*", filters={key: doc.name}, - order_by="is_primary_address desc, modified desc")] + address_list = [frappe.get_value('Address', a.parent, '*') + for a in frappe.get_all('Dynamic Link', fields='parent', + filters=dict(parenttype='Address', link_doctype=doc.doctype, link_name=doc.name))] + + address_list = [a.update({"display": get_address_display(a)}) + for a in address_list] + + address_list = sorted(address_list, + lambda a, b: + (int(a.is_primary_address - b.is_primary_address)) or + (1 if a.modified - b.modified else 0)) + + doc.set_onload('addr_list', address_list) if doc.doctype != "Lead": - doc.get("__onload")["contact_list"] = frappe.get_all("Contact", - fields="*", filters={key: doc.name}, - order_by="is_primary_contact desc, modified desc") + contact_list = [frappe.get_value('Contact', a.parent, '*') + for a in frappe.get_all('Dynamic Link', fields='parent', + filters=dict(parenttype='Contact', link_doctype=doc.doctype, link_name=doc.name))] + + contact_list = sorted(contact_list, + lambda a, b: + (int(a.is_primary_contact - b.is_primary_contact)) or + (1 if a.modified - b.modified else 0)) + + doc.set_onload('contact_list', contact_list) + +def set_default_role(doc, method): + '''Set customer, supplier, student based on email''' + contact_name = frappe.get_value('Contact', dict(email_id=doc.email)) + if contact_name: + contact = frappe.get_doc('Contact', contact_name) + for link in contact.links: + if link.link_doctype=='Customer': + doc.add_roles('Customer') + elif link.link_doctype=='Supplier': + doc.add_roles('Supplier') + elif frappe.get_value('Student', dict(student_email_id=doc.email)): + doc.add_roles('Student') def has_permission(doc, ptype, user): links = get_permitted_and_not_permitted_links(doc.doctype) @@ -50,15 +79,15 @@ def get_permission_query_conditions(doctype): if not links.get("not_permitted_links"): # when everything is permitted, don't add additional condition return "" - + elif not links.get("permitted_links"): conditions = [] - + # when everything is not permitted for df in links.get("not_permitted_links"): # like ifnull(customer, '')='' and ifnull(supplier, '')='' conditions.append("ifnull(`tab{doctype}`.`{fieldname}`, '')=''".format(doctype=doctype, fieldname=df.fieldname)) - + return "( " + " and ".join(conditions) + " )" else: @@ -66,7 +95,7 @@ def get_permission_query_conditions(doctype): for df in links.get("permitted_links"): # like ifnull(customer, '')!='' or ifnull(supplier, '')!='' - conditions.append("ifnull(`tab{doctype}`.`{fieldname}`, '')!=''".format(doctype=doctype, fieldname=df.fieldname)) + conditions.append("ifnull(`tab{doctype}`.`{fieldname}`, '')!=''".format(doctype=doctype, fieldname=df.fieldname)) return "( " + " or ".join(conditions) + " )" @@ -89,3 +118,14 @@ def get_permitted_and_not_permitted_links(doctype): "permitted_links": permitted_links, "not_permitted_links": not_permitted_links } + +def delete_contact_and_address(doctype, name): + for parenttype in ('Contact', 'Address'): + items = frappe.db.sql("""select parent from `tabDynamic Link` + where parenttype=%s and link_type=%s and link_name=%s""", + (parenttype, doctype, name)) + + for name in items: + doc = frappe.get_doc(parenttype, name) + if len(doc.links)==1: + doc.delete() diff --git a/erpnext/utilities/doctype/address/README.md b/erpnext/utilities/doctype/address/README.md deleted file mode 100644 index a4efda625fd..00000000000 --- a/erpnext/utilities/doctype/address/README.md +++ /dev/null @@ -1 +0,0 @@ -Address belonging to a Customer or Supplier. \ No newline at end of file diff --git a/erpnext/utilities/doctype/address/__init__.py b/erpnext/utilities/doctype/address/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/erpnext/utilities/doctype/address/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/erpnext/utilities/doctype/address/address.js b/erpnext/utilities/doctype/address/address.js deleted file mode 100644 index 1e874c3b5b8..00000000000 --- a/erpnext/utilities/doctype/address/address.js +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -// License: GNU General Public License v3. See license.txt - -{% include 'erpnext/controllers/js/contact_address_common.js' %}; - -frappe.ui.form.on("Address", "validate", function(frm) { - // clear linked customer / supplier / sales partner on saving... - $.each(["Customer", "Supplier", "Sales Partner", "Lead"], function(i, doctype) { - var name = frm.doc[doctype.toLowerCase().replace(/ /g, "_")]; - if(name && locals[doctype] && locals[doctype][name]) - frappe.model.remove_from_locals(doctype, name); - }); -}); diff --git a/erpnext/utilities/doctype/address/address.json b/erpnext/utilities/doctype/address/address.json deleted file mode 100644 index 329e05f587f..00000000000 --- a/erpnext/utilities/doctype/address/address.json +++ /dev/null @@ -1,851 +0,0 @@ -{ - "allow_copy": 0, - "allow_import": 1, - "allow_rename": 1, - "beta": 0, - "creation": "2013-01-10 16:34:32", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 0, - "fields": [ - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "address_details", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "", - "length": 0, - "no_copy": 0, - "options": "fa fa-map-marker", - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Name of person or organization that this address belongs to.", - "fieldname": "address_title", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address Title", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "address_type", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Address Type", - "length": 0, - "no_copy": 0, - "options": "Billing\nShipping\nOffice\nPersonal\nPlant\nPostal\nShop\nSubsidiary\nWarehouse\nOther", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "address_line1", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address Line 1", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "address_line2", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address Line 2", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "city", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "City/Town", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "county", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "County", - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "state", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "State", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "country", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Country", - "length": 0, - "no_copy": 0, - "options": "Country", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "pincode", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Postal Code", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break0", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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, - "width": "50%" - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "email_id", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Email Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "phone", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Phone", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "fax", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Fax", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "description": "", - "fieldname": "is_primary_address", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Preferred Billing Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "description": "", - "fieldname": "is_shipping_address", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Preferred Shipping Address", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "linked_with", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Reference", - "length": 0, - "no_copy": 0, - "options": "fa fa-pushpin", - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "fieldname": "is_your_company_address", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Is Your Company Address", - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.is_your_company_address", - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.is_your_company_address", - "fieldname": "customer", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Customer", - "length": 0, - "no_copy": 0, - "options": "Customer", - "permlevel": 0, - "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_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.is_your_company_address", - "fieldname": "customer_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Customer Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.is_your_company_address", - "fieldname": "supplier", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Supplier", - "length": 0, - "no_copy": 0, - "options": "Supplier", - "permlevel": 0, - "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_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.is_your_company_address", - "fieldname": "supplier_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Supplier Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval: !doc.is_your_company_address", - "fieldname": "sales_partner", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Sales Partner", - "length": 0, - "no_copy": 0, - "options": "Sales Partner", - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.supplier && !doc.sales_partner && !doc.is_your_company_address", - "fieldname": "lead", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Lead", - "length": 0, - "no_copy": 0, - "options": "Lead", - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.supplier && !doc.sales_partner && !doc.is_your_company_address", - "fieldname": "lead_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Lead Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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 - } - ], - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-map-marker", - "idx": 5, - "image_view": 0, - "in_create": 0, - "in_dialog": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2016-11-07 05:47:06.911933", - "modified_by": "Administrator", - "module": "Utilities", - "name": "Address", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "is_custom": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Sales User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - }, - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "is_custom": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Purchase User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - }, - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "is_custom": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Maintenance User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - }, - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "is_custom": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Accounts User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "search_fields": "customer, supplier, sales_partner, country, state", - "sort_field": "modified", - "sort_order": "DESC", - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/utilities/doctype/address/address.py b/erpnext/utilities/doctype/address/address.py deleted file mode 100644 index 2952531f013..00000000000 --- a/erpnext/utilities/doctype/address/address.py +++ /dev/null @@ -1,181 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import frappe - -from frappe import throw, _ -from frappe.utils import cstr - -from frappe.model.document import Document -from jinja2 import TemplateSyntaxError -from frappe.utils.user import is_website_user -from frappe.model.naming import make_autoname - -class Address(Document): - def __setup__(self): - self.flags.linked = False - - def autoname(self): - if not self.address_title: - self.address_title = self.customer \ - or self.supplier or self.sales_partner or self.lead - - if self.address_title: - self.name = (cstr(self.address_title).strip() + "-" + cstr(self.address_type).strip()) - if frappe.db.exists("Address", self.name): - self.name = make_autoname(cstr(self.address_title).strip() + "-" + - cstr(self.address_type).strip() + "-.#") - else: - throw(_("Address Title is mandatory.")) - - def validate(self): - self.link_fields = ("customer", "supplier", "sales_partner", "lead") - self.link_address() - self.validate_primary_address() - self.validate_shipping_address() - self.validate_reference() - - def validate_primary_address(self): - """Validate that there can only be one primary address for particular customer, supplier""" - if self.is_primary_address == 1: - self._unset_other("is_primary_address") - - elif self.is_shipping_address != 1: - for fieldname in self.link_fields: - if self.get(fieldname): - if not frappe.db.sql("""select name from `tabAddress` where is_primary_address=1 - and `%s`=%s and name!=%s""" % (frappe.db.escape(fieldname), "%s", "%s"), - (self.get(fieldname), self.name)): - self.is_primary_address = 1 - break - - def link_address(self): - """Link address based on owner""" - if not self.flags.linked: - self.check_if_linked() - - if not self.flags.linked and not self.is_your_company_address: - contact = frappe.db.get_value("Contact", {"email_id": self.owner}, - ("name", "customer", "supplier"), as_dict = True) - if contact: - self.customer = contact.customer - self.supplier = contact.supplier - - self.lead = frappe.db.get_value("Lead", {"email_id": self.owner}) - - def check_if_linked(self): - for fieldname in self.link_fields: - if self.get(fieldname): - self.flags.linked = True - break - - def validate_shipping_address(self): - """Validate that there can only be one shipping address for particular customer, supplier""" - if self.is_shipping_address == 1: - self._unset_other("is_shipping_address") - - def validate_reference(self): - if self.is_your_company_address: - if not self.company: - frappe.throw(_("Company is mandatory, as it is your company address")) - if self.customer or self.supplier or self.sales_partner or self.lead: - frappe.throw(_("Remove reference of customer, supplier, sales partner and lead, as it is your company address")) - - def _unset_other(self, is_address_type): - for fieldname in ["customer", "supplier", "sales_partner", "lead"]: - if self.get(fieldname): - frappe.db.sql("""update `tabAddress` set `%s`=0 where `%s`=%s and name!=%s""" % - (is_address_type, fieldname, "%s", "%s"), (self.get(fieldname), self.name)) - break - - def get_display(self): - return get_address_display(self.as_dict()) - -@frappe.whitelist() -def get_address_display(address_dict): - if not address_dict: - return - - if not isinstance(address_dict, dict): - address_dict = frappe.db.get_value("Address", address_dict, "*", as_dict=True) or {} - - name, template = get_address_templates(address_dict) - - try: - return frappe.render_template(template, address_dict) - except TemplateSyntaxError: - frappe.throw(_("There is an error in your Address Template {0}").format(name)) - - -def get_territory_from_address(address): - """Tries to match city, state and country of address to existing territory""" - if not address: - return - - if isinstance(address, basestring): - address = frappe.get_doc("Address", address) - - territory = None - for fieldname in ("city", "state", "country"): - territory = frappe.db.get_value("Territory", address.get(fieldname)) - if territory: - break - - return territory - -def get_list_context(context=None): - from erpnext.shopping_cart.cart import get_address_docs - return { - "title": _("Addresses"), - "get_list": get_address_list, - "row_template": "templates/includes/address_row.html", - 'no_breadcrumbs': True, - } - -def get_address_list(doctype, txt, filters, limit_start, limit_page_length=20): - from frappe.www.list import get_list - user = frappe.session.user - ignore_permissions = False - if is_website_user(): - if not filters: filters = [] - filters.append(("Address", "owner", "=", user)) - ignore_permissions = True - - return get_list(doctype, txt, filters, limit_start, limit_page_length, ignore_permissions=ignore_permissions) - -def has_website_permission(doc, ptype, user, verbose=False): - """Returns true if customer or lead matches with user""" - customer = frappe.db.get_value("Contact", {"email_id": frappe.session.user}, "customer") - if customer: - return doc.customer == customer - else: - lead = frappe.db.get_value("Lead", {"email_id": frappe.session.user}) - if lead: - return doc.lead == lead - - return False - -def get_address_templates(address): - result = frappe.db.get_value("Address Template", \ - {"country": address.get("country")}, ["name", "template"]) - - if not result: - result = frappe.db.get_value("Address Template", \ - {"is_default": 1}, ["name", "template"]) - - if not result: - frappe.throw(_("No default Address Template found. Please create a new one from Setup > Printing and Branding > Address Template.")) - else: - return result - -@frappe.whitelist() -def get_shipping_address(company): - filters = {"company": company, "is_your_company_address":1} - fieldname = ["name", "address_line1", "address_line2", "city", "state", "country"] - - address_as_dict = frappe.db.get_value("Address", filters=filters, fieldname=fieldname, as_dict=True) - - if address_as_dict: - name, address_template = get_address_templates(address_as_dict) - return address_as_dict.get("name"), frappe.render_template(address_template, address_as_dict) diff --git a/erpnext/utilities/doctype/address/test_address.py b/erpnext/utilities/doctype/address/test_address.py deleted file mode 100644 index 36f2535fa18..00000000000 --- a/erpnext/utilities/doctype/address/test_address.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals - -import frappe -test_records = frappe.get_test_records('Address') - -import unittest -import frappe - -from erpnext.utilities.doctype.address.address import get_address_display - -class TestAddress(unittest.TestCase): - def test_template_works(self): - address = frappe.get_list("Address")[0].name - display = get_address_display(frappe.get_doc("Address", address).as_dict()) - self.assertTrue(display) - - -test_dependencies = ["Address Template"] diff --git a/erpnext/utilities/doctype/address/test_records.json b/erpnext/utilities/doctype/address/test_records.json deleted file mode 100644 index a7bde9a8148..00000000000 --- a/erpnext/utilities/doctype/address/test_records.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "address_line1": "_Test Address Line 1", - "address_title": "_Test Address", - "address_type": "Office", - "city": "_Test City", - "state": "Test State", - "country": "India", - "customer": "_Test Customer", - "customer_name": "_Test Customer", - "doctype": "Address", - "is_primary_address": 1, - "phone": "+91 0000000000" - } -] \ No newline at end of file diff --git a/erpnext/utilities/doctype/address_template/__init__.py b/erpnext/utilities/doctype/address_template/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/erpnext/utilities/doctype/address_template/address_template.js b/erpnext/utilities/doctype/address_template/address_template.js deleted file mode 100644 index c055bcaceca..00000000000 --- a/erpnext/utilities/doctype/address_template/address_template.js +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Address Template', { - refresh: function(frm) { - if(frm.is_new() && !frm.doc.template) { - // set default template via js so that it is translated - frappe.call({ - method: 'erpnext.utilities.doctype.address_template.address_template.get_default_address_template', - callback: function(r) { - frm.set_value('template', r.message); - } - }); - } - } -}); diff --git a/erpnext/utilities/doctype/address_template/address_template.json b/erpnext/utilities/doctype/address_template/address_template.json deleted file mode 100644 index 6ff93d93f84..00000000000 --- a/erpnext/utilities/doctype/address_template/address_template.json +++ /dev/null @@ -1,147 +0,0 @@ -{ - "allow_copy": 0, - "allow_import": 0, - "allow_rename": 1, - "autoname": "field:country", - "beta": 0, - "creation": "2014-06-05 02:22:36.029850", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 0, - "engine": "InnoDB", - "fields": [ - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "country", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Country", - "length": 0, - "no_copy": 0, - "options": "Country", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 1, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "This format is used if country specific format is not found", - "fieldname": "is_default", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Is Default", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "description": "Uses Jinja Templating and all the fields of Address (including Custom Fields if any) will be available
\n{{ address_line1 }}<br>\n{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}\n{{ city }}<br>\n{% if state %}{{ state }}<br>{% endif -%}\n{% if pincode %} PIN: {{ pincode }}<br>{% endif -%}\n{{ country }}<br>\n{% if phone %}Phone: {{ phone }}<br>{% endif -%}\n{% if fax %}Fax: {{ fax }}<br>{% endif -%}\n{% if email_id %}Email: {{ email_id }}<br>{% endif -%}\n",
- "fieldname": "template",
- "fieldtype": "Code",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Template",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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
- }
- ],
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-map-marker",
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "in_dialog": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2016-11-07 05:47:11.633848",
- "modified_by": "Administrator",
- "module": "Utilities",
- "name": "Address Template",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 0,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "is_custom": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 1,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/utilities/doctype/address_template/address_template.py b/erpnext/utilities/doctype/address_template/address_template.py
deleted file mode 100644
index 64aaa45d269..00000000000
--- a/erpnext/utilities/doctype/address_template/address_template.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.document import Document
-from frappe.utils.jinja import validate_template
-from frappe import _
-
-class AddressTemplate(Document):
- def validate(self):
- if not self.template:
- self.template = get_default_address_template()
-
- self.defaults = frappe.db.get_values("Address Template", {"is_default":1, "name":("!=", self.name)})
- if not self.is_default:
- if not self.defaults:
- self.is_default = 1
- frappe.msgprint(_("Setting this Address Template as default as there is no other default"))
-
- validate_template(self.template)
-
- def on_update(self):
- if self.is_default and self.defaults:
- for d in self.defaults:
- frappe.db.set_value("Address Template", d[0], "is_default", 0)
-
- def on_trash(self):
- if self.is_default:
- frappe.throw(_("Default Address Template cannot be deleted"))
-
-@frappe.whitelist()
-def get_default_address_template():
- '''Get default address template (translated)'''
- return '''{{ address_line1 }}