From 9784d27317cf8e426c366a60438f4b40591124eb Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 30 Dec 2016 16:21:35 +0530 Subject: [PATCH 01/32] Optimization to reduce GLE reposting time for future stock transactions --- .../doctype/fiscal_year/fiscal_year.py | 2 + erpnext/accounts/doctype/gl_entry/gl_entry.py | 23 +++--- .../period_closing_voucher.py | 4 +- .../test_period_closing_voucher.py | 4 +- .../purchase_invoice/purchase_invoice.py | 6 +- .../doctype/sales_invoice/sales_invoice.py | 6 +- erpnext/accounts/general_ledger.py | 21 ++++-- .../accounts/report/cash_flow/cash_flow.py | 9 ++- .../accounts/report/financial_statements.py | 5 +- erpnext/accounts/utils.py | 75 +++++++++++++------ erpnext/controllers/accounts_controller.py | 2 +- erpnext/controllers/stock_controller.py | 29 ++++--- .../vehicle_expenses/vehicle_expenses.py | 2 +- .../process_payroll/process_payroll.py | 7 +- .../doctype/salary_slip/test_salary_slip.py | 4 +- .../stock_ledger_entry/stock_ledger_entry.py | 7 +- 16 files changed, 128 insertions(+), 78 deletions(-) diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py index 2ff98da983..517a2a332e 100644 --- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py +++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py @@ -43,11 +43,13 @@ class FiscalYear(Document): def on_update(self): check_duplicate_fiscal_year(self) + frappe.cache().delete_value("fiscal_years") def on_trash(self): global_defaults = frappe.get_doc("Global Defaults") if global_defaults.current_fiscal_year == self.name: frappe.throw(_("You cannot delete Fiscal Year {0}. Fiscal Year {0} is set as default in Global Settings").format(self.name)) + frappe.cache().delete_value("fiscal_years") def validate_overlap(self): existing_fiscal_years = frappe.db.sql("""select name from `tabFiscal Year` diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 5773813955..ce60298c17 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -18,22 +18,27 @@ class GLEntry(Document): def validate(self): self.flags.ignore_submit_comment = True self.check_mandatory() - self.pl_must_have_cost_center() - self.check_pl_account() - self.validate_cost_center() - self.validate_party() - self.validate_currency() self.validate_and_set_fiscal_year() + + if not self.flags.from_repost: + self.pl_must_have_cost_center() + self.check_pl_account() + self.validate_cost_center() + self.validate_party() + self.validate_currency() - def on_update_with_args(self, adv_adj, update_outstanding = 'Yes'): - self.validate_account_details(adv_adj) + + def on_update_with_args(self, adv_adj, update_outstanding = 'Yes', from_repost=False): + if not from_repost: + self.validate_account_details(adv_adj) + check_freezing_date(self.posting_date, adv_adj) + validate_frozen_account(self.account, adv_adj) - check_freezing_date(self.posting_date, adv_adj) validate_balance_type(self.account, adv_adj) # Update outstanding amt on against voucher if self.against_voucher_type in ['Journal Entry', 'Sales Invoice', 'Purchase Invoice'] \ - and self.against_voucher and update_outstanding == 'Yes': + and self.against_voucher and update_outstanding == 'Yes' and not from_repost: update_outstanding_amt(self.account, self.party_type, self.party, self.against_voucher_type, self.against_voucher) diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py index 04d4ed7078..03d0918226 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py @@ -35,9 +35,9 @@ class PeriodClosingVoucher(AccountsController): def validate_posting_date(self): from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year - validate_fiscal_year(self.posting_date, self.fiscal_year, label=_("Posting Date"), doc=self) + validate_fiscal_year(self.posting_date, self.fiscal_year, self.company, label=_("Posting Date"), doc=self) - self.year_start_date = get_fiscal_year(self.posting_date, self.fiscal_year)[1] + self.year_start_date = get_fiscal_year(self.posting_date, self.fiscal_year, company=self.company)[1] pce = frappe.db.sql("""select name from `tabPeriod Closing Voucher` where posting_date > %s and fiscal_year = %s and docstatus = 1""", diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py index d68e29157b..9ef66edc34 100644 --- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py +++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py @@ -11,7 +11,7 @@ from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journ class TestPeriodClosingVoucher(unittest.TestCase): def test_closing_entry(self): - year_start_date = get_fiscal_year(today())[1] + year_start_date = get_fiscal_year(today(), company="_Test Company")[1] make_journal_entry("_Test Bank - _TC", "Sales - _TC", 400, "_Test Cost Center - _TC", posting_date=now(), submit=True) @@ -70,7 +70,7 @@ class TestPeriodClosingVoucher(unittest.TestCase): "doctype": "Period Closing Voucher", "closing_account_head": "_Test Account Reserves and Surplus - _TC", "company": "_Test Company", - "fiscal_year": get_fiscal_year(today())[0], + "fiscal_year": get_fiscal_year(today(), company="_Test Company")[0], "posting_date": today(), "remarks": "test" }) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 14459fa497..c0693d14a6 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -302,11 +302,11 @@ class PurchaseInvoice(BuyingController): asset.flags.ignore_validate_update_after_submit = True asset.save() - 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 not self.grand_total: return - - gl_entries = self.get_gl_entries() + if not gl_entries: + gl_entries = self.get_gl_entries() if gl_entries: update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes" diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index db6d594580..64425c8d88 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -532,10 +532,12 @@ class SalesInvoice(SellingController): if d.delivery_note and frappe.db.get_value("Delivery Note", d.delivery_note, "docstatus") != 1: throw(_("Delivery Note {0} is not submitted").format(d.delivery_note)) - 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 not self.grand_total: return - gl_entries = self.get_gl_entries() + + if not gl_entries: + gl_entries = self.get_gl_entries() if gl_entries: from erpnext.accounts.general_ledger import make_gl_entries diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 392902c935..4c5535d69a 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -11,12 +11,12 @@ from erpnext.accounts.doctype.budget.budget import validate_expense_against_budg class StockAccountInvalidTransaction(frappe.ValidationError): pass -def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes'): +def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes', from_repost=False): if gl_map: if not cancel: gl_map = process_gl_map(gl_map, merge_entries) if gl_map and len(gl_map) > 1: - save_entries(gl_map, adv_adj, update_outstanding) + save_entries(gl_map, adv_adj, update_outstanding, from_repost) else: frappe.throw(_("Incorrect number of General Ledger Entries found. You might have selected a wrong Account in the transaction.")) else: @@ -78,21 +78,26 @@ def check_if_in_list(gle, gl_map): and cstr(e.get('project')) == cstr(gle.get('project')): return e -def save_entries(gl_map, adv_adj, update_outstanding): - validate_account_for_auto_accounting_for_stock(gl_map) +def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False): + if not from_repost: + validate_account_for_auto_accounting_for_stock(gl_map) + round_off_debit_credit(gl_map) for entry in gl_map: - make_entry(entry, adv_adj, update_outstanding) + make_entry(entry, adv_adj, update_outstanding, from_repost) + # check against budget - validate_expense_against_budget(entry) + if not from_repost: + validate_expense_against_budget(entry) -def make_entry(args, adv_adj, update_outstanding): +def make_entry(args, adv_adj, update_outstanding, from_repost=False): args.update({"doctype": "GL Entry"}) gle = frappe.get_doc(args) gle.flags.ignore_permissions = 1 + gle.flags.from_repost = from_repost gle.insert() - gle.run_method("on_update_with_args", adv_adj, update_outstanding) + gle.run_method("on_update_with_args", adv_adj, update_outstanding, from_repost) gle.submit() def validate_account_for_auto_accounting_for_stock(gl_map): diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py index 182878af37..7a776f57e1 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 bc4a220faa..c897d1ca61 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 8e59d8f99b..187fc24142 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] diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 554529c6f6..da0591134e 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/stock_controller.py b/erpnext/controllers/stock_controller.py index f0c8dbfc16..3e900b2814 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/fleet_management/report/vehicle_expenses/vehicle_expenses.py b/erpnext/fleet_management/report/vehicle_expenses/vehicle_expenses.py index 717a94f271..a03b7f3e13 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/hr/doctype/process_payroll/process_payroll.py b/erpnext/hr/doctype/process_payroll/process_payroll.py index 45030cba13..0d9fc7ccdb 100644 --- a/erpnext/hr/doctype/process_payroll/process_payroll.py +++ b/erpnext/hr/doctype/process_payroll/process_payroll.py @@ -284,17 +284,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 54faa64053..d1a8d81da8 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/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index 2caabee7b4..00e3abec71 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -27,9 +27,6 @@ class StockLedgerEntry(Document): self.validate_and_set_fiscal_year() self.block_transactions_against_group_warehouse() - from erpnext.accounts.utils import validate_fiscal_year - validate_fiscal_year(self.posting_date, self.fiscal_year, self.meta.get_label("posting_date"), self) - def on_submit(self): self.check_stock_frozen_date() self.actual_amt_check() @@ -117,6 +114,10 @@ class StockLedgerEntry(Document): def validate_and_set_fiscal_year(self): if not self.fiscal_year: self.fiscal_year = get_fiscal_year(self.posting_date, company=self.company)[0] + else: + from erpnext.accounts.utils import validate_fiscal_year + validate_fiscal_year(self.posting_date, self.fiscal_year, self.company, + self.meta.get_label("posting_date"), self) def block_transactions_against_group_warehouse(self): from erpnext.stock.utils import is_group_warehouse From 138c2f6b294f607f51055e8ed5c0ed94f4884220 Mon Sep 17 00:00:00 2001 From: robert schouten Date: Mon, 9 Jan 2017 11:02:55 +0800 Subject: [PATCH 02/32] [fix] timesheet overlap validation not including modified timesheet --- erpnext/projects/doctype/timesheet/timesheet.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index c3dbcd4180..490a70721a 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 @@ -359,7 +368,8 @@ def get_events(start, end, filters=None): conditions = get_conditions(filters) return frappe.db.sql("""select `tabTimesheet Detail`.name as name, `tabTimesheet Detail`.docstatus as status, `tabTimesheet Detail`.parent as parent, - from_time as start_date, hours, activity_type, project, to_time as end_date + from_time as start_date, hours, activity_type, project, to_time as end_date, + CONCAT(`tabTimesheet Detail`.parent, ' (', ROUND(hours,2),' hrs)') as title from `tabTimesheet Detail`, `tabTimesheet` where `tabTimesheet Detail`.parent = `tabTimesheet`.name and `tabTimesheet`.docstatus < 2 From 2b41f9d5488aafc9e8e0476d91c84904a922ab7f Mon Sep 17 00:00:00 2001 From: Kanchan Chauhan Date: Mon, 9 Jan 2017 18:43:52 +0530 Subject: [PATCH 03/32] [Fix] Payroll Frequency toggle fix --- erpnext/hr/doctype/process_payroll/process_payroll.js | 5 +++++ erpnext/hr/doctype/process_payroll/process_payroll.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/process_payroll/process_payroll.js b/erpnext/hr/doctype/process_payroll/process_payroll.js index 0ad8cec549..cfb646d033 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 45030cba13..7741263aac 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))) From 43e07aed2c6954fcb18a04c244d34aa8d21b93b8 Mon Sep 17 00:00:00 2001 From: Kanchan Chauhan Date: Tue, 10 Jan 2017 12:06:51 +0530 Subject: [PATCH 04/32] [Minor]Valuation rate in Quick entry for Item --- erpnext/stock/doctype/item/item.json | 149 ++++++--------------------- 1 file changed, 29 insertions(+), 120 deletions(-) diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index a31aed4a89..d90235143b 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -26,7 +26,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "", "length": 0, "no_copy": 0, @@ -55,7 +54,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Series", "length": 0, "no_copy": 0, @@ -84,7 +82,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Item Code", "length": 0, "no_copy": 1, @@ -115,7 +112,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 1, "label": "Variant Of", "length": 0, "no_copy": 0, @@ -144,7 +140,6 @@ "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, - "in_standard_filter": 0, "label": "Item Name", "length": 0, "no_copy": 0, @@ -173,7 +168,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Barcode", "length": 0, "no_copy": 1, @@ -201,7 +195,6 @@ "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 1, - "in_standard_filter": 1, "label": "Item Group", "length": 0, "no_copy": 0, @@ -232,7 +225,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Unit of Measure", "length": 0, "no_copy": 0, @@ -262,7 +254,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -288,7 +279,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Disabled", "length": 0, "no_copy": 0, @@ -318,7 +308,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Maintain Stock", "length": 0, "no_copy": 0, @@ -349,7 +338,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Opening Stock", "length": 0, "no_copy": 0, @@ -365,40 +353,39 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:(doc.__islocal && doc.is_stock_item && !doc.has_serial_no && !doc.has_batch_no && doc.opening_stock)", - "fieldname": "valuation_rate", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Valuation Rate", - "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": 1, "collapsible": 0, "columns": 0, + "depends_on": "eval:(doc.__islocal && doc.is_stock_item && !doc.has_serial_no && !doc.has_batch_no && doc.opening_stock)", + "fieldname": "valuation_rate", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Valuation Rate", + "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": "standard_rate", "fieldtype": "Currency", "hidden": 0, @@ -406,7 +393,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Standard Selling Rate", "length": 0, "no_copy": 0, @@ -434,7 +420,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Is Fixed Asset", "length": 0, "no_copy": 0, @@ -463,7 +448,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Asset Category", "length": 0, "no_copy": 0, @@ -492,7 +476,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Image", "length": 0, "no_copy": 0, @@ -521,7 +504,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Description", "length": 0, "no_copy": 0, @@ -549,7 +531,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Brand", "length": 0, "no_copy": 0, @@ -579,7 +560,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Description", "length": 0, "no_copy": 0, @@ -610,7 +590,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Inventory", "length": 0, "no_copy": 0, @@ -641,7 +620,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Warehouse", "length": 0, "no_copy": 0, @@ -673,7 +651,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "End of Life", "length": 0, "no_copy": 0, @@ -704,7 +681,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Has Batch No", "length": 0, "no_copy": 0, @@ -737,7 +713,6 @@ "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, - "in_standard_filter": 0, "label": "Has Serial No", "length": 0, "no_copy": 0, @@ -769,7 +744,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Serial Number Series", "length": 0, "no_copy": 0, @@ -797,7 +771,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Material Request Type", "length": 0, "no_copy": 0, @@ -827,7 +800,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "length": 0, "no_copy": 0, "oldfieldtype": "Column Break", @@ -857,7 +829,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Allow over delivery or receipt upto this percent", "length": 0, "no_copy": 0, @@ -887,7 +858,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Valuation Method", "length": 0, "no_copy": 0, @@ -916,7 +886,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Warranty Period (in days)", "length": 0, "no_copy": 0, @@ -947,7 +916,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Net Weight", "length": 0, "no_copy": 0, @@ -975,7 +943,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Weight UOM", "length": 0, "no_copy": 0, @@ -1005,7 +972,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Auto re-order", "length": 0, "no_copy": 0, @@ -1035,7 +1001,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Reorder level based on Warehouse", "length": 0, "no_copy": 0, @@ -1065,7 +1030,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Variants", "length": 0, "no_copy": 0, @@ -1096,7 +1060,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Has Variants", "length": 0, "no_copy": 1, @@ -1126,7 +1089,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Attributes", "length": 0, "no_copy": 1, @@ -1155,7 +1117,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Purchase Details", "length": 0, "no_copy": 0, @@ -1185,7 +1146,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Is Purchase Item", "length": 0, "no_copy": 0, @@ -1216,7 +1176,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Minimum Order Qty", "length": 0, "no_copy": 0, @@ -1245,7 +1204,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Safety Stock", "length": 0, "no_copy": 0, @@ -1275,7 +1233,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Lead Time in days", "length": 0, "no_copy": 0, @@ -1306,7 +1263,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Buying Cost Center", "length": 0, "no_copy": 0, @@ -1338,7 +1294,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Expense Account", "length": 0, "no_copy": 0, @@ -1369,7 +1324,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Unit of Measure Conversion", "length": 0, "no_copy": 0, @@ -1399,7 +1353,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "UOMs", "length": 0, "no_copy": 1, @@ -1430,7 +1383,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Last Purchase Rate", "length": 0, "no_copy": 1, @@ -1460,7 +1412,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Supplier Details", "length": 0, "no_copy": 0, @@ -1489,7 +1440,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Supplier", "length": 0, "no_copy": 0, @@ -1517,7 +1467,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Delivered by Supplier (Drop Ship)", "length": 0, "no_copy": 0, @@ -1546,7 +1495,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Manufacturer", "length": 0, "no_copy": 0, @@ -1575,7 +1523,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Manufacturer Part Number", "length": 0, "no_copy": 0, @@ -1603,7 +1550,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Item Code for Suppliers", "length": 0, "no_copy": 0, @@ -1633,7 +1579,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Supplier Items", "length": 0, "no_copy": 0, @@ -1661,7 +1606,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Sales Details", "length": 0, "no_copy": 0, @@ -1691,7 +1635,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Is Sales Item", "length": 0, "no_copy": 0, @@ -1721,7 +1664,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Publish in Hub", "length": 0, "no_copy": 0, @@ -1750,7 +1692,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Synced With Hub", "length": 0, "no_copy": 0, @@ -1779,7 +1720,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Income Account", "length": 0, "no_copy": 0, @@ -1808,7 +1748,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Default Selling Cost Center", "length": 0, "no_copy": 0, @@ -1837,7 +1776,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Customer Item Codes", "length": 0, "no_copy": 0, @@ -1868,7 +1806,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Customer Items", "length": 0, "no_copy": 0, @@ -1897,7 +1834,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Max Discount (%)", "length": 0, "no_copy": 0, @@ -1926,7 +1862,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Item Tax", "length": 0, "no_copy": 0, @@ -1956,7 +1891,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Taxes", "length": 0, "no_copy": 0, @@ -1986,7 +1920,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Inspection Criteria", "length": 0, "no_copy": 0, @@ -2016,7 +1949,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Inspection Required before Purchase", "length": 0, "no_copy": 0, @@ -2046,7 +1978,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Inspection Required before Delivery", "length": 0, "no_copy": 0, @@ -2076,7 +2007,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Quality Parameters", "length": 0, "no_copy": 0, @@ -2107,7 +2037,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Manufacturing", "length": 0, "no_copy": 0, @@ -2137,7 +2066,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Default BOM", "length": 0, "no_copy": 1, @@ -2169,7 +2097,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Supply Raw Materials for Purchase", "length": 0, "no_copy": 0, @@ -2199,7 +2126,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -2226,7 +2152,6 @@ "ignore_xss_filter": 0, "in_filter": 1, "in_list_view": 0, - "in_standard_filter": 0, "label": "Customer Code", "length": 0, "no_copy": 1, @@ -2253,7 +2178,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Website", "length": 0, "no_copy": 0, @@ -2282,7 +2206,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Show in Website", "length": 0, "no_copy": 0, @@ -2310,7 +2233,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Show in Website (Variant)", "length": 0, "no_copy": 0, @@ -2339,7 +2261,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Route", "length": 0, "no_copy": 0, @@ -2369,7 +2290,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Weightage", "length": 0, "no_copy": 0, @@ -2398,7 +2318,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Slideshow", "length": 0, "no_copy": 0, @@ -2428,7 +2347,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Image", "length": 0, "no_copy": 0, @@ -2456,7 +2374,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Thumbnail", "length": 0, "no_copy": 0, @@ -2484,7 +2401,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -2512,7 +2428,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Website Warehouse", "length": 0, "no_copy": 0, @@ -2542,7 +2457,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Website Item Groups", "length": 0, "no_copy": 0, @@ -2572,7 +2486,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Website Specifications", "length": 0, "no_copy": 0, @@ -2600,7 +2513,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Copy From Item Group", "length": 0, "no_copy": 0, @@ -2628,7 +2540,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Website Specifications", "length": 0, "no_copy": 0, @@ -2657,7 +2568,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Website Description", "length": 0, "no_copy": 0, @@ -2684,7 +2594,6 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_list_view": 0, - "in_standard_filter": 0, "label": "Total Projected Qty", "length": 0, "no_copy": 0, @@ -2713,7 +2622,7 @@ "issingle": 0, "istable": 0, "max_attachments": 1, - "modified": "2016-12-27 12:17:44.227302", + "modified": "2017-01-10 12:02:51.807965", "modified_by": "Administrator", "module": "Stock", "name": "Item", From 01baceb74e416b66d16ac31eb7586a30c8fd2cdb Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 10 Jan 2017 12:19:48 +0530 Subject: [PATCH 05/32] Revert "proposed usage of daterange picker" --- .../daily_timesheet_summary.js | 16 ++++++++++------ .../daily_timesheet_summary.py | 4 +--- 2 files changed, 11 insertions(+), 9 deletions(-) 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 d085a330fd..93cb9402fa 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 6ed3b5801f..682fb2e09d 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" From 4180a3777301bdb767d228e96ccfd4f6a2f110cf Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 10 Jan 2017 13:00:09 +0600 Subject: [PATCH 06/32] bumped to version 7.2.8 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 3338d3f426..bc7ef5726b 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '7.2.7' +__version__ = '7.2.8' def get_default_company(user=None): '''Get default company for user''' From d40e661ebde7d91aa34229b2e3cc689467daf61a Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 10 Jan 2017 14:46:45 +0530 Subject: [PATCH 07/32] [style] better demo start page --- erpnext/hooks.py | 2 +- erpnext/public/css/website.css | 1 - erpnext/public/less/website.less | 6 +----- erpnext/templates/pages/demo.html | 32 +++++++++++++++---------------- 4 files changed, 18 insertions(+), 23 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 95f6c0b5c4..59a1e2b2b6 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 = [ diff --git a/erpnext/public/css/website.css b/erpnext/public/css/website.css index 6a1d311e98..1617ea7bd1 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/less/website.less b/erpnext/public/less/website.less index b270b8bed7..a645f28d71 100644 --- a/erpnext/public/less/website.less +++ b/erpnext/public/less/website.less @@ -93,14 +93,10 @@ color: @text-muted; } - .transaction-time { - // margin-left: 15px; - } - - .items-preview, .transaction-time { margin-top: 5px; } + } // order.html diff --git a/erpnext/templates/pages/demo.html b/erpnext/templates/pages/demo.html index 3850cd3e6f..108319fcf1 100644 --- a/erpnext/templates/pages/demo.html +++ b/erpnext/templates/pages/demo.html @@ -48,23 +48,23 @@ $(document).ready(function() { {% endblock %} {% block page_content %} +
- -
- -

ERPNext Demo

-

- -

- - - -
-

Some functionality is disabled for the demo app. The demo data will be cleared regulary. - - To start your free ERPNext account, click here

+
+ + {{ _("ERPNext Demo") }} +
+ +

Some functionality is disabled for the demo and the data will be cleared regulary.

+
+ +

Sign up for a Free ERPNext.com account here +

+ {% endblock %} From 4a15fa4c861b67b92b31bfd57377e6c3abb6a1d7 Mon Sep 17 00:00:00 2001 From: Kanchan Chauhan Date: Tue, 10 Jan 2017 16:01:38 +0530 Subject: [PATCH 08/32] Sync Project Task and Task --- erpnext/projects/doctype/project/project.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 388f43e93d..276259b5ae 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() From 5dd988207f0542def75cf66cba26c5dd5578269d Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 10 Jan 2017 16:10:40 +0530 Subject: [PATCH 09/32] Show values based on precision and filter out zero value rows --- .../report/stock_balance/stock_balance.py | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index d5d6f9dbe4..a8db4e09b6 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -102,7 +102,7 @@ def get_item_warehouse_map(filters): "in_qty": 0.0, "in_val": 0.0, "out_qty": 0.0, "out_val": 0.0, "bal_qty": 0.0, "bal_val": 0.0, - "val_rate": 0.0, "uom": None + "val_rate": 0.0 }) qty_dict = iwb_map[(d.company, d.item_code, d.warehouse)] @@ -129,6 +129,24 @@ def get_item_warehouse_map(filters): qty_dict.val_rate = d.valuation_rate qty_dict.bal_qty += qty_diff qty_dict.bal_val += value_diff + + iwb_map = filter_items_with_no_transactions(iwb_map) + + return iwb_map + +def filter_items_with_no_transactions(iwb_map): + for (company, item, warehouse) in sorted(iwb_map): + qty_dict = iwb_map[(company, item, warehouse)] + + no_transactions = True + for key, val in qty_dict.items(): + val = flt(val, 3) + qty_dict[key] = val + if key != "val_rate" and val: + no_transactions = False + + if no_transactions: + iwb_map.pop((company, item, warehouse)) return iwb_map From c4aceaad7fa58ca2d49c2b0db09b3aea3b97d1a5 Mon Sep 17 00:00:00 2001 From: Kanchan Chauhan Date: Tue, 10 Jan 2017 16:35:54 +0530 Subject: [PATCH 10/32] [Minor] Added Projects Manager role --- erpnext/projects/doctype/project/project.json | 62 +++++++------------ 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/erpnext/projects/doctype/project/project.json b/erpnext/projects/doctype/project/project.json index 37ca968ae9..38ebbcb4f8 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, From c0eab41ec5eff8228cb633d7a9e11f4fd9324b40 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 11 Jan 2017 10:16:10 +0530 Subject: [PATCH 11/32] Fix for Budget against Project --- erpnext/accounts/doctype/budget/budget.py | 9 ++-- .../doctype/sales_invoice/sales_invoice.py | 52 ++++++++++--------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/erpnext/accounts/doctype/budget/budget.py b/erpnext/accounts/doctype/budget/budget.py index 5fc4fbf319..15d6f106df 100644 --- a/erpnext/accounts/doctype/budget/budget.py +++ b/erpnext/accounts/doctype/budget/budget.py @@ -63,7 +63,7 @@ def validate_expense_against_budget(args): and frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"}): if args.project: - condition = "and exists(select name from `tabProject` where name=b.project)" + condition = "and b.project='%s'" % frappe.db.escape(args.project) args.budget_against_field = "Project" elif args.cost_center: @@ -88,12 +88,13 @@ def validate_expense_against_budget(args): """.format(condition=condition, budget_against_field=frappe.scrub(args.get("budget_against_field"))), (args.fiscal_year, args.account), as_dict=True) - - validate_budget_records(args, budget_records) + + if budget_records: + validate_budget_records(args, budget_records) def validate_budget_records(args, budget_records): for budget in budget_records: - if budget.budget_amount: + if flt(budget.budget_amount): yearly_action = budget.action_if_annual_budget_exceeded monthly_action = budget.action_if_accumulated_monthly_budget_exceeded diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index db6d594580..c5aa7ea893 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -651,32 +651,34 @@ class SalesInvoice(SellingController): def make_pos_gl_entries(self, gl_entries): if cint(self.is_pos): for payment_mode in self.payments: - # POS, make payment entries - gl_entries.append( - self.get_gl_dict({ - "account": self.debit_to, - "party_type": "Customer", - "party": self.customer, - "against": payment_mode.account, - "credit": payment_mode.base_amount, - "credit_in_account_currency": payment_mode.base_amount \ - if self.party_account_currency==self.company_currency \ - else payment_mode.amount, - "against_voucher": self.return_against if cint(self.is_return) else self.name, - "against_voucher_type": self.doctype, - }, self.party_account_currency) - ) + if payment_mode.amount: + # POS, make payment entries + gl_entries.append( + self.get_gl_dict({ + "account": self.debit_to, + "party_type": "Customer", + "party": self.customer, + "against": payment_mode.account, + "credit": payment_mode.base_amount, + "credit_in_account_currency": payment_mode.base_amount \ + if self.party_account_currency==self.company_currency \ + else payment_mode.amount, + "against_voucher": self.return_against if cint(self.is_return) else self.name, + "against_voucher_type": self.doctype, + }, self.party_account_currency) + ) - payment_mode_account_currency = get_account_currency(payment_mode.account) - gl_entries.append( - self.get_gl_dict({ - "account": payment_mode.account, - "against": self.customer, - "debit": payment_mode.base_amount, - "debit_in_account_currency": payment_mode.base_amount \ - if payment_mode_account_currency==self.company_currency else payment_mode.amount - }, payment_mode_account_currency) - ) + payment_mode_account_currency = get_account_currency(payment_mode.account) + gl_entries.append( + self.get_gl_dict({ + "account": payment_mode.account, + "against": self.customer, + "debit": payment_mode.base_amount, + "debit_in_account_currency": payment_mode.base_amount \ + if payment_mode_account_currency==self.company_currency \ + else payment_mode.amount + }, payment_mode_account_currency) + ) def make_gle_for_change_amount(self, gl_entries): if cint(self.is_pos) and self.change_amount: From 0287d31c0f7ca7baba09775193ca0772d4cbb2f2 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 11 Jan 2017 10:31:33 +0530 Subject: [PATCH 12/32] Fetch bin details after setting warehouse based on POS Profile --- erpnext/stock/get_item_details.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 9b944facf5..b21cc3b2b1 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -42,9 +42,6 @@ def get_item_details(args): get_party_item_code(args, item_doc, out) - if out.get("warehouse"): - out.update(get_bin_details(args.item_code, out.warehouse)) - if frappe.db.exists("Product Bundle", args.item_code): valuation_rate = 0.0 bundled_items = frappe.get_doc("Product Bundle", args.item_code) @@ -65,6 +62,9 @@ def get_item_details(args): if args.customer and cint(args.is_pos): out.update(get_pos_profile_item_details(args.company, args)) + + if out.get("warehouse"): + out.update(get_bin_details(args.item_code, out.warehouse)) # update args with out, if key or value not exists for key, value in out.iteritems(): From 595cfb9f176114cec3b083313c1a3b847f0162ad Mon Sep 17 00:00:00 2001 From: Kanchan Chauhan Date: Wed, 11 Jan 2017 12:03:15 +0530 Subject: [PATCH 13/32] [Minor] Field type of Description field changed to Text Editor --- .../maintenance_schedule_item.json | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) 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 e9192f77a2..1e68fab4d6 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", From 2f02101d7de9334f71834efb36e4304dc3b305fe Mon Sep 17 00:00:00 2001 From: Saurabh Date: Wed, 11 Jan 2017 12:41:01 +0530 Subject: [PATCH 14/32] [fix] provision to handle custom mandatory params while creating node --- erpnext/accounts/utils.py | 10 +++++++-- erpnext/stock/doctype/warehouse/warehouse.py | 23 +++++--------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 8e59d8f99b..b7fef75de8 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -206,9 +206,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 +236,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/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index e01cc0b6fe..5fa300f139 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -269,26 +269,13 @@ def get_children(): @frappe.whitelist() def add_node(): - doctype = frappe.form_dict.get('doctype') - company = frappe.form_dict.get('company') - parent_field = 'parent_' + doctype.lower().replace(' ', '_') - name_field = doctype.lower().replace(' ', '_') + '_name' + from frappe.desk.treeview import make_tree_args + args = make_tree_args(**frappe.form_dict) - doc = frappe.new_doc(doctype) + if cint(args.is_root): + args.parent_warehouse = None - parent = frappe.form_dict['parent'] - - if cint(frappe.form_dict['is_root']): - parent = None - - doc.update({ - name_field: frappe.form_dict['warehouse_name'], - parent_field: parent, - "is_group": frappe.form_dict['is_group'], - "company": company - }) - - doc.save() + frappe.get_doc(args).insert() @frappe.whitelist() def convert_to_group_or_ledger(): From 7182de76847bc44d21de91661d135276e8d12ebf Mon Sep 17 00:00:00 2001 From: RicardoJohann Date: Wed, 11 Jan 2017 06:28:59 -0200 Subject: [PATCH 15/32] allowed rename salary structure --- erpnext/hr/doctype/salary_structure/salary_structure.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.json b/erpnext/hr/doctype/salary_structure/salary_structure.json index 8db8e93ef7..ca59ded940 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 +} From 056276c60e467be1ff35df6621e87360fb8c5c9f Mon Sep 17 00:00:00 2001 From: Saurabh Date: Wed, 11 Jan 2017 15:50:09 +0530 Subject: [PATCH 16/32] [minor][fix] show date in user format --- .../doctype/cheque_print_template/cheque_print_template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py b/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py index 752ecdaeb7..5b7d73f2bd 100644 --- a/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py +++ b/erpnext/accounts/doctype/cheque_print_template/cheque_print_template.py @@ -35,7 +35,7 @@ def create_or_update_cheque_print_format(template_name): - {{doc.reference_date or '' }} + {{ frappe.utils.formatdate(doc.reference_date) or '' }} From 2f3ae914a6015f40a0f6289bd6b6e67105636c35 Mon Sep 17 00:00:00 2001 From: Kanchan Chauhan Date: Wed, 11 Jan 2017 19:43:16 +0530 Subject: [PATCH 17/32] Changes to Salary Register --- erpnext/config/hr.py | 2 +- .../monthly_salary_register.js | 34 ------------------- .../__init__.py | 0 .../salary_register.html} | 4 +-- .../report/salary_register/salary_register.js | 27 +++++++++++++++ .../salary_register.json} | 11 +++--- .../salary_register.py} | 11 +++--- 7 files changed, 40 insertions(+), 49 deletions(-) delete mode 100644 erpnext/hr/report/monthly_salary_register/monthly_salary_register.js rename erpnext/hr/report/{monthly_salary_register => salary_register}/__init__.py (100%) rename erpnext/hr/report/{monthly_salary_register/monthly_salary_register.html => salary_register/salary_register.html} (89%) create mode 100644 erpnext/hr/report/salary_register/salary_register.js rename erpnext/hr/report/{monthly_salary_register/monthly_salary_register.json => salary_register/salary_register.json} (59%) rename erpnext/hr/report/{monthly_salary_register/monthly_salary_register.py => salary_register/salary_register.py} (92%) diff --git a/erpnext/config/hr.py b/erpnext/config/hr.py index 55363abe80..75ebd27cd4 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/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 a879b39a6c..0000000000 --- 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 c77e4e58b8..2a9cd3ebdb 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")] %}

{%= __(report.report_name) %}

-
Fiscal Year: {%= filters.fiscal_year %}
-
Month: {%= filters.month %}
+
From {%= filters.date_range[0] %} to {%= filters.date_range[1] %}

@@ -36,4 +35,3 @@

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 0000000000..8b0faf5219 --- /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 d32e71e6ff..116691509e 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 e8d0a0bf2f..1e36b92e22 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" From 8afe2678136357b50eca8d65d55c59b6afdca110 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 12 Jan 2017 15:22:02 +0530 Subject: [PATCH 18/32] [Fix] POS issues --- erpnext/accounts/doctype/sales_invoice/pos.py | 21 ++++++++++++------- .../point_of_sale/point_of_sale.json | 4 ++-- erpnext/public/js/pos/pos_bill_item.html | 4 ++-- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index f5721e884d..99fed1ed40 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -39,14 +39,17 @@ def get_pos_data(): 'pricing_rules': get_pricing_rule_data(doc), 'print_template': print_template, 'pos_profile': pos_profile, - 'meta': { - 'invoice': frappe.get_meta('Sales Invoice'), - 'customer': frappe.get_meta('Customer'), - 'items': frappe.get_meta('Sales Invoice Item'), - 'taxes': frappe.get_meta('Sales Taxes and Charges') - } + 'meta': get_meta() } +def get_meta(): + doctype_meta = {'customer': frappe.get_meta('Customer')} + for row in frappe.get_all('DocField', fields = ['fieldname', 'options'], + filters = {'parent': 'Sales Invoice', 'fieldtype': 'Table'}): + doctype_meta[row.fieldname] = frappe.get_meta(row.options) + + return doctype_meta + def get_company_data(company): return frappe.get_all('Company', fields = ["*"], filters= {'name': company})[0] @@ -63,10 +66,10 @@ def update_pos_profile_data(doc, pos_profile, company_data): doc.currency = pos_profile.get('currency') or company_data.default_currency doc.conversion_rate = 1.0 - + if doc.currency != company_data.default_currency: doc.conversion_rate = get_exchange_rate(doc.currency, company_data.default_currency, doc.posting_date) - + doc.selling_price_list = pos_profile.get('selling_price_list') or \ frappe.db.get_value('Selling Settings', None, 'selling_price_list') doc.naming_series = pos_profile.get('naming_series') or 'SINV-' @@ -75,6 +78,8 @@ def update_pos_profile_data(doc, pos_profile, company_data): doc.apply_discount_on = pos_profile.get('apply_discount_on') if pos_profile.get('apply_discount') else '' doc.customer_group = pos_profile.get('customer_group') or get_root('Customer Group') doc.territory = pos_profile.get('territory') or get_root('Territory') + if pos_profile.get('tc_name'): + doc.terms = frappe.db.get_value('Terms and Conditions', pos_profile.get('tc_name'), 'terms') def get_root(table): root = frappe.db.sql(""" select name from `tab%(table)s` having diff --git a/erpnext/accounts/print_format/point_of_sale/point_of_sale.json b/erpnext/accounts/print_format/point_of_sale/point_of_sale.json index 367ce07e28..f7d5f630a3 100644 --- a/erpnext/accounts/print_format/point_of_sale/point_of_sale.json +++ b/erpnext/accounts/print_format/point_of_sale/point_of_sale.json @@ -7,10 +7,10 @@ "docstatus": 0, "doctype": "Print Format", "font": "Default", - "html": "\n\n

\n\t{{ company }}
\n\t{{ __(\"POS No : \") }}{{offline_pos_name}}
\n

\n

\n\t{{ __(\"Date\") }}: {{ dateutil.global_date_format(posting_date) }}
\n

\n\n
\n\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t\n\t\t{% for item in items %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% endfor %}\n\t\n
{{ __(\"Item\") }}{{ __(\"Qty\") }}{{ __(\"Amount\") }}
\n\t\t\t\t{{ item.item_name }}\n\t\t\t{{ format_number(item.qty, precision(\"difference\")) }}
@ {{ format_currency(item.rate, currency) }}
{{ format_currency(item.amount, currency) }}
\n\n\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% for row in taxes %}\n\t\t{% if not row.included_in_print_rate %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if discount_amount %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% endif %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n
\n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t
\n\t\t\t\t{{ row.description }}\n\t\t\t\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t
\n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t
\n\t\t\t\t{{ __(\"Grand Total\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t
\n\t\t\t\t{{ __(\"Paid Amount\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t
\n\n\n
\n

{{ __(\"Thank you, please visit again.\") }}

", + "html": "\n\n

\n\t{{ company }}
\n\t{{ __(\"POS No : \") }}{{offline_pos_name}}
\n

\n

\n\t{{ __(\"Date\") }}: {{ dateutil.global_date_format(posting_date) }}
\n

\n\n
\n\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t\n\t\t{% for item in items %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% endfor %}\n\t\n
{{ __(\"Item\") }}{{ __(\"Qty\") }}{{ __(\"Amount\") }}
\n\t\t\t\t{{ item.item_name }}\n\t\t\t{{ format_number(item.qty, precision(\"difference\")) }}
@ {{ format_currency(item.rate, currency) }}
{{ format_currency(item.amount, currency) }}
\n\n\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% for row in taxes %}\n\t\t{% if not row.included_in_print_rate %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if discount_amount %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% endif %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n
\n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t
\n\t\t\t\t{{ row.description }}\n\t\t\t\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t
\n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t
\n\t\t\t\t{{ __(\"Grand Total\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t
\n\t\t\t\t{{ __(\"Paid Amount\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t
\n\n\n
\n

{{ 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/public/js/pos/pos_bill_item.html b/erpnext/public/js/pos/pos_bill_item.html index d8833bb835..f5d1a7652e 100644 --- a/erpnext/public/js/pos/pos_bill_item.html +++ b/erpnext/public/js/pos/pos_bill_item.html @@ -2,7 +2,7 @@
{%= item_code || "" %}{%= item_name || "" %}
-
+
@@ -13,7 +13,7 @@
{% } %}
-
+
From ac81440a81afa6417de2d688d277176b5ea8f6b9 Mon Sep 17 00:00:00 2001 From: Felipe Orellana Date: Thu, 12 Jan 2017 12:08:20 -0500 Subject: [PATCH 19/32] [FIX] Contact form breaks on existing lead When an email address from the contacts form is from a existing lead utils.py tries to set new_lead(an undefined var) as the lead reference if a lead is found. --- erpnext/templates/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/templates/utils.py b/erpnext/templates/utils.py index 94f924243c..c1405c374f 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 From b6114e672f6674ffc848eff05a4fb5df28e0b1f9 Mon Sep 17 00:00:00 2001 From: Kanchan Chauhan Date: Fri, 13 Jan 2017 11:15:53 +0530 Subject: [PATCH 20/32] Patch to add Start and End Date in Salary Slips --- erpnext/patches.txt | 1 + erpnext/patches/v7_2/update_salary_slips.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 erpnext/patches/v7_2/update_salary_slips.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index ef1e2c12a9..492fc1bdbb 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -360,3 +360,4 @@ erpnext.patches.v7_1.set_sales_person_status 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_salary_slips \ 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 0000000000..232de2892d --- /dev/null +++ b/erpnext/patches/v7_2/update_salary_slips.py @@ -0,0 +1,16 @@ +import frappe +from erpnext.hr.doctype.process_payroll.process_payroll import get_month_details + +def execute(): + salary_slips = frappe.db.sql("""select fiscal_year, month, name from `tabSalary Slip` + where (month is not null and month != '') + and (fiscal_year is not null and fiscal_year != '') and + (start_date is null or start_date = '') and + (end_date is null or end_date = '') and docstatus != 2""") + + 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 From 29458836e4cc6a229952db5a8fb00d281ba63922 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 13 Jan 2017 12:51:19 +0530 Subject: [PATCH 21/32] [Fix] After amend the status become cancelled even if docstatus is zero --- erpnext/controllers/status_updater.py | 2 ++ erpnext/patches.txt | 1 + erpnext/patches/v7_2/update_doctype_status.py | 11 +++++++++++ 3 files changed, 14 insertions(+) create mode 100644 erpnext/patches/v7_2/update_doctype_status.py diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 096bb2df71..4fbee58c84 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/patches.txt b/erpnext/patches.txt index ef1e2c12a9..f74b171066 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -360,3 +360,4 @@ erpnext.patches.v7_1.set_sales_person_status 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_doctype_status \ No newline at end of file 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 0000000000..c66f3f2e73 --- /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 From 45cad45420243871607a787ff3d5a1d644771efa Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 13 Jan 2017 15:03:56 +0600 Subject: [PATCH 22/32] bumped to version 7.2.9 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index bc7ef5726b..454503fda7 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '7.2.8' +__version__ = '7.2.9' def get_default_company(user=None): '''Get default company for user''' From 7a3d418aa5dded1da582547f02cd9228676e936a Mon Sep 17 00:00:00 2001 From: robert schouten Date: Fri, 13 Jan 2017 17:21:09 +0800 Subject: [PATCH 23/32] Email inbox based off of frappe email inbox pr (#7308) * email inbox * inbox fixes * separate email-inbox to pass tests * separate email-inbox to pass tests * fix import * add more info to contact and address --- erpnext/hooks.py | 3 + erpnext/public/js/templates/address_list.html | 2 +- erpnext/public/js/templates/contact_list.html | 4 +- .../utilities/doctype/address/address.json | 31 ++- erpnext/utilities/doctype/address/address.py | 6 +- erpnext/utilities/doctype/contact/__init__.py | 38 ++++ erpnext/utilities/doctype/contact/contact.js | 36 +++- .../utilities/doctype/contact/contact.json | 31 ++- erpnext/utilities/doctype/contact/contact.py | 85 +++++++- .../doctype/organisation/__init__.py | 0 .../doctype/organisation/organisation.js | 14 ++ .../doctype/organisation/organisation.json | 199 ++++++++++++++++++ .../doctype/organisation/organisation.py | 13 ++ .../doctype/organisation/test_organisation.py | 12 ++ 14 files changed, 465 insertions(+), 9 deletions(-) create mode 100644 erpnext/utilities/doctype/organisation/__init__.py create mode 100644 erpnext/utilities/doctype/organisation/organisation.js create mode 100644 erpnext/utilities/doctype/organisation/organisation.json create mode 100644 erpnext/utilities/doctype/organisation/organisation.py create mode 100644 erpnext/utilities/doctype/organisation/test_organisation.py diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 59a1e2b2b6..25444d9988 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -165,6 +165,9 @@ doc_events = { "Address": { "validate": "erpnext.shopping_cart.cart.set_customer_in_address" }, + "Communication":{ + "after_insert":"erpnext.utilities.doctype.contact.match_email_to_contact" + }, # bubble transaction notification on master ('Opportunity', 'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice', diff --git a/erpnext/public/js/templates/address_list.html b/erpnext/public/js/templates/address_list.html index 6ee7d782bf..f9a317f173 100644 --- a/erpnext/public/js/templates/address_list.html +++ b/erpnext/public/js/templates/address_list.html @@ -2,7 +2,7 @@
{% for(var i=0, l=addr_list.length; i - {%= i+1 %}. {%= addr_list[i].address_type %} + {%= i+1 %}. {%= addr_list[i].address_type!="Other" ? addr_list[i].address_type : addr_list[i].address_title %} {% if(addr_list[i].is_primary_address) { %} ({%= __("Primary") %}){% } %} {% if(addr_list[i].is_shipping_address) { %} diff --git a/erpnext/public/js/templates/contact_list.html b/erpnext/public/js/templates/contact_list.html index ddd3e5292d..765ddf802d 100644 --- a/erpnext/public/js/templates/contact_list.html +++ b/erpnext/public/js/templates/contact_list.html @@ -8,7 +8,9 @@ {% if(contact_list[i].is_primary_contact) { %} ({%= __("Primary") %}) {% } %} - + {% if(contact_list[i].designation){ %} + – {%= contact_list[i].designation %} + {% } %} {%= __("Edit") %} diff --git a/erpnext/utilities/doctype/address/address.json b/erpnext/utilities/doctype/address/address.json index 329e05f587..70564acd24 100644 --- a/erpnext/utilities/doctype/address/address.json +++ b/erpnext/utilities/doctype/address/address.json @@ -595,6 +595,35 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "organisation", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Organisation", + "length": 0, + "no_copy": 0, + "options": "Organisation", + "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, @@ -750,7 +779,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-11-07 05:47:06.911933", + "modified": "2016-12-22 13:49:22.968498", "modified_by": "Administrator", "module": "Utilities", "name": "Address", diff --git a/erpnext/utilities/doctype/address/address.py b/erpnext/utilities/doctype/address/address.py index 2952531f01..2c84a9df55 100644 --- a/erpnext/utilities/doctype/address/address.py +++ b/erpnext/utilities/doctype/address/address.py @@ -19,7 +19,7 @@ class Address(Document): def autoname(self): if not self.address_title: self.address_title = self.customer \ - or self.supplier or self.sales_partner or self.lead + or self.supplier or self.sales_partner or self.lead or self.organisation if self.address_title: self.name = (cstr(self.address_title).strip() + "-" + cstr(self.address_type).strip()) @@ -30,7 +30,7 @@ class Address(Document): throw(_("Address Title is mandatory.")) def validate(self): - self.link_fields = ("customer", "supplier", "sales_partner", "lead") + self.link_fields = ("customer", "supplier", "sales_partner", "lead", "organisation") self.link_address() self.validate_primary_address() self.validate_shipping_address() @@ -83,7 +83,7 @@ class Address(Document): 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"]: + for fieldname in ["customer", "supplier", "sales_partner", "lead", "organisation"]: 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)) diff --git a/erpnext/utilities/doctype/contact/__init__.py b/erpnext/utilities/doctype/contact/__init__.py index baffc48825..e4075fda8e 100644 --- a/erpnext/utilities/doctype/contact/__init__.py +++ b/erpnext/utilities/doctype/contact/__init__.py @@ -1 +1,39 @@ from __future__ import unicode_literals +import frappe + +def match_email_to_contact(doc,method=None): + if doc.communication_type == "Communication": + origin_contact = frappe.db.sql( + "select name, email_id, supplier, supplier_name, customer, customer_name, user, organisation from `tabContact` where email_id <>''", + as_dict=1) + for comm in origin_contact: + if comm.email_id: + if (doc.sender and doc.sent_or_received == "Received" and doc.sender.find(comm.email_id) > -1) or ( + doc.recipients and doc.sent_or_received == "Sent" and doc.recipients.find( + comm.email_id) > -1): + if sum(1 for x in [comm.supplier, comm.customer, comm.user, comm.organisation] if x) > 1: + doc.db_set("timeline_doctype", "Contact") + doc.db_set("timeline_name", comm.name) + doc.db_set("timeline_label", doc.name) + + elif comm.supplier: + doc.db_set("timeline_doctype", "Supplier") + doc.db_set("timeline_name", comm.supplier) + doc.db_set("timeline_label", comm.supplier_name) + + elif comm.customer: + doc.db_set("timeline_doctype", "Customer") + doc.db_set("timeline_name", comm.customer) + doc.db_set("timeline_label", comm.customer_name) + elif comm.user: + doc.db_set("timeline_doctype", "User") + doc.db_set("timeline_name", comm.user) + doc.db_set("timeline_label", comm.user) + elif comm.organisation: + doc.db_set("timeline_doctype", "Organisation") + doc.db_set("timeline_name", comm.organisation) + doc.db_set("timeline_label", comm.organisation) + else: + doc.db_set("timeline_doctype", None) + doc.db_set("timeline_name", None) + doc.db_set("timeline_label", None) diff --git a/erpnext/utilities/doctype/contact/contact.js b/erpnext/utilities/doctype/contact/contact.js index 07d9d6f90b..db25e99dea 100644 --- a/erpnext/utilities/doctype/contact/contact.js +++ b/erpnext/utilities/doctype/contact/contact.js @@ -5,6 +5,21 @@ cur_frm.email_field = "email_id"; frappe.ui.form.on("Contact", { + onload:function(frm){ + if(frappe.route_titles["update_contact"]) + { + frappe.confirm("change email address from "+cur_frm.doc.email_id+ " to "+frappe.route_titles["update_contact"]["email_id"] + ,function(){ + cur_frm.doc.email_id = frappe.route_titles["update_contact"]["email_id"]; + cur_frm.refresh(); + cur_frm.dirty(); + delete frappe.route_titles["update_contact"]; + },function(){ + delete frappe.route_titles["update_contact"]; + }) + + } + }, refresh: function(frm) { if(!frm.doc.user && !frm.is_new() && frm.perm[0].write) { frm.add_custom_button(__("Invite as User"), function() { @@ -27,5 +42,24 @@ frappe.ui.form.on("Contact", { if(name && locals[doctype] && locals[doctype][name]) frappe.model.remove_from_locals(doctype, name); }); + var fieldlist = ["supplier","customer","user","organisation"] + if(frappe.route_titles["create_contact"]==1&&!($.map(fieldlist,function(v){return frm.doc[v]?true:false}).indexOf(true)!=-1)){ + $.each(fieldlist,function(i,v){ + cur_frm.set_df_property(v,"reqd",1); + }) + + } else { + $.each(fieldlist,function(i,v){ + cur_frm.set_df_property(v,"reqd",0); + }) + } + }, + after_save:function(frm){ + if (frappe.route_titles["create_contact"]) + { + delete frappe.route_titles["create_contact"] + frappe.set_route("email_inbox"); + frappe.pages['email_inbox'].Inbox.run() + } } -}); +}); \ No newline at end of file diff --git a/erpnext/utilities/doctype/contact/contact.json b/erpnext/utilities/doctype/contact/contact.json index 98061da23c..21046b7f57 100644 --- a/erpnext/utilities/doctype/contact/contact.json +++ b/erpnext/utilities/doctype/contact/contact.json @@ -469,6 +469,35 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "organisation", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Organisation", + "length": 0, + "no_copy": 0, + "options": "Organisation", + "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, @@ -653,7 +682,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-11-07 05:30:56.576752", + "modified": "2016-12-22 13:46:02.655141", "modified_by": "Administrator", "module": "Utilities", "name": "Contact", diff --git a/erpnext/utilities/doctype/contact/contact.py b/erpnext/utilities/doctype/contact/contact.py index be0f9858e9..03eb94cab1 100644 --- a/erpnext/utilities/doctype/contact/contact.py +++ b/erpnext/utilities/doctype/contact/contact.py @@ -15,7 +15,7 @@ class Contact(StatusUpdater): [cstr(self.get(f)).strip() for f in ["first_name", "last_name"]])) # concat party name if reqd - for fieldname in ("customer", "supplier", "sales_partner"): + for fieldname in ("customer", "supplier", "sales_partner", "organisation"): if self.get(fieldname): self.name = self.name + "-" + cstr(self.get(fieldname)).strip() break @@ -26,6 +26,7 @@ class Contact(StatusUpdater): self.set_user() if self.email_id: self.image = has_gravatar(self.email_id) + self.contact_update_communication_ref() def set_user(self): if not self.user and self.email_id: @@ -61,6 +62,88 @@ class Contact(StatusUpdater): frappe.db.sql("""update `tabIssue` set contact='' where contact=%s""", self.name) + def contact_update_communication_ref(self): + origin_communication = frappe.db.sql("select name, sender,recipients,sent_or_received from `tabCommunication`", + as_dict=1) + + if self.email_id: + self.email_id = self.email_id.lower() + comm = frappe._dict({"email_id": self.email_id, + "name": self.name, + "supplier": self.supplier, + "supplier_name": self.supplier_name, + "customer": self.customer, + "customer_name": self.customer_name, + "user": self.user, + "organisation": self.organisation + }) + for communication in origin_communication: + sender = communication.sender + recipients = communication.recipients + if comm.email_id: + if (sender and communication.sent_or_received == "Received" and sender.find( + comm.email_id) > -1) or ( + recipients and communication.sent_or_received == "Sent" and recipients.find( + comm.email_id) > -1): + if sum(1 for x in [comm.supplier, comm.customer, comm.user, comm.organisation] if x) > 1: + frappe.db.sql("""update `tabCommunication` + set timeline_doctype = %(timeline_doctype)s, + timeline_name = %(timeline_name)s, + timeline_label = %(timeline_label)s + where name = %(name)s""", { + "timeline_doctype": "Contact", + "timeline_name": comm.name, + "timeline_label": self.name, + "name": communication.name + }) + + elif comm.supplier: + frappe.db.sql("""update `tabCommunication` + set timeline_doctype = %(timeline_doctype)s, + timeline_name = %(timeline_name)s, + timeline_label = %(timeline_label)s + where name = %(name)s""", { + "timeline_doctype": "Supplier", + "timeline_name": comm.supplier, + "timeline_label": comm.supplier_name, + "name": communication.name + }) + + elif comm.customer: + + frappe.db.sql("""update `tabCommunication` + set timeline_doctype = %(timeline_doctype)s, + timeline_name = %(timeline_name)s, + timeline_label = %(timeline_label)s + where name = %(name)s""", { + "timeline_doctype": "Customer", + "timeline_name": comm.customer, + "timeline_label": comm.customer_name, + "name": communication.name + }) + elif comm.user: + frappe.db.sql("""update `tabCommunication` + set timeline_doctype = %(timeline_doctype)s, + timeline_name = %(timeline_name)s, + timeline_label = %(timeline_label)s + where name = %(name)s""", { + "timeline_doctype": "User", + "timeline_name": comm.user, + "timeline_label": comm.user, + "name": communication.name + }) + elif comm.organisation: + frappe.db.sql("""update `tabCommunication` + set timeline_doctype = %(timeline_doctype)s, + timeline_name = %(timeline_name)s, + timeline_label = %(timeline_label)s + where name = %(name)s""", { + "timeline_doctype": "Organisation", + "timeline_name": comm.organisation, + "timeline_label": comm.organisation, + "name": communication.name + }) + @frappe.whitelist() def invite_user(contact): contact = frappe.get_doc("Contact", contact) diff --git a/erpnext/utilities/doctype/organisation/__init__.py b/erpnext/utilities/doctype/organisation/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/utilities/doctype/organisation/organisation.js b/erpnext/utilities/doctype/organisation/organisation.js new file mode 100644 index 0000000000..2d3bb31bea --- /dev/null +++ b/erpnext/utilities/doctype/organisation/organisation.js @@ -0,0 +1,14 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Organisation', { + refresh: function(frm) { + frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); + + if(!frm.doc.__islocal) { + erpnext.utils.render_address_and_contact(frm); + } else { + erpnext.utils.clear_address_and_contact(frm); + } + } +}); diff --git a/erpnext/utilities/doctype/organisation/organisation.json b/erpnext/utilities/doctype/organisation/organisation.json new file mode 100644 index 0000000000..9cbcc90cf9 --- /dev/null +++ b/erpnext/utilities/doctype/organisation/organisation.json @@ -0,0 +1,199 @@ +{ + "allow_copy": 0, + "allow_import": 1, + "allow_rename": 1, + "autoname": "field:organisation_name", + "beta": 0, + "creation": "2016-08-22 11:08:27.151412", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", + "document_type": "", + "editable_grid": 0, + "fields": [ + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "organisation_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": "Name", + "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.__islocal", + "fieldname": "address_contacts", + "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": "Address and Contact", + "length": 0, + "no_copy": 0, + "options": "icon-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, + "fieldname": "address_html", + "fieldtype": "HTML", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Address HTML", + "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, + "fieldname": "column_break1", + "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": "contact_html", + "fieldtype": "HTML", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Contact HTML", + "length": 0, + "no_copy": 0, + "oldfieldtype": "HTML", + "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, + "idx": 0, + "image_view": 0, + "in_create": 0, + "in_dialog": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "modified": "2016-12-23 08:33:29.997375", + "modified_by": "Administrator", + "module": "Utilities", + "name": "Organisation", + "name_case": "", + "owner": "Administrator", + "permissions": [ + { + "amend": 0, + "apply_user_permissions": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 0, + "import": 1, + "is_custom": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Email User", + "set_user_permissions": 0, + "share": 1, + "submit": 0, + "write": 1 + } + ], + "quick_entry": 0, + "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/organisation/organisation.py b/erpnext/utilities/doctype/organisation/organisation.py new file mode 100644 index 0000000000..d04f226ea1 --- /dev/null +++ b/erpnext/utilities/doctype/organisation/organisation.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# 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 erpnext.utilities.address_and_contact import load_address_and_contact + +class Organisation(Document): + def onload(self): + """Load address and contacts in `__onload`""" + load_address_and_contact(self, "organisation") \ No newline at end of file diff --git a/erpnext/utilities/doctype/organisation/test_organisation.py b/erpnext/utilities/doctype/organisation/test_organisation.py new file mode 100644 index 0000000000..499c63acbb --- /dev/null +++ b/erpnext/utilities/doctype/organisation/test_organisation.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import frappe +import unittest + +# test_records = frappe.get_test_records('Organisation') + +class TestOrganisation(unittest.TestCase): + pass From b166caa9fb0efa4aceab315fd6a945d2fe6922e4 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 13 Jan 2017 17:09:57 +0530 Subject: [PATCH 24/32] Patch fixed --- erpnext/patches/v7_2/update_salary_slips.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v7_2/update_salary_slips.py b/erpnext/patches/v7_2/update_salary_slips.py index 232de2892d..87eae3b414 100644 --- a/erpnext/patches/v7_2/update_salary_slips.py +++ b/erpnext/patches/v7_2/update_salary_slips.py @@ -6,7 +6,7 @@ def execute(): where (month is not null and month != '') and (fiscal_year is not null and fiscal_year != '') and (start_date is null or start_date = '') and - (end_date is null or end_date = '') and docstatus != 2""") + (end_date is null or end_date = '') and docstatus != 2""", as_dict=1) for salary_slip in salary_slips: get_start_end_date = get_month_details(salary_slip.fiscal_year, salary_slip.month) From fd7f3240b40f9b3709c54e3096aabf77db78c62e Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 13 Jan 2017 17:40:51 +0600 Subject: [PATCH 25/32] bumped to version 7.2.10 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 454503fda7..6ac6cca2d5 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '7.2.9' +__version__ = '7.2.10' def get_default_company(user=None): '''Get default company for user''' From e7cb911634a4ce394ec6335f50ba536dc4167ed1 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 13 Jan 2017 17:29:39 +0530 Subject: [PATCH 26/32] Salary Slip Patch Fixed --- erpnext/patches/v7_2/update_salary_slips.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/patches/v7_2/update_salary_slips.py b/erpnext/patches/v7_2/update_salary_slips.py index 87eae3b414..c694fc5f1e 100644 --- a/erpnext/patches/v7_2/update_salary_slips.py +++ b/erpnext/patches/v7_2/update_salary_slips.py @@ -2,6 +2,10 @@ import frappe from erpnext.hr.doctype.process_payroll.process_payroll import get_month_details def execute(): + ss_columns = frappe.db.get_table_columns("Salary Slip") + if "fiscal_year" not in ss_columns or "month" not in ss_columns: + return + salary_slips = frappe.db.sql("""select fiscal_year, month, name from `tabSalary Slip` where (month is not null and month != '') and (fiscal_year is not null and fiscal_year != '') and From 3d26ddd790f6b47b7fcc97ffafa2d3e68ca01c07 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 13 Jan 2017 18:00:45 +0600 Subject: [PATCH 27/32] bumped to version 7.2.11 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 6ac6cca2d5..0083cebb71 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '7.2.10' +__version__ = '7.2.11' def get_default_company(user=None): '''Get default company for user''' From b92087cb2d28790e032cd4bfedf650e26cf60836 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 13 Jan 2017 18:53:11 +0530 Subject: [PATCH 28/32] [cleanup] move contact, address to frappe :boom: --- .../purchase_invoice/purchase_invoice.js | 16 +- erpnext/accounts/party.py | 17 +- .../purchase_common/purchase_common.js | 12 +- .../doctype/purchase_order/purchase_order.js | 12 - erpnext/buying/doctype/supplier/supplier.js | 2 + .../supplier_quotation/supplier_quotation.js | 12 - .../controllers/js/contact_address_common.js | 61 -- erpnext/controllers/queries.py | 27 +- .../crm/doctype/opportunity/opportunity.js | 24 +- erpnext/hooks.py | 9 +- .../maintenance_schedule.js | 38 +- .../maintenance_visit/maintenance_visit.js | 39 +- erpnext/patches/v7_2/contact_address_links.py | 24 + erpnext/patches/v7_2/update_salary_slips.py | 15 +- erpnext/public/js/queries.js | 34 +- erpnext/public/js/utils/party.js | 4 +- erpnext/selling/doctype/customer/customer.js | 2 + .../installation_note/installation_note.js | 6 +- .../selling/doctype/quotation/quotation.js | 1 + .../doctype/sales_order/sales_order.js | 7 - erpnext/selling/sales_common.js | 12 +- .../doctype/sales_partner/sales_partner.js | 21 +- erpnext/shopping_cart/cart.py | 13 +- .../doctype/delivery_note/delivery_note.js | 7 - .../purchase_receipt/purchase_receipt.js | 22 +- .../doctype/warranty_claim/warranty_claim.js | 18 +- erpnext/utilities/address_and_contact.py | 40 +- erpnext/utilities/doctype/address/README.md | 1 - erpnext/utilities/doctype/address/__init__.py | 1 - erpnext/utilities/doctype/address/address.js | 13 - .../utilities/doctype/address/address.json | 880 ---------------- erpnext/utilities/doctype/address/address.py | 181 ---- .../utilities/doctype/address/test_address.py | 21 - .../doctype/address/test_records.json | 15 - .../doctype/address_template/__init__.py | 0 .../address_template/address_template.js | 16 - .../address_template/address_template.json | 147 --- .../address_template/address_template.py | 42 - .../address_template/test_address_template.py | 27 - .../address_template/test_records.json | 13 - erpnext/utilities/doctype/contact/README.md | 1 - erpnext/utilities/doctype/contact/__init__.py | 39 - erpnext/utilities/doctype/contact/contact.js | 65 -- .../utilities/doctype/contact/contact.json | 950 ------------------ erpnext/utilities/doctype/contact/contact.py | 190 ---- .../utilities/doctype/contact/test_contact.py | 7 - .../doctype/contact/test_records.json | 22 - .../doctype/organisation/__init__.py | 0 .../doctype/organisation/organisation.js | 14 - .../doctype/organisation/organisation.json | 199 ---- .../doctype/organisation/organisation.py | 13 - .../doctype/organisation/test_organisation.py | 12 - 52 files changed, 196 insertions(+), 3168 deletions(-) delete mode 100644 erpnext/controllers/js/contact_address_common.js create mode 100644 erpnext/patches/v7_2/contact_address_links.py delete mode 100644 erpnext/utilities/doctype/address/README.md delete mode 100644 erpnext/utilities/doctype/address/__init__.py delete mode 100644 erpnext/utilities/doctype/address/address.js delete mode 100644 erpnext/utilities/doctype/address/address.json delete mode 100644 erpnext/utilities/doctype/address/address.py delete mode 100644 erpnext/utilities/doctype/address/test_address.py delete mode 100644 erpnext/utilities/doctype/address/test_records.json delete mode 100644 erpnext/utilities/doctype/address_template/__init__.py delete mode 100644 erpnext/utilities/doctype/address_template/address_template.js delete mode 100644 erpnext/utilities/doctype/address_template/address_template.json delete mode 100644 erpnext/utilities/doctype/address_template/address_template.py delete mode 100644 erpnext/utilities/doctype/address_template/test_address_template.py delete mode 100644 erpnext/utilities/doctype/address_template/test_records.json delete mode 100644 erpnext/utilities/doctype/contact/README.md delete mode 100644 erpnext/utilities/doctype/contact/__init__.py delete mode 100644 erpnext/utilities/doctype/contact/contact.js delete mode 100644 erpnext/utilities/doctype/contact/contact.json delete mode 100644 erpnext/utilities/doctype/contact/contact.py delete mode 100644 erpnext/utilities/doctype/contact/test_contact.py delete mode 100644 erpnext/utilities/doctype/contact/test_records.json delete mode 100644 erpnext/utilities/doctype/organisation/__init__.py delete mode 100644 erpnext/utilities/doctype/organisation/organisation.js delete mode 100644 erpnext/utilities/doctype/organisation/organisation.json delete mode 100644 erpnext/utilities/doctype/organisation/organisation.py delete mode 100644 erpnext/utilities/doctype/organisation/test_organisation.py diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index b6378f1eb5..c322370f63 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -8,7 +8,7 @@ frappe.provide("erpnext.accounts"); erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ onload: function() { this._super(); - + if(!this.frm.doc.__islocal) { // show credit_to in print format if(!this.frm.doc.supplier && this.frm.doc.credit_to) { @@ -32,7 +32,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ if(doc.update_stock==1 && doc.docstatus==1) { this.show_stock_ledger(); } - + if(!doc.is_return && doc.docstatus==1) { if(doc.outstanding_amount != 0) { this.frm.add_custom_button(__('Payment'), this.make_payment_entry, __("Make")); @@ -218,18 +218,6 @@ cur_frm.fields_dict.cash_bank_account.get_query = function(doc) { } } -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("item_code").get_query = function(doc, cdt, cdn) { return { query: "erpnext.controllers.queries.item_query", diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index c65a845deb..eb705cdc1f 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -8,8 +8,8 @@ import datetime from frappe import _, msgprint, scrub from frappe.defaults import get_user_permissions from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff, add_years -from erpnext.utilities.doctype.address.address import get_address_display -from erpnext.utilities.doctype.contact.contact import get_contact_details +from frappe.geo.doctype.address.address import get_address_display, get_default_address +from frappe.email.doctype.contact.contact import get_contact_details, get_default_contact from erpnext.exceptions import PartyFrozen, InvalidCurrency, PartyDisabled, InvalidAccountCurrency class DuplicatePartyAccountError(frappe.ValidationError): pass @@ -60,21 +60,18 @@ def _get_party_details(party=None, account=None, party_type="Customer", company= def set_address_details(out, party, party_type): billing_address_field = "customer_address" if party_type == "Lead" \ else party_type.lower() + "_address" - out[billing_address_field] = frappe.db.get_value("Address", - {party_type.lower(): party.name, "is_primary_address":1}, "name") + out[billing_address_field] = get_default_address(party_type, party.name) # address display out.address_display = get_address_display(out[billing_address_field]) # shipping address if party_type in ["Customer", "Lead"]: - out.shipping_address_name = frappe.db.get_value("Address", - {party_type.lower(): party.name, "is_shipping_address":1}, "name") + out.shipping_address_name = get_default_address(party_type, party.name, 'is_shipping_address') out.shipping_address = get_address_display(out["shipping_address_name"]) def set_contact_details(out, party, party_type): - out.contact_person = frappe.db.get_value("Contact", - {party_type.lower(): party.name, "is_primary_contact":1}, "name") + out.contact_person = get_default_contact(party_type, party.name) if not out.contact_person: out.update({ @@ -184,7 +181,7 @@ def get_party_account(party_type, party, company): default_account_name = "default_receivable_account" \ if party_type=="Customer" else "default_payable_account" account = frappe.db.get_value("Company", company, default_account_name) - + existing_gle_currency = get_party_gle_currency(party_type, party, company) if existing_gle_currency: if account: @@ -211,7 +208,7 @@ def get_party_gle_currency(party_type, party, company): return frappe.local_cache("party_gle_currency", (party_type, party, company), generator, regenerate_if_none=True) - + def get_party_gle_account(party_type, party, company): def generator(): existing_gle_account = frappe.db.sql("""select account from `tabGL Entry` diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js index 5d74760392..921c3b57ea 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 15356fd471..f2f04fe88c 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 b176e000cd..9808718446 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_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js index fc9cc3bc28..b3bdeb01a7 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/controllers/js/contact_address_common.js b/erpnext/controllers/js/contact_address_common.js deleted file mode 100644 index c51ff468c3..0000000000 --- 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 98390ff2d2..cc3f27724e 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/crm/doctype/opportunity/opportunity.js b/erpnext/crm/doctype/opportunity/opportunity.js index 21fba7b1e7..1ebc0a96a5 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/hooks.py b/erpnext/hooks.py index 25444d9988..d794200fc5 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -127,7 +127,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" } @@ -157,17 +156,11 @@ doc_events = { "User": { "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": "frappe.email.doctype.contact.contact.update_contact" }, ("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" - }, - "Communication":{ - "after_insert":"erpnext.utilities.doctype.contact.match_email_to_contact" - }, # bubble transaction notification on master ('Opportunity', 'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice', diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js index bcf1ae6932..b5d1ad320f 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_visit/maintenance_visit.js b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js index 38c20dadd4..1a3c35cc06 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/v7_2/contact_address_links.py b/erpnext/patches/v7_2/contact_address_links.py new file mode 100644 index 0000000000..490834b2ee --- /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_salary_slips.py b/erpnext/patches/v7_2/update_salary_slips.py index c694fc5f1e..612b900256 100644 --- a/erpnext/patches/v7_2/update_salary_slips.py +++ b/erpnext/patches/v7_2/update_salary_slips.py @@ -2,15 +2,14 @@ import frappe from erpnext.hr.doctype.process_payroll.process_payroll import get_month_details def execute(): - ss_columns = frappe.db.get_table_columns("Salary Slip") - if "fiscal_year" not in ss_columns or "month" not in ss_columns: + frappe.reload_doctype('Salary Slip') + if not frappe.db.has_column('Salary Slip', 'fiscal_year'): return - - salary_slips = frappe.db.sql("""select fiscal_year, month, name from `tabSalary Slip` - where (month is not null and month != '') - and (fiscal_year is not null and fiscal_year != '') and - (start_date is null or start_date = '') and - (end_date is null or end_date = '') and docstatus != 2""", as_dict=1) + + 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) diff --git a/erpnext/public/js/queries.js b/erpnext/public/js/queries.js index 7c4bf0f2c7..8236ce7ae6 100644 --- a/erpnext/public/js/queries.js +++ b/erpnext/public/js/queries.js @@ -36,17 +36,41 @@ $.extend(erpnext.queries, { customer_filter: function(doc) { if(!doc.customer) { - frappe.throw(__("Please specify a") + " " + - __(frappe.meta.get_label(doc.doctype, "customer", doc.name))); + frappe.throw(__("Please set {0}", __(frappe.meta.get_label(doc.doctype, "customer", doc.name)))); } return { filters: { customer: doc.customer } }; }, + contact_query: function(doc) { + if(frappe.contact_link) { + if(!doc[frappe.contact_link.fieldname]) { + frappe.throw(__("Please set {0}", __(frappe.meta.get_label(doc.doctype, + frappe.contact_link.fieldname, doc.name)))); + } + + return { + query: 'frappe.email.doctype.contact.contact.contact_query', + filters: { link_doctype: frappe.contact_link.doctype, link_name: doc[frappe.contact_link.fieldname] } }; + } + }, + + address_query: function(doc) { + if(frappe.contact_link) { + if(!doc[frappe.contact_link.fieldname]) { + frappe.throw(__("Please set {0}", __(frappe.meta.get_label(doc.doctype, + frappe.contact_link.fieldname, doc.name)))); + } + + return { + query: 'frappe.email.doctype.address.address_query', + filters: { link_doctype: frappe.contact_link.doctype, link_name: doc[frappe.contact_link.fieldname] } }; + } + }, + supplier_filter: function(doc) { if(!doc.supplier) { - frappe.throw(__("Please specify a") + " " + - __(frappe.meta.get_label(doc.doctype, "supplier", doc.name))); + frappe.throw(__("Please set {0}", __(frappe.meta.get_label(doc.doctype, "supplier", doc.name)))); } return { filters: { supplier: doc.supplier } }; @@ -74,7 +98,7 @@ $.extend(erpnext.queries, { filters: [ ["Warehouse", "company", "in", ["", cstr(doc.company)]], ["Warehouse", "is_group", "=",0] - + ] } } diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js index a3f3550714..a1d200f6ef 100644 --- a/erpnext/public/js/utils/party.js +++ b/erpnext/public/js/utils/party.js @@ -65,7 +65,7 @@ erpnext.utils.get_address_display = function(frm, address_field, display_field, if(!display_field) display_field = "address_display"; if(frm.doc[address_field]) { frappe.call({ - method: "erpnext.utilities.doctype.address.address.get_address_display", + method: "frappe.geo.doctype.address.address.get_address_display", args: {"address_dict": frm.doc[address_field] }, callback: function(r) { if(r.message) { @@ -151,7 +151,7 @@ erpnext.utils.validate_mandatory = function(frm, label, value, trigger_on) { erpnext.utils.get_shipping_address = function(frm, callback){ frappe.call({ - method: "erpnext.utilities.doctype.address.address.get_shipping_address", + method: "frappe.geo.doctype.address.address.get_shipping_address", args: {company: frm.doc.company}, callback: function(r){ if(r.message){ diff --git a/erpnext/selling/doctype/customer/customer.js b/erpnext/selling/doctype/customer/customer.js index ea88e8b8b5..975604deb4 100644 --- a/erpnext/selling/doctype/customer/customer.js +++ b/erpnext/selling/doctype/customer/customer.js @@ -32,6 +32,8 @@ frappe.ui.form.on("Customer", { erpnext.toggle_naming_series(); } + frappe.contact_link = {doc: frm.doc, fieldname: 'name', doctype: 'Customer'} + frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); if(!frm.doc.__islocal) { diff --git a/erpnext/selling/doctype/installation_note/installation_note.js b/erpnext/selling/doctype/installation_note/installation_note.js index 0334ae764a..d4b2179172 100644 --- a/erpnext/selling/doctype/installation_note/installation_note.js +++ b/erpnext/selling/doctype/installation_note/installation_note.js @@ -32,11 +32,7 @@ erpnext.selling.InstallationNote = frappe.ui.form.Controller.extend({ } }); - this.frm.set_query("contact_person", function() { - return { - filters: {'customer': me.frm.doc.customer } - } - }); + this.frm.set_query('contact_person', erpnext.queries.contact_query); this.frm.set_query("customer", function() { return { diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js index d111c14734..ab1a24a80a 100644 --- a/erpnext/selling/doctype/quotation/quotation.js +++ b/erpnext/selling/doctype/quotation/quotation.js @@ -16,6 +16,7 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({ }, refresh: function(doc, dt, dn) { this._super(doc, dt, dn); + if(doc.docstatus == 1 && doc.status!=='Lost') { cur_frm.add_custom_button(__('Make Sales Order'), cur_frm.cscript['Make Sales Order']); diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index f1eeccc750..8a4a47cf3a 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -203,13 +203,6 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( // for backward compatibility: combine new and previous states $.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm})); -cur_frm.cscript.new_contact = function(){ - tn = frappe.model.make_new_doc_and_get_name('Contact'); - locals['Contact'][tn].is_customer = 1; - if(doc.customer) locals['Contact'][tn].customer = doc.customer; - frappe.set_route('Form', 'Contact', tn); -} - cur_frm.fields_dict['project'].get_query = function(doc, cdt, cdn) { return { query: "erpnext.controllers.queries.get_project_name", diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 7ddf45d529..96ce79acb0 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -26,16 +26,17 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.frm.add_fetch("sales_partner", "commission_rate", "commission_rate"); - $.each([["customer_address", "customer_filter"], - ["shipping_address_name", "customer_filter"], - ["contact_person", "customer_filter"], - ["customer", "customer"], + $.each([["customer", "customer"], ["lead", "lead"]], function(i, opts) { if(me.frm.fields_dict[opts[0]]) me.frm.set_query(opts[0], erpnext.queries[opts[1]]); }); + me.frm.set_query('contact_person', erpnext.queries.contact_query); + me.frm.set_query('customer_address', erpnext.queries.address_query); + me.frm.set_query('shipping_address_name', erpnext.queries.address_query); + if(this.frm.fields_dict.taxes_and_charges) { this.frm.set_query("taxes_and_charges", function() { return { @@ -104,6 +105,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ refresh: function() { this._super(); + + frappe.contact_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'} + this.frm.toggle_display("customer_name", (this.frm.doc.customer_name && this.frm.doc.customer_name!==this.frm.doc.customer)); if(this.frm.fields_dict.packed_items) { diff --git a/erpnext/setup/doctype/sales_partner/sales_partner.js b/erpnext/setup/doctype/sales_partner/sales_partner.js index 143bf442d3..653163075b 100644 --- a/erpnext/setup/doctype/sales_partner/sales_partner.js +++ b/erpnext/setup/doctype/sales_partner/sales_partner.js @@ -1,14 +1,17 @@ // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt -cur_frm.cscript.refresh = function(doc,dt,dn){ +frappe.ui.form.on('Sales Partner', { + refresh: function(frm) { + frappe.contact_link = {doc: frm.doc, fieldname: 'name', doctype: 'Sales Person'} - if(doc.__islocal){ - hide_field(['address_html', 'contact_html']); - erpnext.utils.clear_address_and_contact(cur_frm); + if(doc.__islocal){ + hide_field(['address_html', 'contact_html']); + erpnext.utils.clear_address_and_contact(frm); + } + else{ + unhide_field(['address_html', 'contact_html']); + erpnext.utils.render_address_and_contact(frm); + } } - else{ - unhide_field(['address_html', 'contact_html']); - erpnext.utils.render_address_and_contact(cur_frm); - } -} +}); diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py index d5cde4ad69..d3db4c97dd 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/shopping_cart/cart.py @@ -6,7 +6,7 @@ import frappe from frappe import throw, _ import frappe.defaults from frappe.utils import cint, flt, get_fullname, cstr -from erpnext.utilities.doctype.address.address import get_address_display +from frappe.geo.doctype.address.address import get_address_display from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import get_shopping_cart_settings from frappe.utils.nestedset import get_root_of from erpnext.accounts.utils import get_account_name @@ -383,17 +383,6 @@ def get_address_docs(doctype=None, txt=None, filters=None, limit_start=0, limit_ return address_docs -def set_customer_in_address(doc, method=None): - if doc.flags.linked: - return - - doc.check_if_linked() - - if not doc.flags.linked and (frappe.db.get_value("User", frappe.session.user, "user_type") == "Website User"): - # creates a customer if one does not exist - get_party() - doc.link_address() - @frappe.whitelist() def apply_shipping_rule(shipping_rule): quotation = _get_cart_quotation() diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js index 204e98a012..8f871987f0 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note.js @@ -137,13 +137,6 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend( // for backward compatibility: combine new and previous states $.extend(cur_frm.cscript, new erpnext.stock.DeliveryNoteController({frm: cur_frm})); -cur_frm.cscript.new_contact = function(){ - tn = frappe.model.make_new_doc_and_get_name('Contact'); - locals['Contact'][tn].is_customer = 1; - if(doc.customer) locals['Contact'][tn].customer = doc.customer; - frappe.set_route('Form', 'Contact', tn); -} - cur_frm.cscript.update_status = function(status) { frappe.ui.form.is_saving = true; diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index 457a7c2245..c843d7daaa 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -26,7 +26,7 @@ frappe.ui.form.on("Purchase Receipt", { ] } }); - + } }); @@ -122,26 +122,6 @@ cur_frm.cscript.update_status = function(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.cscript.new_contact = function() { - tn = frappe.model.make_new_doc_and_get_name('Contact'); - locals['Contact'][tn].is_supplier = 1; - if(doc.supplier) - locals['Contact'][tn].supplier = doc.supplier; - frappe.set_route('Form', 'Contact', tn); -} - cur_frm.fields_dict['items'].grid.get_field('project').get_query = function(doc, cdt, cdn) { return { filters: [ diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.js b/erpnext/support/doctype/warranty_claim/warranty_claim.js index 9fed265ed0..abd207b9e4 100644 --- a/erpnext/support/doctype/warranty_claim/warranty_claim.js +++ b/erpnext/support/doctype/warranty_claim/warranty_claim.js @@ -4,6 +4,10 @@ frappe.provide("erpnext.support"); frappe.ui.form.on("Warranty Claim", { + 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); }, @@ -17,6 +21,8 @@ frappe.ui.form.on("Warranty Claim", { erpnext.support.WarrantyClaim = frappe.ui.form.Controller.extend({ refresh: function() { + frappe.contact_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'} + if(!cur_frm.doc.__islocal && (cur_frm.doc.status=='Open' || cur_frm.doc.status == 'Work In Progress')) { cur_frm.add_custom_button(__('Maintenance Visit'), @@ -40,18 +46,6 @@ cur_frm.cscript.onload = function(doc,cdt,cdn){ set_multiple(cdt,cdn,{status:'Open'}); } -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['serial_no'].get_query = function(doc, cdt, cdn) { var cond = []; var filter = [ diff --git a/erpnext/utilities/address_and_contact.py b/erpnext/utilities/address_and_contact.py index 36879d216d..fddb1f7cb5 100644 --- a/erpnext/utilities/address_and_contact.py +++ b/erpnext/utilities/address_and_contact.py @@ -6,17 +6,33 @@ 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 has_permission(doc, ptype, user): links = get_permitted_and_not_permitted_links(doc.doctype) @@ -50,15 +66,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 +82,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) + " )" diff --git a/erpnext/utilities/doctype/address/README.md b/erpnext/utilities/doctype/address/README.md deleted file mode 100644 index a4efda625f..0000000000 --- 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 baffc48825..0000000000 --- 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 1e874c3b5b..0000000000 --- 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 70564acd24..0000000000 --- a/erpnext/utilities/doctype/address/address.json +++ /dev/null @@ -1,880 +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, - "fieldname": "organisation", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Organisation", - "length": 0, - "no_copy": 0, - "options": "Organisation", - "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": "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-12-22 13:49:22.968498", - "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 2c84a9df55..0000000000 --- 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 or self.organisation - - 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", "organisation") - 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", "organisation"]: - 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 36f2535fa1..0000000000 --- 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 a7bde9a814..0000000000 --- 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 e69de29bb2..0000000000 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 c055bcacec..0000000000 --- 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 6ff93d93f8..0000000000 --- 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": "

Default Template

\n

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 64aaa45d26..0000000000 --- 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 }}
{% if address_line2 %}{{ address_line2 }}
{% endif -%}\ -{{ city }}
-{% if state %}{{ state }}
{% endif -%} -{% if pincode %}{{ pincode }}
{% endif -%} -{{ country }}
-{% if phone %}'''+_('Phone')+''': {{ phone }}
{% endif -%} -{% if fax %}'''+_('Fax')+''': {{ fax }}
{% endif -%} -{% if email_id %}'''+_('Email')+''': {{ email_id }}
{% endif -%}''' diff --git a/erpnext/utilities/doctype/address_template/test_address_template.py b/erpnext/utilities/doctype/address_template/test_address_template.py deleted file mode 100644 index 9490005d17..0000000000 --- a/erpnext/utilities/doctype/address_template/test_address_template.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# License: See license.txt - -from __future__ import unicode_literals - -import frappe -test_records = frappe.get_test_records('Address Template') - -import unittest -import frappe - -class TestAddressTemplate(unittest.TestCase): - def test_default_is_unset(self): - a = frappe.get_doc("Address Template", "India") - a.is_default = 1 - a.save() - - b = frappe.get_doc("Address Template", "Brazil") - b.is_default = 1 - b.save() - - self.assertEqual(frappe.db.get_value("Address Template", "India", "is_default"), 0) - - def tearDown(self): - a = frappe.get_doc("Address Template", "India") - a.is_default = 1 - a.save() diff --git a/erpnext/utilities/doctype/address_template/test_records.json b/erpnext/utilities/doctype/address_template/test_records.json deleted file mode 100644 index 412c9e745b..0000000000 --- a/erpnext/utilities/doctype/address_template/test_records.json +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "country": "India", - "is_default": 1, - "template": "{{ address_title }}
\n{{ address_line1 }}
\n{% if address_line2 %}{{ address_line2 }}
{% endif %}\n{{ city }}
\n{% if state %}{{ state }}
{% endif %}\n{% if pincode %} PIN / ZIP: {{ pincode }}
{% endif %}\n{{ country }}
\n{% if phone %}Phone: {{ phone }}
{% endif %}\n{% if fax %}Fax: {{ fax }}
{% endif %}\n{% if email_id %}Email: {{ email_id }}
{% endif %}\n" - }, - { - "country": "Brazil", - "is_default": 0, - "template": "{{ address_title }}
\n{{ address_line1 }}
\n{% if address_line2 %}{{ address_line2 }}
{% endif %}\n{{ city }}
\n{% if state %}{{ state }}
{% endif %}\n{% if pincode %} PIN / ZIP: {{ pincode }}
{% endif %}\n{{ country }}
\n{% if phone %}Phone: {{ phone }}
{% endif %}\n{% if fax %}Fax: {{ fax }}
{% endif %}\n{% if email_id %}Email: {{ email_id }}
{% endif %}\n" - } -] - diff --git a/erpnext/utilities/doctype/contact/README.md b/erpnext/utilities/doctype/contact/README.md deleted file mode 100644 index 484522c1ba..0000000000 --- a/erpnext/utilities/doctype/contact/README.md +++ /dev/null @@ -1 +0,0 @@ -Contact representing a Customer or Supplier. \ No newline at end of file diff --git a/erpnext/utilities/doctype/contact/__init__.py b/erpnext/utilities/doctype/contact/__init__.py deleted file mode 100644 index e4075fda8e..0000000000 --- a/erpnext/utilities/doctype/contact/__init__.py +++ /dev/null @@ -1,39 +0,0 @@ -from __future__ import unicode_literals -import frappe - -def match_email_to_contact(doc,method=None): - if doc.communication_type == "Communication": - origin_contact = frappe.db.sql( - "select name, email_id, supplier, supplier_name, customer, customer_name, user, organisation from `tabContact` where email_id <>''", - as_dict=1) - for comm in origin_contact: - if comm.email_id: - if (doc.sender and doc.sent_or_received == "Received" and doc.sender.find(comm.email_id) > -1) or ( - doc.recipients and doc.sent_or_received == "Sent" and doc.recipients.find( - comm.email_id) > -1): - if sum(1 for x in [comm.supplier, comm.customer, comm.user, comm.organisation] if x) > 1: - doc.db_set("timeline_doctype", "Contact") - doc.db_set("timeline_name", comm.name) - doc.db_set("timeline_label", doc.name) - - elif comm.supplier: - doc.db_set("timeline_doctype", "Supplier") - doc.db_set("timeline_name", comm.supplier) - doc.db_set("timeline_label", comm.supplier_name) - - elif comm.customer: - doc.db_set("timeline_doctype", "Customer") - doc.db_set("timeline_name", comm.customer) - doc.db_set("timeline_label", comm.customer_name) - elif comm.user: - doc.db_set("timeline_doctype", "User") - doc.db_set("timeline_name", comm.user) - doc.db_set("timeline_label", comm.user) - elif comm.organisation: - doc.db_set("timeline_doctype", "Organisation") - doc.db_set("timeline_name", comm.organisation) - doc.db_set("timeline_label", comm.organisation) - else: - doc.db_set("timeline_doctype", None) - doc.db_set("timeline_name", None) - doc.db_set("timeline_label", None) diff --git a/erpnext/utilities/doctype/contact/contact.js b/erpnext/utilities/doctype/contact/contact.js deleted file mode 100644 index db25e99dea..0000000000 --- a/erpnext/utilities/doctype/contact/contact.js +++ /dev/null @@ -1,65 +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' %}; - -cur_frm.email_field = "email_id"; -frappe.ui.form.on("Contact", { - onload:function(frm){ - if(frappe.route_titles["update_contact"]) - { - frappe.confirm("change email address from "+cur_frm.doc.email_id+ " to "+frappe.route_titles["update_contact"]["email_id"] - ,function(){ - cur_frm.doc.email_id = frappe.route_titles["update_contact"]["email_id"]; - cur_frm.refresh(); - cur_frm.dirty(); - delete frappe.route_titles["update_contact"]; - },function(){ - delete frappe.route_titles["update_contact"]; - }) - - } - }, - refresh: function(frm) { - if(!frm.doc.user && !frm.is_new() && frm.perm[0].write) { - frm.add_custom_button(__("Invite as User"), function() { - frappe.call({ - method: "erpnext.utilities.doctype.contact.contact.invite_user", - args: { - contact: frm.doc.name - }, - callback: function(r) { - frm.set_value("user", r.message); - } - }); - }); - } - }, - validate: function(frm) { - // clear linked customer / supplier / sales partner on saving... - $.each(["Customer", "Supplier", "Sales Partner"], 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); - }); - var fieldlist = ["supplier","customer","user","organisation"] - if(frappe.route_titles["create_contact"]==1&&!($.map(fieldlist,function(v){return frm.doc[v]?true:false}).indexOf(true)!=-1)){ - $.each(fieldlist,function(i,v){ - cur_frm.set_df_property(v,"reqd",1); - }) - - } else { - $.each(fieldlist,function(i,v){ - cur_frm.set_df_property(v,"reqd",0); - }) - } - }, - after_save:function(frm){ - if (frappe.route_titles["create_contact"]) - { - delete frappe.route_titles["create_contact"] - frappe.set_route("email_inbox"); - frappe.pages['email_inbox'].Inbox.run() - } - } -}); \ No newline at end of file diff --git a/erpnext/utilities/doctype/contact/contact.json b/erpnext/utilities/doctype/contact/contact.json deleted file mode 100644 index 21046b7f57..0000000000 --- a/erpnext/utilities/doctype/contact/contact.json +++ /dev/null @@ -1,950 +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, - "engine": "InnoDB", - "fields": [ - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contact_section", - "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-user", - "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": "first_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": "First Name", - "length": 0, - "no_copy": 0, - "oldfieldname": "first_name", - "oldfieldtype": "Data", - "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": 1, - "collapsible": 0, - "columns": 0, - "fieldname": "last_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": "Last Name", - "length": 0, - "no_copy": 0, - "oldfieldname": "last_name", - "oldfieldtype": "Data", - "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, - "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, - "oldfieldname": "email_id", - "oldfieldtype": "Data", - "options": "Email", - "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": "cb00", - "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 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "Passive", - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "Passive\nOpen\nReplied", - "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, - "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, - "oldfieldname": "contact_no", - "oldfieldtype": "Data", - "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": "image", - "fieldtype": "Attach Image", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Image", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "contact_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": "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, - "fieldname": "user", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "User Id", - "length": 0, - "no_copy": 0, - "options": "User", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_on_submit": 0, - "bold": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "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, - "oldfieldname": "customer", - "oldfieldtype": "Link", - "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": "", - "fieldname": "customer_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": "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, - "fieldname": "column_break1", - "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, - "oldfieldtype": "Column Break", - "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": 1, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "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": "", - "fieldname": "supplier_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": "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": "", - "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, - "fieldname": "organisation", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Organisation", - "length": 0, - "no_copy": 0, - "options": "Organisation", - "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, - "default": "0", - "depends_on": "eval:(doc.customer || doc.supplier || doc.sales_partner)", - "fieldname": "is_primary_contact", - "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 Primary Contact", - "length": 0, - "no_copy": 0, - "oldfieldname": "is_primary_contact", - "oldfieldtype": "Select", - "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": "more_info", - "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": "More Information", - "length": 0, - "no_copy": 0, - "options": "fa fa-file-text", - "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": "mobile_no", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Mobile No", - "length": 0, - "no_copy": 0, - "oldfieldname": "mobile_no", - "oldfieldtype": "Data", - "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": "Enter department to which this Contact belongs", - "fieldname": "department", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Department", - "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, - "description": "Enter designation of this Contact", - "fieldname": "designation", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Designation", - "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": "unsubscribed", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Unsubscribed", - "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-user", - "idx": 1, - "image_field": "image", - "image_view": 0, - "in_create": 0, - "in_dialog": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2016-12-22 13:46:02.655141", - "modified_by": "Administrator", - "module": "Utilities", - "name": "Contact", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "is_custom": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - }, - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "is_custom": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Sales Master Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - }, - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "is_custom": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Purchase Master Manager", - "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": "Sales Manager", - "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 Manager", - "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 Manager", - "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 Manager", - "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": "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 - }, - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "is_custom": 0, - "match": "", - "permlevel": 1, - "print": 0, - "read": 1, - "report": 1, - "role": "All", - "set_user_permissions": 0, - "share": 0, - "submit": 0, - "write": 0 - } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "sort_order": "ASC", - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/utilities/doctype/contact/contact.py b/erpnext/utilities/doctype/contact/contact.py deleted file mode 100644 index 03eb94cab1..0000000000 --- a/erpnext/utilities/doctype/contact/contact.py +++ /dev/null @@ -1,190 +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.utils import cstr, has_gravatar -from frappe import _ - -from erpnext.controllers.status_updater import StatusUpdater - -class Contact(StatusUpdater): - def autoname(self): - # concat first and last name - self.name = " ".join(filter(None, - [cstr(self.get(f)).strip() for f in ["first_name", "last_name"]])) - - # concat party name if reqd - for fieldname in ("customer", "supplier", "sales_partner", "organisation"): - if self.get(fieldname): - self.name = self.name + "-" + cstr(self.get(fieldname)).strip() - break - - def validate(self): - self.set_status() - self.validate_primary_contact() - self.set_user() - if self.email_id: - self.image = has_gravatar(self.email_id) - self.contact_update_communication_ref() - - def set_user(self): - if not self.user and self.email_id: - self.user = frappe.db.get_value("User", {"email": self.email_id}) - - def validate_primary_contact(self): - if self.is_primary_contact == 1: - if self.customer: - frappe.db.sql("update tabContact set is_primary_contact=0 where customer = %s", - (self.customer)) - elif self.supplier: - frappe.db.sql("update tabContact set is_primary_contact=0 where supplier = %s", - (self.supplier)) - elif self.sales_partner: - frappe.db.sql("""update tabContact set is_primary_contact=0 - where sales_partner = %s""", (self.sales_partner)) - else: - if self.customer: - if not frappe.db.sql("select name from tabContact \ - where is_primary_contact=1 and customer = %s", (self.customer)): - self.is_primary_contact = 1 - elif self.supplier: - if not frappe.db.sql("select name from tabContact \ - where is_primary_contact=1 and supplier = %s", (self.supplier)): - self.is_primary_contact = 1 - elif self.sales_partner: - if not frappe.db.sql("select name from tabContact \ - where is_primary_contact=1 and sales_partner = %s", - self.sales_partner): - self.is_primary_contact = 1 - - def on_trash(self): - frappe.db.sql("""update `tabIssue` set contact='' where contact=%s""", - self.name) - - def contact_update_communication_ref(self): - origin_communication = frappe.db.sql("select name, sender,recipients,sent_or_received from `tabCommunication`", - as_dict=1) - - if self.email_id: - self.email_id = self.email_id.lower() - comm = frappe._dict({"email_id": self.email_id, - "name": self.name, - "supplier": self.supplier, - "supplier_name": self.supplier_name, - "customer": self.customer, - "customer_name": self.customer_name, - "user": self.user, - "organisation": self.organisation - }) - for communication in origin_communication: - sender = communication.sender - recipients = communication.recipients - if comm.email_id: - if (sender and communication.sent_or_received == "Received" and sender.find( - comm.email_id) > -1) or ( - recipients and communication.sent_or_received == "Sent" and recipients.find( - comm.email_id) > -1): - if sum(1 for x in [comm.supplier, comm.customer, comm.user, comm.organisation] if x) > 1: - frappe.db.sql("""update `tabCommunication` - set timeline_doctype = %(timeline_doctype)s, - timeline_name = %(timeline_name)s, - timeline_label = %(timeline_label)s - where name = %(name)s""", { - "timeline_doctype": "Contact", - "timeline_name": comm.name, - "timeline_label": self.name, - "name": communication.name - }) - - elif comm.supplier: - frappe.db.sql("""update `tabCommunication` - set timeline_doctype = %(timeline_doctype)s, - timeline_name = %(timeline_name)s, - timeline_label = %(timeline_label)s - where name = %(name)s""", { - "timeline_doctype": "Supplier", - "timeline_name": comm.supplier, - "timeline_label": comm.supplier_name, - "name": communication.name - }) - - elif comm.customer: - - frappe.db.sql("""update `tabCommunication` - set timeline_doctype = %(timeline_doctype)s, - timeline_name = %(timeline_name)s, - timeline_label = %(timeline_label)s - where name = %(name)s""", { - "timeline_doctype": "Customer", - "timeline_name": comm.customer, - "timeline_label": comm.customer_name, - "name": communication.name - }) - elif comm.user: - frappe.db.sql("""update `tabCommunication` - set timeline_doctype = %(timeline_doctype)s, - timeline_name = %(timeline_name)s, - timeline_label = %(timeline_label)s - where name = %(name)s""", { - "timeline_doctype": "User", - "timeline_name": comm.user, - "timeline_label": comm.user, - "name": communication.name - }) - elif comm.organisation: - frappe.db.sql("""update `tabCommunication` - set timeline_doctype = %(timeline_doctype)s, - timeline_name = %(timeline_name)s, - timeline_label = %(timeline_label)s - where name = %(name)s""", { - "timeline_doctype": "Organisation", - "timeline_name": comm.organisation, - "timeline_label": comm.organisation, - "name": communication.name - }) - -@frappe.whitelist() -def invite_user(contact): - contact = frappe.get_doc("Contact", contact) - - if not contact.email_id: - frappe.throw(_("Please set Email Address")) - - if contact.has_permission("write"): - user = frappe.get_doc({ - "doctype": "User", - "first_name": contact.first_name, - "last_name": contact.last_name, - "email": contact.email_id, - "user_type": "Website User", - "send_welcome_email": 1 - }).insert(ignore_permissions = True) - - return user.name - -@frappe.whitelist() -def get_contact_details(contact): - contact = frappe.get_doc("Contact", contact) - out = { - "contact_person": contact.get("name"), - "contact_display": " ".join(filter(None, - [contact.get("first_name"), contact.get("last_name")])), - "contact_email": contact.get("email_id"), - "contact_mobile": contact.get("mobile_no"), - "contact_phone": contact.get("phone"), - "contact_designation": contact.get("designation"), - "contact_department": contact.get("department") - } - return out - -def update_contact(doc, method): - '''Update contact when user is updated, if contact is found. Called via hooks''' - contact_name = frappe.db.get_value("Contact", {"email_id": doc.name}) - if contact_name: - contact = frappe.get_doc("Contact", contact_name) - for key in ("first_name", "last_name", "phone"): - if doc.get(key): - contact.set(key, doc.get(key)) - contact.flags.ignore_mandatory = True - contact.save(ignore_permissions=True) diff --git a/erpnext/utilities/doctype/contact/test_contact.py b/erpnext/utilities/doctype/contact/test_contact.py deleted file mode 100644 index 964c8d767c..0000000000 --- a/erpnext/utilities/doctype/contact/test_contact.py +++ /dev/null @@ -1,7 +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('Contact') \ No newline at end of file diff --git a/erpnext/utilities/doctype/contact/test_records.json b/erpnext/utilities/doctype/contact/test_records.json deleted file mode 100644 index 133a7b6883..0000000000 --- a/erpnext/utilities/doctype/contact/test_records.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "customer": "_Test Customer", - "customer_name": "_Test Customer", - "doctype": "Contact", - "email_id": "test_contact_customer@example.com", - "first_name": "_Test Contact For _Test Customer", - "is_primary_contact": 1, - "phone": "+91 0000000000", - "status": "Open" - }, - { - "doctype": "Contact", - "email_id": "test_contact_supplier@example.com", - "first_name": "_Test Contact For _Test Supplier", - "is_primary_contact": 1, - "phone": "+91 0000000000", - "status": "Open", - "supplier": "_Test Supplier", - "supplier_name": "_Test Supplier" - } -] \ No newline at end of file diff --git a/erpnext/utilities/doctype/organisation/__init__.py b/erpnext/utilities/doctype/organisation/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/utilities/doctype/organisation/organisation.js b/erpnext/utilities/doctype/organisation/organisation.js deleted file mode 100644 index 2d3bb31bea..0000000000 --- a/erpnext/utilities/doctype/organisation/organisation.js +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors -// For license information, please see license.txt - -frappe.ui.form.on('Organisation', { - refresh: function(frm) { - frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal); - - if(!frm.doc.__islocal) { - erpnext.utils.render_address_and_contact(frm); - } else { - erpnext.utils.clear_address_and_contact(frm); - } - } -}); diff --git a/erpnext/utilities/doctype/organisation/organisation.json b/erpnext/utilities/doctype/organisation/organisation.json deleted file mode 100644 index 9cbcc90cf9..0000000000 --- a/erpnext/utilities/doctype/organisation/organisation.json +++ /dev/null @@ -1,199 +0,0 @@ -{ - "allow_copy": 0, - "allow_import": 1, - "allow_rename": 1, - "autoname": "field:organisation_name", - "beta": 0, - "creation": "2016-08-22 11:08:27.151412", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 0, - "fields": [ - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "organisation_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": "Name", - "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.__islocal", - "fieldname": "address_contacts", - "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": "Address and Contact", - "length": 0, - "no_copy": 0, - "options": "icon-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, - "fieldname": "address_html", - "fieldtype": "HTML", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Address HTML", - "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, - "fieldname": "column_break1", - "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": "contact_html", - "fieldtype": "HTML", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Contact HTML", - "length": 0, - "no_copy": 0, - "oldfieldtype": "HTML", - "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, - "idx": 0, - "image_view": 0, - "in_create": 0, - "in_dialog": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2016-12-23 08:33:29.997375", - "modified_by": "Administrator", - "module": "Utilities", - "name": "Organisation", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 1, - "is_custom": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "Email User", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 0, - "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/organisation/organisation.py b/erpnext/utilities/doctype/organisation/organisation.py deleted file mode 100644 index d04f226ea1..0000000000 --- a/erpnext/utilities/doctype/organisation/organisation.py +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- -# 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 erpnext.utilities.address_and_contact import load_address_and_contact - -class Organisation(Document): - def onload(self): - """Load address and contacts in `__onload`""" - load_address_and_contact(self, "organisation") \ No newline at end of file diff --git a/erpnext/utilities/doctype/organisation/test_organisation.py b/erpnext/utilities/doctype/organisation/test_organisation.py deleted file mode 100644 index 499c63acbb..0000000000 --- a/erpnext/utilities/doctype/organisation/test_organisation.py +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors -# See license.txt -from __future__ import unicode_literals - -import frappe -import unittest - -# test_records = frappe.get_test_records('Organisation') - -class TestOrganisation(unittest.TestCase): - pass From c0bfb0ba56b1611413707120365e2ed49a168045 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 13 Jan 2017 23:05:56 +0530 Subject: [PATCH 29/32] [fix] contact and address for demo --- erpnext/demo/data/address.json | 403 +++++++++++++++------------------ erpnext/demo/data/contact.json | 295 +++++++++++------------- 2 files changed, 322 insertions(+), 376 deletions(-) diff --git a/erpnext/demo/data/address.json b/erpnext/demo/data/address.json index be4d5ecc41..de0e3c863c 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 130845b258..9911a7f015 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 From 95439db53f81a3087934e93c1649f4f30ac27c7a Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Sat, 14 Jan 2017 00:25:22 +0530 Subject: [PATCH 30/32] [fixes] address and contact --- erpnext/accounts/doctype/tax_rule/tax_rule.py | 35 +++++++----- erpnext/buying/doctype/supplier/supplier.py | 36 ++---------- erpnext/demo/data/address.json | 54 +++++++++--------- erpnext/demo/data/contact.json | 20 +++---- erpnext/demo/setup/setup_data.py | 2 +- erpnext/hooks.py | 9 ++- erpnext/selling/doctype/customer/customer.py | 55 ++++--------------- erpnext/setup/setup_wizard/setup_wizard.py | 11 ++-- erpnext/shopping_cart/utils.py | 13 ++--- erpnext/utilities/address_and_contact.py | 24 ++++++++ 10 files changed, 113 insertions(+), 146 deletions(-) diff --git a/erpnext/accounts/doctype/tax_rule/tax_rule.py b/erpnext/accounts/doctype/tax_rule/tax_rule.py index 7ec833e959..606d067335 100644 --- a/erpnext/accounts/doctype/tax_rule/tax_rule.py +++ b/erpnext/accounts/doctype/tax_rule/tax_rule.py @@ -7,6 +7,7 @@ import frappe from frappe import _ from frappe.model.document import Document from frappe.utils import cstr, cint +from frappe.geo.doctype.address.address import get_default_address class IncorrectCustomerGroup(frappe.ValidationError): pass class IncorrectSupplierType(frappe.ValidationError): pass @@ -96,27 +97,31 @@ class TaxRule(Document): @frappe.whitelist() def get_party_details(party, party_type, args=None): out = {} + billing_address, shipping_address = None, None if args: - billing_filters= {"name": args.get("billing_address")} - shipping_filters= {"name": args.get("shipping_address")} + if args.get('billing_address'): + billing_address = frappe.get_doc('Address', args.get('billing_address')) + if args.get('shipping_address'): + shipping_address = frappe.get_doc('Address', args.get('shipping_address')) else: - billing_filters= {party_type: party, "is_primary_address": 1} - shipping_filters= {party_type:party, "is_shipping_address": 1} - - billing_address= frappe.get_all("Address", fields=["city", "county", "state", "country"], filters= billing_filters) - shipping_address= frappe.get_all("Address", fields=["city", "county", "state", "country"], filters= shipping_filters) + billing_address_name = get_default_address(party_type, party) + shipping_address_name = get_default_address(party_type, party, 'is_shipping_address') + if billing_address_name: + billing_address = frappe.get_doc('Address', billing_address_name) + if shipping_address_name: + shipping_address = frappe.get_doc('Address', shipping_address_name) if billing_address: - out["billing_city"]= billing_address[0].city - out["billing_county"]= billing_address[0].county - out["billing_state"]= billing_address[0].state - out["billing_country"]= billing_address[0].country + out["billing_city"]= billing_address.city + out["billing_county"]= billing_address.county + out["billing_state"]= billing_address.state + out["billing_country"]= billing_address.country if shipping_address: - out["shipping_city"]= shipping_address[0].city - out["shipping_county"]= shipping_address[0].county - out["shipping_state"]= shipping_address[0].state - out["shipping_country"]= shipping_address[0].country + out["shipping_city"]= shipping_address.city + out["shipping_county"]= shipping_address.county + out["shipping_state"]= shipping_address.state + out["shipping_country"]= shipping_address.country return out diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py index 3677ee296b..9eaaad1e61 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/demo/data/address.json b/erpnext/demo/data/address.json index de0e3c863c..7618c2cf33 100644 --- a/erpnext/demo/data/address.json +++ b/erpnext/demo/data/address.json @@ -5,7 +5,7 @@ "city": "Larnaka", "country": "Cyprus", "links": [{"link_doctype": "Customer", "link_name": "Adaptas"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "R Patr\u00e3o Caramelho 116", @@ -13,7 +13,7 @@ "city": "Fajozes", "country": "Portugal", "links": [{"link_doctype": "Customer", "link_name": "Asian Fusion"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "30 Fulford Road", @@ -21,7 +21,7 @@ "city": "PENTRE-PIOD", "country": "United Kingdom", "links": [{"link_doctype": "Customer", "link_name": "Asian Junction"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "Schoenebergerstrasse 13", @@ -29,7 +29,7 @@ "city": "Raschau", "country": "Germany", "links": [{"link_doctype": "Customer", "link_name": "Big D Supermarkets"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "Hoheluftchaussee 43", @@ -37,7 +37,7 @@ "city": "Kieritzsch", "country": "Germany", "links": [{"link_doctype": "Customer", "link_name": "Buttrey Food & Drug"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "R Cimo Vila 6", @@ -45,7 +45,7 @@ "city": "Rebordosa", "country": "Portugal", "links": [{"link_doctype": "Customer", "link_name": "Chi-Chis"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "R 5 Outubro 9", @@ -53,7 +53,7 @@ "city": "Quinta Nova S\u00e3o Domingos", "country": "Portugal", "links": [{"link_doctype": "Customer", "link_name": "Choices"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "Avenida Macambira 953", @@ -61,7 +61,7 @@ "city": "Goi\u00e2nia", "country": "Brazil", "links": [{"link_doctype": "Customer", "link_name": "Consumers and Consumers Express"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "2342 Goyeau Ave", @@ -69,7 +69,7 @@ "city": "Windsor", "country": "Canada", "links": [{"link_doctype": "Customer", "link_name": "Crafts Canada"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "Laukaantie 82", @@ -77,7 +77,7 @@ "city": "KOKKOLA", "country": "Finland", "links": [{"link_doctype": "Customer", "link_name": "Endicott Shoes"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "9 Brown Street", @@ -85,7 +85,7 @@ "city": "PETERSHAM", "country": "Australia", "links": [{"link_doctype": "Customer", "link_name": "Fayva"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "Via Donnalbina 41", @@ -93,7 +93,7 @@ "city": "Cala Gonone", "country": "Italy", "links": [{"link_doctype": "Customer", "link_name": "Intelacard"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "Liljerum Grenadj\u00e4rtorpet 69", @@ -101,7 +101,7 @@ "city": "TOMTEBODA", "country": "Sweden", "links": [{"link_doctype": "Customer", "link_name": "Landskip Yard Care"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "72 Bishopgate Street", @@ -109,7 +109,7 @@ "city": "SEAHAM", "country": "United Kingdom", "links": [{"link_doctype": "Customer", "link_name": "Life Plan Counselling"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "\u03a3\u03ba\u03b1\u03c6\u03af\u03b4\u03b9\u03b1 105", @@ -117,7 +117,7 @@ "city": "\u03a0\u0391\u03a1\u0395\u039a\u039a\u039b\u0397\u03a3\u0399\u0391", "country": "Cyprus", "links": [{"link_doctype": "Customer", "link_name": "Mr Fables"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "Mellemvej 7", @@ -125,7 +125,7 @@ "city": "Aabybro", "country": "Denmark", "links": [{"link_doctype": "Customer", "link_name": "Nelson Brothers"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "Plougg\u00e5rdsvej 98", @@ -133,7 +133,7 @@ "city": "Karby", "country": "Denmark", "links": [{"link_doctype": "Customer", "link_name": "Netobill"}], - "phone": "23566775757", + "phone": "23566775757" }, { "address_line1": "176 Michalakopoulou Street", @@ -141,7 +141,7 @@ "city": "Agio Georgoudi", "country": "Cyprus", "phone": "23566775757", - "links": [{"link_doctype": "Supplier", "link_name": "Helios Air"}], + "links": [{"link_doctype": "Supplier", "link_name": "Helios Air"}] }, { "address_line1": "Fibichova 1102", @@ -149,7 +149,7 @@ "city": "Kokor\u00edn", "country": "Czech Republic", "phone": "23566775757", - "links": [{"link_doctype": "Supplier", "link_name": "Ks Merchandise"}], + "links": [{"link_doctype": "Supplier", "link_name": "Ks Merchandise"}] }, { "address_line1": "Zahradn\u00ed 888", @@ -157,7 +157,7 @@ "city": "Cecht\u00edn", "country": "Czech Republic", "phone": "23566775757", - "links": [{"link_doctype": "Supplier", "link_name": "HomeBase"}], + "links": [{"link_doctype": "Supplier", "link_name": "HomeBase"}] }, { "address_line1": "ul. Grochowska 94", @@ -165,7 +165,7 @@ "city": "Warszawa", "country": "Poland", "phone": "23566775757", - "links": [{"link_doctype": "Supplier", "link_name": "Scott Ties"}], + "links": [{"link_doctype": "Supplier", "link_name": "Scott Ties"}] }, { "address_line1": "Norra Esplanaden 87", @@ -173,7 +173,7 @@ "city": "HELSINKI", "country": "Finland", "phone": "23566775757", - "links": [{"link_doctype": "Supplier", "link_name": "Reliable Investments"}], + "links": [{"link_doctype": "Supplier", "link_name": "Reliable Investments"}] }, { "address_line1": "2038 Fallon Drive", @@ -181,7 +181,7 @@ "city": "Dresden", "country": "Canada", "phone": "23566775757", - "links": [{"link_doctype": "Supplier", "link_name": "Nan Duskin"}], + "links": [{"link_doctype": "Supplier", "link_name": "Nan Duskin"}] }, { "address_line1": "77 cours Franklin Roosevelt", @@ -189,7 +189,7 @@ "city": "MARSEILLE", "country": "France", "phone": "23566775757", - "links": [{"link_doctype": "Supplier", "link_name": "Rainbow Records"}], + "links": [{"link_doctype": "Supplier", "link_name": "Rainbow Records"}] }, { "address_line1": "ul. Tuwima Juliana 85", @@ -197,7 +197,7 @@ "city": "\u0141\u00f3d\u017a", "country": "Poland", "phone": "23566775757", - "links": [{"link_doctype": "Supplier", "link_name": "New World Realty"}], + "links": [{"link_doctype": "Supplier", "link_name": "New World Realty"}] }, { "address_line1": "Gl. Sygehusvej 41", @@ -205,7 +205,7 @@ "city": "Narsaq", "country": "Greenland", "phone": "23566775757", - "links": [{"link_doctype": "Supplier", "link_name": "Asiatic Solutions"}], + "links": [{"link_doctype": "Supplier", "link_name": "Asiatic Solutions"}] }, { "address_line1": "Gosposka ulica 50", @@ -213,6 +213,6 @@ "city": "Nova Gorica", "country": "Slovenia", "phone": "23566775757", - "links": [{"link_doctype": "Supplier", "link_name": "Eagle Hardware"}], + "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 9911a7f015..113b561ce5 100644 --- a/erpnext/demo/data/contact.json +++ b/erpnext/demo/data/contact.json @@ -105,60 +105,60 @@ "links": [{"link_doctype": "Supplier", "link_name": "Helios Air"}], "email_id": "TewoldeAbaalom@example.com", "first_name": "Tewolde", - "last_name": "Abaalom", + "last_name": "Abaalom" }, { "links": [{"link_doctype": "Supplier", "link_name": "Ks Merchandise"}], "email_id": "LeilaFernandesRodrigues@example.com", "first_name": "Leila", - "last_name": "Rodrigues", + "last_name": "Rodrigues" }, { "links": [{"link_doctype": "Supplier", "link_name": "HomeBase"}], "email_id": "DmitryBulgakov@example.com", "first_name": "Dmitry", - "last_name": "Bulgakov", + "last_name": "Bulgakov" }, { "links": [{"link_doctype": "Supplier", "link_name": "Scott Ties"}], "email_id": "HaiducWhitfoot@example.com", "first_name": "Haiduc", - "last_name": "Whitfoot", + "last_name": "Whitfoot" }, { "links": [{"link_doctype": "Supplier", "link_name": "Reliable Investments"}], "email_id": "SesseljaPetursdottir@example.com", "first_name": "Sesselja", - "last_name": "P\u00e9tursd\u00f3ttir", + "last_name": "P\u00e9tursd\u00f3ttir" }, { "links": [{"link_doctype": "Supplier", "link_name": "Nan Duskin"}], "email_id": "HajdarPignar@example.com", "first_name": "Hajdar", - "last_name": "Pignar", + "last_name": "Pignar" }, { "links": [{"link_doctype": "Supplier", "link_name": "Rainbow Records"}], "email_id": "GustavaLorenzo@example.com", "first_name": "Gustava", - "last_name": "Lorenzo", + "last_name": "Lorenzo" }, { "links": [{"link_doctype": "Supplier", "link_name": "New World Realty"}], "email_id": "BethanyWood@example.com", "first_name": "Bethany", - "last_name": "Wood", + "last_name": "Wood" }, { "links": [{"link_doctype": "Supplier", "link_name": "Asiatic Solutions"}], "email_id": "GlorianaBrownlock@example.com", "first_name": "Gloriana", - "last_name": "Brownlock", + "last_name": "Brownlock" }, { "links": [{"link_doctype": "Supplier", "link_name": "Eagle Hardware"}], "email_id": "JensonFraser@gustr.com", "first_name": "Jenson", - "last_name": "Fraser", + "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 902bbabd1e..21ac6484d9 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/hooks.py b/erpnext/hooks.py index d794200fc5..acea675a77 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -114,10 +114,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'} ] @@ -154,9 +152,10 @@ 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": "frappe.email.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" diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 48e2982c35..d8011af20a 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -9,7 +9,7 @@ import frappe.defaults from frappe.utils import flt, cint, cstr from frappe.desk.reportview import build_match_conditions from erpnext.utilities.transaction_base import TransactionBase -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.accounts.party import validate_party_accounts, get_timeline_data # keep this from erpnext.accounts.party_status import get_party_status from erpnext import get_default_currency @@ -79,9 +79,6 @@ class Customer(TransactionBase): if self.flags.old_lead != self.lead_name: self.update_lead_status() - self.update_address() - self.update_contact() - if self.flags.is_new_doc: self.create_lead_address_contact() @@ -95,30 +92,26 @@ class Customer(TransactionBase): for d in frappe.get_all(doctype, {'lead': self.lead_name}): frappe.db.set_value(doctype, d.name, 'customer', self.name, update_modified=False) - def update_address(self): - frappe.db.sql("""update `tabAddress` set customer_name=%s, modified=NOW() - where customer=%s""", (self.customer_name, self.name)) - - def update_contact(self): - frappe.db.sql("""update `tabContact` set customer_name=%s, modified=NOW() - where customer=%s""", (self.customer_name, self.name)) - def create_lead_address_contact(self): if self.lead_name: - if not frappe.db.get_value("Address", {"lead": self.lead_name, "customer": self.name}): - frappe.db.sql("""update `tabAddress` set customer=%s, customer_name=%s where lead=%s""", - (self.name, self.customer_name, self.lead_name)) + # assign lead address to customer (if already not set) + address_name = frappe.get_value('Dynamic Link', dict(parenttype='Address', link_doctype='Lead', link_name=self.name)) + if address_name: + address = frappe.get_doc('Address', address_name) + if not address.has_link('Customer', self.name): + address.append('links', dict(link_doctype='Customer', link_name=self.name)) + address.save() lead = frappe.db.get_value("Lead", self.lead_name, ["lead_name", "email_id", "phone", "mobile_no"], as_dict=True) + # create contact from lead c = frappe.new_doc('Contact') c.first_name = lead.lead_name c.email_id = lead.email_id c.phone = lead.phone c.mobile_no = lead.mobile_no - c.customer = self.name - c.customer_name = self.customer_name c.is_primary_contact = 1 + c.append('links', dict(link_doctype='Customer', link_name=self.name)) c.flags.ignore_permissions = self.flags.ignore_permissions c.autoname() if not frappe.db.exists("Contact", c.name): @@ -137,40 +130,14 @@ class Customer(TransactionBase): if flt(self.credit_limit) < outstanding_amt: frappe.throw(_("""New credit limit is less than current outstanding amount for the customer. Credit limit has to be atleast {0}""").format(outstanding_amt)) - def delete_customer_address(self): - addresses = frappe.db.sql("""select name, lead from `tabAddress` - where customer=%s""", (self.name,)) - - for name, lead in addresses: - if lead: - frappe.db.sql("""update `tabAddress` set customer=null, customer_name=null - where name=%s""", name) - else: - frappe.db.sql("""delete from `tabAddress` where name=%s""", name) - - def delete_customer_contact(self): - for contact in frappe.db.sql_list("""select name from `tabContact` - where customer=%s""", self.name): - frappe.delete_doc("Contact", contact) - def on_trash(self): - self.delete_customer_address() - self.delete_customer_contact() + delete_contact_and_address('Customer', self.name) if self.lead_name: frappe.db.sql("update `tabLead` set status='Interested' where name=%s",self.lead_name) def after_rename(self, olddn, newdn, merge=False): - set_field = '' if frappe.defaults.get_global_default('cust_master_name') == 'Customer Name': frappe.db.set(self, "customer_name", newdn) - self.update_contact() - set_field = ", customer_name=%(newdn)s" - self.update_customer_address(newdn, set_field) - - def update_customer_address(self, newdn, set_field): - frappe.db.sql("""update `tabAddress` set address_title=%(newdn)s - {set_field} where customer=%(newdn)s"""\ - .format(set_field=set_field), ({"newdn": newdn})) def get_customer_list(doctype, txt, searchfield, start, page_len, filters): diff --git a/erpnext/setup/setup_wizard/setup_wizard.py b/erpnext/setup/setup_wizard/setup_wizard.py index 395ea51d3c..664c08989e 100644 --- a/erpnext/setup/setup_wizard/setup_wizard.py +++ b/erpnext/setup/setup_wizard/setup_wizard.py @@ -407,7 +407,7 @@ def create_customers(args): if args.get("customer_contact_" + str(i)): create_contact(args.get("customer_contact_" + str(i)), - "customer", doc.name) + "Customer", doc.name) except frappe.NameError: pass @@ -425,7 +425,7 @@ def create_suppliers(args): if args.get("supplier_contact_" + str(i)): create_contact(args.get("supplier_contact_" + str(i)), - "supplier", doc.name) + "Supplier", doc.name) except frappe.NameError: pass @@ -433,12 +433,13 @@ def create_contact(contact, party_type, party): """Create contact based on given contact name""" contact = contact.strip().split(" ") - frappe.get_doc({ + contact = frappe.get_doc({ "doctype":"Contact", - party_type: party, "first_name":contact[0], "last_name": len(contact) > 1 and contact[1] or "" - }).insert() + }) + contact.append('links', dict(link_doctype=party_type, link_name=party)) + contact.insert() def create_letter_head(args): if args.get("attach_letterhead"): diff --git a/erpnext/shopping_cart/utils.py b/erpnext/shopping_cart/utils.py index 50ce5cf42f..3241234af5 100644 --- a/erpnext/shopping_cart/utils.py +++ b/erpnext/shopping_cart/utils.py @@ -31,12 +31,11 @@ def update_website_context(context): def check_customer_or_supplier(): if frappe.session.user: - contacts = frappe.get_all("Contact", fields=["customer", "supplier", "email_id"], - filters={"email_id": frappe.session.user}) + contact_name = frappe.get_value("Contact", {"email_id": frappe.session.user}) + if contact_name: + contact = frappe.get_doc('Contact', contact_name) + for link in contact.links: + if link.link_doctype in ('Customer', 'Supplier'): + return link.link_doctype, link.link_name - customer = [d.customer for d in contacts if d.customer] or None - supplier = [d.supplier for d in contacts if d.supplier] or None - - if customer: return 'Customer', customer - if supplier : return 'Supplier', supplier return 'Customer', None \ No newline at end of file diff --git a/erpnext/utilities/address_and_contact.py b/erpnext/utilities/address_and_contact.py index fddb1f7cb5..eaa71f9b1f 100644 --- a/erpnext/utilities/address_and_contact.py +++ b/erpnext/utilities/address_and_contact.py @@ -34,6 +34,19 @@ def load_address_and_contact(doc, key): 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) if not links.get("not_permitted_links"): @@ -105,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() From 820abd3ba4829ac50dc12f9c86a5239745552ae2 Mon Sep 17 00:00:00 2001 From: ci2014 Date: Mon, 16 Jan 2017 07:27:34 +0100 Subject: [PATCH 31/32] Fix missing comma (#7495) Fixed missing comma after method set_contact_link --- erpnext/crm/doctype/opportunity/opportunity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.js b/erpnext/crm/doctype/opportunity/opportunity.js index 1ebc0a96a5..d7d412a1e1 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.js +++ b/erpnext/crm/doctype/opportunity/opportunity.js @@ -56,7 +56,7 @@ frappe.ui.form.on("Opportunity", { } 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({ From 4ad121e1a43f7ac1049118414f1f77300002ffd3 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 16 Jan 2017 12:19:07 +0530 Subject: [PATCH 32/32] [minor] fixes for Contact --- erpnext/shopping_cart/cart.py | 20 +++++++++++--------- erpnext/shopping_cart/test_shopping_cart.py | 6 +++--- erpnext/support/doctype/issue/issue.py | 8 ++++---- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py index d3db4c97dd..e52ef8105d 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/shopping_cart/cart.py @@ -182,8 +182,7 @@ def _get_cart_quotation(party=None): (party.doctype.lower()): party.name }) - qdoc.contact_person = frappe.db.get_value("Contact", {"email_id": frappe.session.user, - "customer": party.name}) + qdoc.contact_person = frappe.db.get_value("Contact", {"email_id": frappe.session.user}) qdoc.contact_email = frappe.session.user qdoc.flags.ignore_permissions = True @@ -198,8 +197,7 @@ def update_party(fullname, company_name=None, mobile_no=None, phone=None): party.customer_name = company_name or fullname party.customer_type == "Company" if company_name else "Individual" - contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user, - "customer": party.name}) + contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user}) contact = frappe.get_doc("Contact", contact_name) contact.first_name = fullname contact.last_name = None @@ -291,10 +289,14 @@ def get_party(user=None): if not user: user = frappe.session.user - party = frappe.db.get_value("Contact", {"email_id": user}, ["customer", "supplier"], as_dict=1) - if party: - party_doctype = 'Customer' if party.customer else 'Supplier' - party = party.customer or party.supplier + contact_name = frappe.db.get_value("Contact", {"email_id": user}) + party = None + + if contact_name: + contact = frappe.get_doc('Contact', contact_name) + if contact.links: + party_doctype = contact.links[0].link_doctype + party = contact.links[0].link_name cart_settings = frappe.get_doc("Shopping Cart Settings") @@ -331,10 +333,10 @@ def get_party(user=None): contact = frappe.new_doc("Contact") contact.update({ - "customer": customer.name, "first_name": fullname, "email_id": user }) + contact.append('links', dict(link_doctype='Customer', link_name=customer.name)) contact.flags.ignore_mandatory = True contact.insert(ignore_permissions=True) diff --git a/erpnext/shopping_cart/test_shopping_cart.py b/erpnext/shopping_cart/test_shopping_cart.py index 528223151c..698d46726c 100644 --- a/erpnext/shopping_cart/test_shopping_cart.py +++ b/erpnext/shopping_cart/test_shopping_cart.py @@ -25,8 +25,8 @@ class TestShoppingCart(unittest.TestCase): # test if lead is created and quotation with new lead is fetched quotation = _get_cart_quotation() self.assertEquals(quotation.quotation_to, "Customer") - self.assertEquals(frappe.db.get_value("Contact", {"customer": quotation.customer}, "email_id"), - "test_cart_user@example.com") + self.assertEquals(frappe.db.get_value("Contact", dict(contact_person="test_cart_user@example.com")), + quotation.contact_name) self.assertEquals(quotation.lead, None) self.assertEquals(quotation.contact_email, frappe.session.user) @@ -101,7 +101,7 @@ class TestShoppingCart(unittest.TestCase): quotation = self.create_quotation() from erpnext.accounts.party import set_taxes - + tax_rule_master = set_taxes(quotation.customer, "Customer", \ quotation.transaction_date, quotation.company, None, None, \ quotation.customer_address, quotation.shipping_address_name, 1) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 36d0876bbd..f2d8bd53e1 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -33,11 +33,11 @@ class Issue(Document): if not self.lead: self.lead = frappe.db.get_value("Lead", {"email_id": email_id}) if not self.contact: - values = frappe.db.get_value("Contact", - {"email_id": email_id}, ("name", "customer")) + self.contact = frappe.db.get_value("Contact", {"email_id": email_id}) - if values: - self.contact, self.customer = values + if self.contact: + contact = frappe.get_doc('Contact', self.contact) + self.customer = contact.get_link_for('Customer') if not self.company: self.company = frappe.db.get_value("Lead", self.lead, "company") or \