Merge branch 'develop' into project-link-for-all-accounts
diff --git a/erpnext/accounts/doctype/item_tax_template/item_tax_template.js b/erpnext/accounts/doctype/item_tax_template/item_tax_template.js
index 42abdb8..e921a0d 100644
--- a/erpnext/accounts/doctype/item_tax_template/item_tax_template.js
+++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.js
@@ -6,6 +6,18 @@
frm.set_query("tax_type", "taxes", function(doc) {
return {
filters: [
+ ['Account', 'company', '=', frm.doc.company],
+ ['Account', 'is_group', '=', 0],
+ ['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
+ ]
+ }
+ });
+ },
+ company: function (frm) {
+ frm.set_query("tax_type", "taxes", function(doc) {
+ return {
+ filters: [
+ ['Account', 'company', '=', frm.doc.company],
['Account', 'is_group', '=', 0],
['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation']]
]
diff --git a/erpnext/accounts/doctype/item_tax_template/item_tax_template.json b/erpnext/accounts/doctype/item_tax_template/item_tax_template.json
index f713cfc..856c371 100644
--- a/erpnext/accounts/doctype/item_tax_template/item_tax_template.json
+++ b/erpnext/accounts/doctype/item_tax_template/item_tax_template.json
@@ -1,168 +1,85 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:title",
- "beta": 0,
- "creation": "2018-11-22 22:45:00.370913",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:title",
+ "creation": "2018-11-22 22:45:00.370913",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "title",
+ "company",
+ "taxes"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "title",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 1,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Title",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "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,
- "translatable": 0,
+ "fieldname": "title",
+ "fieldtype": "Data",
+ "in_filter": 1,
+ "in_list_view": 1,
+ "label": "Title",
+ "no_copy": 1,
+ "reqd": 1,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "taxes",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Tax Rates",
- "length": 0,
- "no_copy": 0,
- "options": "Item Tax Template Detail",
- "permlevel": 0,
- "precision": "",
- "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,
- "translatable": 0,
- "unique": 0
+ "fieldname": "taxes",
+ "fieldtype": "Table",
+ "label": "Tax Rates",
+ "options": "Item Tax Template Detail",
+ "reqd": 1
+ },
+ {
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "options": "Company",
+ "reqd": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-12-21 23:51:16.328340",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Item Tax Template",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "modified": "2020-06-18 20:27:42.615842",
+ "modified_by": "ahmad@havenir.com",
+ "module": "Accounts",
+ "name": "Item Tax Template",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User",
+ "share": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "search_fields": "",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 7360b39..cfdae93 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -840,6 +840,7 @@
return [{"account": a, "balance": get_balance_on(a)} for a in accounts]
+@frappe.whitelist()
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
diff --git a/erpnext/accounts/doctype/payment_order/payment_order.py b/erpnext/accounts/doctype/payment_order/payment_order.py
index 7ecdc41..4702e58 100644
--- a/erpnext/accounts/doctype/payment_order/payment_order.py
+++ b/erpnext/accounts/doctype/payment_order/payment_order.py
@@ -26,6 +26,7 @@
for d in self.references:
frappe.db.set_value(self.payment_order_type, d.get(frappe.scrub(self.payment_order_type)), ref_field, status)
+@frappe.whitelist()
def get_mop_query(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql(""" select mode_of_payment from `tabPayment Order Reference`
where parent = %(parent)s and mode_of_payment like %(txt)s
@@ -36,6 +37,7 @@
'txt': "%%%s%%" % txt
})
+@frappe.whitelist()
def get_supplier_query(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql(""" select supplier from `tabPayment Order Reference`
where parent = %(parent)s and supplier like %(txt)s and
@@ -86,4 +88,4 @@
je.flags.ignore_mandatory = True
je.save()
- frappe.msgprint(_("{0} {1} created").format(je.doctype, je.name))
\ No newline at end of file
+ frappe.msgprint(_("{0} {1} created").format(je.doctype, je.name))
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index 3080496..8eaad7a 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -101,10 +101,10 @@
Having
amount > 0
""".format(
- doc=voucher_type,
- dr_or_cr=dr_or_cr,
- reconciled_dr_or_cr=reconciled_dr_or_cr,
- party_type_field=frappe.scrub(self.party_type)),
+ doc=voucher_type,
+ dr_or_cr=dr_or_cr,
+ reconciled_dr_or_cr=reconciled_dr_or_cr,
+ party_type_field=frappe.scrub(self.party_type)),
{
'party': self.party,
'party_type': self.party_type,
@@ -170,7 +170,7 @@
reconcile_against_document(lst)
if dr_or_cr_notes:
- reconcile_dr_cr_note(dr_or_cr_notes)
+ reconcile_dr_cr_note(dr_or_cr_notes, self.company)
msgprint(_("Successfully Reconciled"))
self.get_unreconciled_entries()
@@ -261,7 +261,7 @@
return cond
-def reconcile_dr_cr_note(dr_cr_notes):
+def reconcile_dr_cr_note(dr_cr_notes, company):
for d in dr_cr_notes:
voucher_type = ('Credit Note'
if d.voucher_type == 'Sales Invoice' else 'Debit Note')
@@ -273,6 +273,7 @@
"doctype": "Journal Entry",
"voucher_type": voucher_type,
"posting_date": today(),
+ "company": company,
"accounts": [
{
'account': d.account,
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py
index 4f17e9f..f186967 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py
@@ -115,6 +115,7 @@
def get_series():
return frappe.get_meta("Sales Invoice").get_field("naming_series").options or ""
+@frappe.whitelist()
def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):
user = frappe.session['user']
company = filters.get('company') or frappe.defaults.get_user_default('company')
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index ead300e..d4d83af 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -432,6 +432,7 @@
return doc
+@frappe.whitelist()
def get_item_uoms(doctype, txt, searchfield, start, page_len, filters):
items = [filters.get('value')]
if filters.get('apply_on') != 'Item Code':
@@ -442,4 +443,4 @@
return frappe.get_all('UOM Conversion Detail',
filters = {'parent': ('in', items), 'uom': ("like", "{0}%".format(txt))},
- fields = ["distinct uom"], as_list=1)
\ No newline at end of file
+ fields = ["distinct uom"], as_list=1)
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index bfe35ab..a245d63 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -140,10 +140,8 @@
gle = frappe.new_doc("GL Entry")
gle.update(args)
gle.flags.ignore_permissions = 1
- gle.validate()
- gle.db_insert()
+ gle.insert()
gle.run_method("on_update_with_args", adv_adj, update_outstanding)
- gle.flags.ignore_validate = True
gle.submit()
# check against budget
diff --git a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
index 69f9907..7df090b 100644
--- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
+++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
@@ -21,7 +21,7 @@
if payment_doctype == "Payment Entry" and payment_entry.unallocated_amount > transaction.unallocated_amount:
frappe.throw(_("The unallocated amount of Payment Entry {0} \
is greater than the Bank Transaction's unallocated amount").format(payment_name))
-
+
if transaction.unallocated_amount == 0:
frappe.throw(_("This bank transaction is already fully reconciled"))
@@ -289,6 +289,7 @@
else:
return []
+@frappe.whitelist()
def payment_entry_query(doctype, txt, searchfield, start, page_len, filters):
account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
if not account:
@@ -317,6 +318,7 @@
}
)
+@frappe.whitelist()
def journal_entry_query(doctype, txt, searchfield, start, page_len, filters):
account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
@@ -352,6 +354,7 @@
}
)
+@frappe.whitelist()
def sales_invoices_query(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""
SELECT
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index db91b66..b764eff 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -388,7 +388,7 @@
from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details
args = {
party_type.lower(): party,
- "company": company
+ "company": company
}
if tax_category:
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 9ae5a87..0bd03a8 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -35,11 +35,9 @@
if not self.booked_fixed_asset and self.validate_make_gl_entry():
self.make_gl_entries()
- def before_cancel(self):
- self.cancel_auto_gen_movement()
-
def on_cancel(self):
self.validate_cancellation()
+ self.cancel_movement_entries()
self.delete_depreciation_entries()
self.set_status()
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
@@ -134,19 +132,6 @@
Please do not book expense of multiple assets against one single Asset.")
.format(frappe.bold("equal"), "<br>"), title=_("Invalid Gross Purchase Amount"))
- def cancel_auto_gen_movement(self):
- movements = frappe.db.sql(
- """SELECT asm.name, asm.docstatus
- FROM `tabAsset Movement` asm, `tabAsset Movement Item` asm_item
- WHERE asm_item.parent=asm.name and asm_item.asset=%s and asm.docstatus=1""", self.name, as_dict=1)
- if len(movements) > 1:
- frappe.throw(_('Asset has multiple Asset Movement Entries which has to be \
- cancelled manually to cancel this asset.'))
- if movements:
- movement = frappe.get_doc('Asset Movement', movements[0].get('name'))
- movement.flags.ignore_validate = True
- movement.cancel()
-
def make_asset_movement(self):
reference_doctype = 'Purchase Receipt' if self.purchase_receipt else 'Purchase Invoice'
reference_docname = self.purchase_receipt or self.purchase_invoice
@@ -413,6 +398,16 @@
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
frappe.throw(_("Asset cannot be cancelled, as it is already {0}").format(self.status))
+ def cancel_movement_entries(self):
+ movements = frappe.db.sql(
+ """SELECT asm.name, asm.docstatus
+ FROM `tabAsset Movement` asm, `tabAsset Movement Item` asm_item
+ WHERE asm_item.parent=asm.name and asm_item.asset=%s and asm.docstatus=1""", self.name, as_dict=1)
+
+ for movement in movements:
+ movement = frappe.get_doc('Asset Movement', movement.get('name'))
+ movement.cancel()
+
def delete_depreciation_entries(self):
for d in self.get("schedules"):
if d.journal_entry:
diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py
index 3da355e..b2de250 100644
--- a/erpnext/assets/doctype/asset_movement/asset_movement.py
+++ b/erpnext/assets/doctype/asset_movement/asset_movement.py
@@ -87,33 +87,9 @@
def on_submit(self):
self.set_latest_location_in_asset()
-
- def before_cancel(self):
- self.validate_last_movement()
def on_cancel(self):
self.set_latest_location_in_asset()
-
- def validate_last_movement(self):
- for d in self.assets:
- auto_gen_movement_entry = frappe.db.sql(
- """
- SELECT asm.name
- FROM `tabAsset Movement Item` asm_item, `tabAsset Movement` asm
- WHERE
- asm.docstatus=1 and
- asm_item.parent=asm.name and
- asm_item.asset=%s and
- asm.company=%s and
- asm_item.source_location is NULL and
- asm.purpose=%s
- ORDER BY
- asm.transaction_date asc
- """, (d.asset, self.company, 'Receipt'), as_dict=1)
-
- if auto_gen_movement_entry and auto_gen_movement_entry[0].get('name') == self.name:
- frappe.throw(_('{0} will be cancelled automatically on asset cancellation as it was \
- auto generated for Asset {1}').format(self.name, d.asset))
def set_latest_location_in_asset(self):
current_location, current_employee = '', ''
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
index 56af4d9..4b85230 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
@@ -206,6 +206,7 @@
})
return list_context
+@frappe.whitelist()
def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select `tabContact`.name from `tabContact`, `tabDynamic Link`
where `tabDynamic Link`.link_doctype = 'Supplier' and (`tabDynamic Link`.link_name=%(name)s
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index f6a8d27..31e3498 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -10,7 +10,8 @@
from erpnext.stock.get_item_details import _get_item_tax_template
from frappe.utils import unique
- # searches for active employees
+# searches for active employees
+@frappe.whitelist()
def employee_query(doctype, txt, searchfield, start, page_len, filters):
conditions = []
fields = get_fields("Employee", ["name", "employee_name"])
@@ -40,6 +41,7 @@
# searches for leads which are not converted
+@frappe.whitelist()
def lead_query(doctype, txt, searchfield, start, page_len, filters):
fields = get_fields("Lead", ["name", "lead_name", "company_name"])
@@ -69,6 +71,7 @@
# searches for customer
+@frappe.whitelist()
def customer_query(doctype, txt, searchfield, start, page_len, filters):
conditions = []
cust_master_name = frappe.defaults.get_user_default("cust_master_name")
@@ -106,6 +109,7 @@
# searches for supplier
+@frappe.whitelist()
def supplier_query(doctype, txt, searchfield, start, page_len, filters):
supp_master_name = frappe.defaults.get_user_default("supp_master_name")
if supp_master_name == "Supplier Name":
@@ -137,6 +141,7 @@
})
+@frappe.whitelist()
def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
company_currency = erpnext.get_company_currency(filters.get('company'))
@@ -162,6 +167,7 @@
return tax_accounts
+@frappe.whitelist()
def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
conditions = []
@@ -224,6 +230,7 @@
}, as_dict=as_dict)
+@frappe.whitelist()
def bom(doctype, txt, searchfield, start, page_len, filters):
conditions = []
fields = get_fields("BOM", ["name", "item"])
@@ -250,6 +257,7 @@
})
+@frappe.whitelist()
def get_project_name(doctype, txt, searchfield, start, page_len, filters):
cond = ''
if filters.get('customer'):
@@ -276,6 +284,7 @@
})
+@frappe.whitelist()
def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters, as_dict):
fields = get_fields("Delivery Note", ["name", "customer", "posting_date"])
@@ -305,6 +314,7 @@
}, {"txt": ("%%%s%%" % txt)}, as_dict=as_dict)
+@frappe.whitelist()
def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
cond = ""
if filters.get("posting_date"):
@@ -362,6 +372,7 @@
limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args)
+@frappe.whitelist()
def get_account_list(doctype, txt, searchfield, start, page_len, filters):
filter_list = []
@@ -385,6 +396,7 @@
limit_start=start, limit_page_length=page_len, as_list=True)
+@frappe.whitelist()
def get_blanket_orders(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select distinct bo.name, bo.blanket_order_type, bo.to_date
from `tabBlanket Order` bo, `tabBlanket Order Item` boi
@@ -570,7 +582,8 @@
args = {
'item_code': filters.get('item_code'),
'posting_date': filters.get('valid_from'),
- 'tax_category': filters.get('tax_category')
+ 'tax_category': filters.get('tax_category'),
+ 'company': filters.get('company')
}
taxes = _get_item_tax_template(args, taxes, for_validate=True)
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 4e568e2..a9eb996 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -53,7 +53,8 @@
'tax_category': self.doc.get('tax_category'),
'posting_date': self.doc.get('posting_date'),
'bill_date': self.doc.get('bill_date'),
- 'transaction_date': self.doc.get('transaction_date')
+ 'transaction_date': self.doc.get('transaction_date'),
+ 'company': self.doc.get('company')
}
item_group = item_doc.item_group
diff --git a/erpnext/crm/dashboard_fixtures.py b/erpnext/crm/dashboard_fixtures.py
index 0535cbb..901c058 100644
--- a/erpnext/crm/dashboard_fixtures.py
+++ b/erpnext/crm/dashboard_fixtures.py
@@ -172,7 +172,9 @@
"doctype": "Number Card",
"document_type": "Lead",
"name": "New Lead (Last 1 Month)",
- "filters_json": json.dumps([["Lead","creation","Previous","1 month",False]]),
+ "filters_json": json.dumps([
+ ["Lead", "creation", "Timespan", "last month"]
+ ]),
"function": "Count",
"is_public": 1,
"label": _("New Lead (Last 1 Month)"),
@@ -183,7 +185,9 @@
"doctype": "Number Card",
"document_type": "Opportunity",
"name": "New Opportunity (Last 1 Month)",
- "filters_json": json.dumps([["Opportunity","creation","Previous","1 month",False]]),
+ "filters_json": json.dumps([
+ ["Opportunity", "creation", "Timespan", "last month"]
+ ]),
"function": "Count",
"is_public": 1,
"label": _("New Opportunity (Last 1 Month)"),
@@ -194,7 +198,10 @@
"doctype": "Number Card",
"document_type": "Opportunity",
"name": "Won Opportunity (Last 1 Month)",
- "filters_json": json.dumps([["Opportunity","creation","Previous","1 month",False]]),
+ "filters_json": json.dumps([
+ ["Opportunity", "status", "=", "Converted",False],
+ ["Opportunity", "creation", "Timespan", "last month"]
+ ]),
"function": "Count",
"is_public": 1,
"label": _("Won Opportunity (Last 1 Month)"),
diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py
index ec7d14d..315d298 100644
--- a/erpnext/crm/doctype/lead/lead.py
+++ b/erpnext/crm/doctype/lead/lead.py
@@ -114,10 +114,12 @@
def set_lead_name(self):
if not self.lead_name:
# Check for leads being created through data import
- if not self.company_name and not self.flags.ignore_mandatory:
+ if not self.company_name and not self.email_id and not self.flags.ignore_mandatory:
frappe.throw(_("A Lead requires either a person's name or an organization's name"))
-
- self.lead_name = self.company_name
+ elif self.company_name:
+ self.lead_name = self.company_name
+ else:
+ self.lead_name = self.email_id.split("@")[0]
def set_title(self):
if self.organization_lead:
diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js
index 8f8dafd..221300b 100644
--- a/erpnext/hr/doctype/expense_claim/expense_claim.js
+++ b/erpnext/hr/doctype/expense_claim/expense_claim.js
@@ -113,6 +113,14 @@
cur_frm.cscript.calculate_total(doc,cdt,cdn);
};
+cur_frm.fields_dict['cost_center'].get_query = function(doc) {
+ return {
+ filters: {
+ "company": doc.company
+ }
+ }
+};
+
erpnext.expense_claim = {
set_title: function(frm) {
if (!frm.doc.task) {
diff --git a/erpnext/hr/doctype/leave_application/leave_application.js b/erpnext/hr/doctype/leave_application/leave_application.js
index fb1f2c0..4001a45 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.js
+++ b/erpnext/hr/doctype/leave_application/leave_application.js
@@ -40,6 +40,8 @@
validate: function(frm) {
if (frm.doc.from_date == frm.doc.to_date && frm.doc.half_day == 1){
frm.doc.half_day_date = frm.doc.from_date;
+ }else if (frm.doc.half_day == 0){
+ frm.doc.half_day_date = "";
}
frm.toggle_reqd("half_day_date", frm.doc.half_day == 1);
},
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 0423824..3f25f58 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -293,6 +293,8 @@
def set_half_day_date(self):
if self.from_date == self.to_date and self.half_day == 1:
self.half_day_date = self.from_date
+ elif self.half_day == 0:
+ self.half_day_date = None
def notify_employee(self):
employee = frappe.get_doc("Employee", self.employee)
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 7d31a1c..256c957 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -910,6 +910,7 @@
return out
+@frappe.whitelist()
def item_query(doctype, txt, searchfield, start, page_len, filters):
meta = frappe.get_meta("Item", cached=True)
searchfields = meta.get_search_fields()
@@ -989,4 +990,4 @@
},
}, target_doc, postprocess)
- return doc
\ No newline at end of file
+ return doc
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index e2233a3..f962a11 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -631,6 +631,7 @@
bom.set_bom_material_details()
return bom
+@frappe.whitelist()
def get_bom_operations(doctype, txt, searchfield, start, page_len, filters):
if txt:
filters['operation'] = ('like', '%%%s%%' % txt)
diff --git a/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py b/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py
index c5627e0..e3e440e 100644
--- a/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py
+++ b/erpnext/manufacturing/report/bom_variance_report/bom_variance_report.py
@@ -19,7 +19,7 @@
"options": "Work Order",
"width": 120
}]
-
+
if not filters.get('bom_no'):
columns.extend([
{
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index f3c5c6f..566b979 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -708,3 +708,4 @@
erpnext.patches.v13_0.move_payroll_setting_separately_from_hr_settings #22-06-2020
erpnext.patches.v13_0.check_is_income_tax_component #22-06-2020
erpnext.patches.v12_0.add_taxjar_integration_field
+erpnext.patches.v12_0.update_item_tax_template_company
diff --git a/erpnext/patches/v12_0/update_item_tax_template_company.py b/erpnext/patches/v12_0/update_item_tax_template_company.py
new file mode 100644
index 0000000..f749699
--- /dev/null
+++ b/erpnext/patches/v12_0/update_item_tax_template_company.py
@@ -0,0 +1,13 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ frappe.reload_doc('accounts', 'doctype', 'item_tax_template')
+
+ item_tax_template_list = frappe.get_list('Item Tax Template')
+ for template in item_tax_template_list:
+ doc = frappe.get_doc('Item Tax Template', template.name)
+ for tax in doc.taxes:
+ doc.company = frappe.get_value('Account', tax.tax_type, 'company')
+ break
+ doc.save()
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
index e166a70..d7d00e6 100644
--- a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
+++ b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.py
@@ -222,7 +222,7 @@
return benefit_amount
-
+@frappe.whitelist()
def get_earning_components(doctype, txt, searchfield, start, page_len, filters):
if len(filters) < 2:
return {}
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.js b/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
index 1ae3553..8d35a7b 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.js
@@ -30,6 +30,7 @@
).toggleClass('btn-primary', !(frm.doc.employees || []).length);
}
if ((frm.doc.employees || []).length) {
+ frm.page.clear_primary_action();
frm.page.set_primary_action(__('Create Salary Slips'), () => {
frm.save('Submit').then(()=>{
frm.page.clear_primary_action();
@@ -49,13 +50,14 @@
return frappe.call({
doc: frm.doc,
method: 'fill_employee_details',
- callback: function(r) {
- if (r.docs[0].employees){
- frm.save();
- frm.refresh();
- if(r.docs[0].validate_attendance){
- render_employee_attendance(frm, r.message);
- }
+ }).then(r => {
+ if (r.docs && r.docs[0].employees){
+ frm.employees = r.docs[0].employees;
+ frm.dirty();
+ frm.save();
+ frm.refresh();
+ if(r.docs[0].validate_attendance){
+ render_employee_attendance(frm, r.message);
}
}
})
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index e6bb708..ad9b6d8 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -539,6 +539,7 @@
if not_submitted_ss:
frappe.msgprint(_("Could not submit some Salary Slips"))
+@frappe.whitelist()
def get_payroll_entries_for_jv(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""
select name from `tabPayroll Entry`
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index afdb5b7..32ea05b 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -238,6 +238,7 @@
"row_template": "templates/includes/projects/project_row.html"
}
+@frappe.whitelist()
def get_users_for_project(doctype, txt, searchfield, start, page_len, filters):
conditions = []
return frappe.db.sql("""select name, concat_ws(' ', first_name, middle_name, last_name)
diff --git a/erpnext/projects/doctype/task/task.json b/erpnext/projects/doctype/task/task.json
index f4b3d3e..4db1f19 100644
--- a/erpnext/projects/doctype/task/task.json
+++ b/erpnext/projects/doctype/task/task.json
@@ -183,7 +183,8 @@
{
"fieldname": "progress",
"fieldtype": "Percent",
- "label": "% Progress"
+ "label": "% Progress",
+ "no_copy": 1
},
{
"default": "0",
@@ -356,6 +357,7 @@
"fieldname": "completed_by",
"fieldtype": "Link",
"label": "Completed By",
+ "no_copy": 1,
"options": "User"
}
],
@@ -364,7 +366,7 @@
"is_tree": 1,
"links": [],
"max_attachments": 5,
- "modified": "2020-03-18 18:08:44.153211",
+ "modified": "2020-07-03 12:36:04.960457",
"modified_by": "Administrator",
"module": "Projects",
"name": "Task",
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 1cb2c50..845cdba 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -188,6 +188,7 @@
return child_tasks
+@frappe.whitelist()
def get_project(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
return frappe.db.sql(""" select name from `tabProject`
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 905f6fb..3c56a63 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1835,7 +1835,8 @@
if (doc.tax_category)
filters['tax_category'] = doc.tax_category;
-
+ if (doc.company)
+ filters['company'] = doc.company;
return {
query: "erpnext.controllers.queries.get_tax_template",
filters: filters
diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js
index 99c1b8a..0653267 100644
--- a/erpnext/public/js/utils/party.js
+++ b/erpnext/public/js/utils/party.js
@@ -4,7 +4,7 @@
frappe.provide("erpnext.utils");
erpnext.utils.get_party_details = function(frm, method, args, callback) {
- if(!method) {
+ if (!method) {
method = "erpnext.accounts.party.get_party_details";
}
@@ -22,12 +22,12 @@
}
}
- if(!args) {
- if((frm.doctype != "Purchase Order" && frm.doc.customer)
+ if (!args) {
+ if ((frm.doctype != "Purchase Order" && frm.doc.customer)
|| (frm.doc.party_name && in_list(['Quotation', 'Opportunity'], frm.doc.doctype))) {
let party_type = "Customer";
- if(frm.doc.quotation_to && frm.doc.quotation_to === "Lead") {
+ if (frm.doc.quotation_to && frm.doc.quotation_to === "Lead") {
party_type = "Lead";
}
@@ -36,7 +36,7 @@
party_type: party_type,
price_list: frm.doc.selling_price_list
};
- } else if(frm.doc.supplier) {
+ } else if (frm.doc.supplier) {
args = {
party: frm.doc.supplier,
party_type: "Supplier",
@@ -78,13 +78,17 @@
args.posting_date = frm.doc.posting_date || frm.doc.transaction_date;
}
}
- if(!args || !args.party) return;
+ if (!args || !args.party) return;
- if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
- if(!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date",
+ if (frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
+ if (!erpnext.utils.validate_mandatory(frm, "Posting / Transaction Date",
args.posting_date, args.party_type=="Customer" ? "customer": "supplier")) return;
}
+ if (!erpnext.utils.validate_mandatory(frm, "Company", frm.doc.company, args.party_type=="Customer" ? "customer": "supplier")) {
+ return;
+ }
+
args.currency = frm.doc.currency;
args.company = frm.doc.company;
args.doctype = frm.doc.doctype;
@@ -92,14 +96,14 @@
method: method,
args: args,
callback: function(r) {
- if(r.message) {
+ if (r.message) {
frm.supplier_tds = r.message.supplier_tds;
frm.updating_party_details = true;
frappe.run_serially([
() => frm.set_value(r.message),
() => {
frm.updating_party_details = false;
- if(callback) callback();
+ if (callback) callback();
frm.refresh();
erpnext.utils.add_item(frm);
}
@@ -110,9 +114,9 @@
}
erpnext.utils.add_item = function(frm) {
- if(frm.is_new()) {
+ if (frm.is_new()) {
var prev_route = frappe.get_prev_route();
- if(prev_route[1]==='Item' && !(frm.doc.items && frm.doc.items.length)) {
+ if (prev_route[1]==='Item' && !(frm.doc.items && frm.doc.items.length)) {
// add row
var item = frm.add_child('items');
frm.refresh_field('items');
@@ -124,23 +128,23 @@
}
erpnext.utils.get_address_display = function(frm, address_field, display_field, is_your_company_address) {
- if(frm.updating_party_details) return;
+ if (frm.updating_party_details) return;
- if(!address_field) {
- if(frm.doctype != "Purchase Order" && frm.doc.customer) {
+ if (!address_field) {
+ if (frm.doctype != "Purchase Order" && frm.doc.customer) {
address_field = "customer_address";
- } else if(frm.doc.supplier) {
+ } else if (frm.doc.supplier) {
address_field = "supplier_address";
} else return;
}
- if(!display_field) display_field = "address_display";
- if(frm.doc[address_field]) {
+ if (!display_field) display_field = "address_display";
+ if (frm.doc[address_field]) {
frappe.call({
method: "frappe.contacts.doctype.address.address.get_address_display",
args: {"address_dict": frm.doc[address_field] },
callback: function(r) {
- if(r.message) {
+ if (r.message) {
frm.set_value(display_field, r.message)
}
}
@@ -151,15 +155,15 @@
};
erpnext.utils.set_taxes_from_address = function(frm, triggered_from_field, billing_address_field, shipping_address_field) {
- if(frm.updating_party_details) return;
+ if (frm.updating_party_details) return;
- if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
- if(!erpnext.utils.validate_mandatory(frm, "Lead/Customer/Supplier",
+ if (frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
+ if (!erpnext.utils.validate_mandatory(frm, "Lead / Customer / Supplier",
frm.doc.customer || frm.doc.supplier || frm.doc.lead || frm.doc.party_name, triggered_from_field)) {
return;
}
- if(!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date",
+ if (!erpnext.utils.validate_mandatory(frm, "Posting / Transaction Date",
frm.doc.posting_date || frm.doc.transaction_date, triggered_from_field)) {
return;
}
@@ -175,8 +179,8 @@
"shipping_address": frm.doc[shipping_address_field]
},
callback: function(r) {
- if(!r.exc){
- if(frm.doc.tax_category != r.message) {
+ if (!r.exc){
+ if (frm.doc.tax_category != r.message) {
frm.set_value("tax_category", r.message);
} else {
erpnext.utils.set_taxes(frm, triggered_from_field);
@@ -187,13 +191,17 @@
};
erpnext.utils.set_taxes = function(frm, triggered_from_field) {
- if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
- if(!erpnext.utils.validate_mandatory(frm, "Lead/Customer/Supplier",
+ if (frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
+ if (!erpnext.utils.validate_mandatory(frm, "Company", frm.doc.company, triggered_from_field)) {
+ return;
+ }
+
+ if (!erpnext.utils.validate_mandatory(frm, "Lead / Customer / Supplier",
frm.doc.customer || frm.doc.supplier || frm.doc.lead || frm.doc.party_name, triggered_from_field)) {
return;
}
- if(!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date",
+ if (!erpnext.utils.validate_mandatory(frm, "Posting / Transaction Date",
frm.doc.posting_date || frm.doc.transaction_date, triggered_from_field)) {
return;
}
@@ -230,7 +238,7 @@
"shipping_address": frm.doc.shipping_address_name
},
callback: function(r) {
- if(r.message){
+ if (r.message){
frm.set_value("taxes_and_charges", r.message)
}
}
@@ -238,14 +246,14 @@
};
erpnext.utils.get_contact_details = function(frm) {
- if(frm.updating_party_details) return;
+ if (frm.updating_party_details) return;
- if(frm.doc["contact_person"]) {
+ if (frm.doc["contact_person"]) {
frappe.call({
method: "frappe.contacts.doctype.contact.contact.get_contact_details",
args: {contact: frm.doc.contact_person },
callback: function(r) {
- if(r.message)
+ if (r.message)
frm.set_value(r.message);
}
})
@@ -253,10 +261,10 @@
}
erpnext.utils.validate_mandatory = function(frm, label, value, trigger_on) {
- if(!value) {
+ if (!value) {
frm.doc[trigger_on] = "";
refresh_field(trigger_on);
- frappe.msgprint(__("Please enter {0} first", [label]));
+ frappe.throw({message:__("Please enter {0} first", [label]), title:__("Mandatory")});
return false;
}
return true;
@@ -271,12 +279,12 @@
address: frm.doc.shipping_address
},
callback: function(r){
- if(r.message){
+ if (r.message){
frm.set_value("shipping_address", r.message[0]) //Address title or name
frm.set_value("shipping_address_display", r.message[1]) //Address to be displayed on the page
}
- if(callback){
+ if (callback){
return callback();
}
}
diff --git a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.js b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.js
index 63747af..dac6ac4 100644
--- a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.js
+++ b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.js
@@ -5,21 +5,28 @@
refresh: function(frm) {
frm.set_value("date", frappe.datetime.get_today());
},
- template: function(frm){
- frappe.call({
- "method": "frappe.client.get",
- args: {
- doctype: "Quality Feedback Template",
- name: frm.doc.template
- },
- callback: function(data){
- frm.fields_dict.parameters.grid.remove_all();
- for (var i in data.message.parameters){
- frm.add_child("parameters");
- frm.fields_dict.parameters.get_value()[i].parameter = data.message.parameters[i].parameter;
+
+ template: function(frm) {
+ if (frm.doc.template) {
+ frappe.call({
+ "method": "frappe.client.get",
+ args: {
+ doctype: "Quality Feedback Template",
+ name: frm.doc.template
+ },
+ callback: function(data) {
+ if (data && data.message) {
+ frm.fields_dict.parameters.grid.remove_all();
+
+ // fetch parameters from template and autofill
+ for (let template_parameter of data.message.parameters) {
+ let row = frm.add_child("parameters");
+ row.parameter = template_parameter.parameter;
+ }
+ frm.refresh();
+ }
}
- frm.refresh();
- }
- });
+ });
+ }
}
});
diff --git a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.json b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.json
index 460438a..ab9084f 100644
--- a/erpnext/quality_management/doctype/quality_feedback/quality_feedback.json
+++ b/erpnext/quality_management/doctype/quality_feedback/quality_feedback.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"autoname": "format:FDBK-{#####}",
"creation": "2019-05-26 21:23:05.308379",
"doctype": "DocType",
@@ -53,12 +54,13 @@
{
"fieldname": "document_name",
"fieldtype": "Dynamic Link",
- "label": "Name",
+ "label": "Feedback By",
"options": "document_type",
"reqd": 1
}
],
- "modified": "2019-05-28 15:16:01.161662",
+ "links": [],
+ "modified": "2020-07-03 15:50:58.589302",
"modified_by": "Administrator",
"module": "Quality Management",
"name": "Quality Feedback",
diff --git a/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.json b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.json
index 31efd04..bdc9dba 100644
--- a/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.json
+++ b/erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"autoname": "format:TMPL-{template}",
"creation": "2019-05-26 21:17:24.283061",
"doctype": "DocType",
@@ -30,10 +31,12 @@
"fieldname": "parameters",
"fieldtype": "Table",
"label": "Parameters",
- "options": "Quality Feedback Template Parameter"
+ "options": "Quality Feedback Template Parameter",
+ "reqd": 1
}
],
- "modified": "2019-05-26 21:48:47.770610",
+ "links": [],
+ "modified": "2020-07-03 16:06:03.749415",
"modified_by": "Administrator",
"module": "Quality Management",
"name": "Quality Feedback Template",
diff --git a/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py b/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py
index a748f9a..357deaa 100644
--- a/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py
+++ b/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py
@@ -65,6 +65,7 @@
return invoice.name
+@frappe.whitelist()
def item_query_restaurant(doctype='Item', txt='', searchfield='name', start=0, page_len=20, filters=None, as_dict=False):
'''Return items that are selected in active menu of the restaurant'''
restaurant, menu = get_restaurant_and_menu_name(filters['table'])
@@ -84,4 +85,4 @@
if not menu:
frappe.throw(_('Please set an active menu for Restaurant {0}').format(restaurant))
- return restaurant, menu
\ No newline at end of file
+ return restaurant, menu
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index e5c7c3c..e614acd 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -541,6 +541,7 @@
return address
+@frappe.whitelist()
def get_customer_primary_contact(doctype, txt, searchfield, start, page_len, filters):
customer = filters.get('customer')
return frappe.db.sql("""
diff --git a/erpnext/selling/doctype/product_bundle/product_bundle.py b/erpnext/selling/doctype/product_bundle/product_bundle.py
index c8a7167..0c85a1b 100644
--- a/erpnext/selling/doctype/product_bundle/product_bundle.py
+++ b/erpnext/selling/doctype/product_bundle/product_bundle.py
@@ -22,12 +22,13 @@
"""Validates, main Item is not a stock item"""
if frappe.db.get_value("Item", self.new_item_code, "is_stock_item"):
frappe.throw(_("Parent Item {0} must not be a Stock Item").format(self.new_item_code))
-
+
def validate_child_items(self):
for item in self.items:
if frappe.db.exists("Product Bundle", item.item_code):
- frappe.throw(_("Child Item should not be a Product Bundle. Please remove item `{0}` and save").format(item.item_code))
-
+ frappe.throw(_("Row #{0}: Child Item should not be a Product Bundle. Please remove Item {1} and Save").format(item.idx, frappe.bold(item.item_code)))
+
+@frappe.whitelist()
def get_new_item_code(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py
index dfa0f7f..1ae1fde 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -167,6 +167,7 @@
return cond % tuple(item_groups)
+@frappe.whitelist()
def item_group_query(doctype, txt, searchfield, start, page_len, filters):
item_groups = []
cond = "1=1"
@@ -187,4 +188,4 @@
@frappe.whitelist()
def get_pos_fields():
return frappe.get_all("POS Field", fields=["label", "fieldname",
- "fieldtype", "default_value", "reqd", "read_only", "options"])
\ No newline at end of file
+ "fieldtype", "default_value", "reqd", "read_only", "options"])
diff --git a/erpnext/stock/doctype/item_alternative/item_alternative.py b/erpnext/stock/doctype/item_alternative/item_alternative.py
index da0c3b7..522dfc6 100644
--- a/erpnext/stock/doctype/item_alternative/item_alternative.py
+++ b/erpnext/stock/doctype/item_alternative/item_alternative.py
@@ -42,6 +42,7 @@
'alternative_item_code': self.alternative_item_code, 'name': ('!=', self.name)}):
frappe.throw(_("Already record exists for the item {0}").format(self.item_code))
+@frappe.whitelist()
def get_alternative_items(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql(""" (select alternative_item_code from `tabItem Alternative`
where item_code = %(item_code)s and alternative_item_code like %(txt)s)
@@ -52,4 +53,4 @@
""".format(start, page_len), {
"item_code": filters.get('item_code'),
"txt": '%' + txt + '%'
- })
\ No newline at end of file
+ })
diff --git a/erpnext/stock/doctype/item_price/item_price.json b/erpnext/stock/doctype/item_price/item_price.json
index 2e0ddfd..5f62381 100644
--- a/erpnext/stock/doctype/item_price/item_price.json
+++ b/erpnext/stock/doctype/item_price/item_price.json
@@ -172,7 +172,7 @@
"default": "Today",
"fieldname": "valid_from",
"fieldtype": "Date",
- "label": "Valid From "
+ "label": "Valid From"
},
{
"default": "0",
@@ -187,7 +187,7 @@
{
"fieldname": "valid_upto",
"fieldtype": "Date",
- "label": "Valid Upto "
+ "label": "Valid Upto"
},
{
"fieldname": "section_break_24",
@@ -208,7 +208,7 @@
"icon": "fa fa-flag",
"idx": 1,
"links": [],
- "modified": "2020-02-28 14:21:25.580331",
+ "modified": "2020-07-06 22:31:32.943475",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item Price",
diff --git a/erpnext/stock/doctype/item_tax/item_tax.json b/erpnext/stock/doctype/item_tax/item_tax.json
index a93e463..ae36efc 100644
--- a/erpnext/stock/doctype/item_tax/item_tax.json
+++ b/erpnext/stock/doctype/item_tax/item_tax.json
@@ -1,5 +1,4 @@
{
- "actions": [],
"creation": "2013-02-22 01:28:01",
"doctype": "DocType",
"editable_grid": 1,
@@ -38,8 +37,7 @@
],
"idx": 1,
"istable": 1,
- "links": [],
- "modified": "2019-12-28 21:54:40.807849",
+ "modified": "2020-06-25 01:40:28.859752",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item Tax",
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 97606f4..25f1ed9 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -402,6 +402,7 @@
return material_requests
+@frappe.whitelist()
def get_default_supplier_query(doctype, txt, searchfield, start, page_len, filters):
doc = frappe.get_doc("Material Request", filters.get("doc"))
item_list = []
@@ -567,4 +568,4 @@
doc.set_item_locations()
- return doc
\ No newline at end of file
+ return doc
diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.py b/erpnext/stock/doctype/packing_slip/packing_slip.py
index 7a5ae31..4f831d7 100644
--- a/erpnext/stock/doctype/packing_slip/packing_slip.py
+++ b/erpnext/stock/doctype/packing_slip/packing_slip.py
@@ -175,6 +175,7 @@
self.update_item_details()
+@frappe.whitelist()
def item_details(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
return frappe.db.sql("""select name, item_name, description from `tabItem`
diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
index 37ab807..568e742 100644
--- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py
+++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
@@ -58,6 +58,7 @@
.format(parent_doc=self.reference_type, child_doc=doctype),
(quality_inspection, self.modified, self.reference_name, self.item_code))
+@frappe.whitelist()
def item_query(doctype, txt, searchfield, start, page_len, filters):
if filters.get("from"):
from frappe.desk.reportview import get_match_cond
@@ -86,6 +87,7 @@
page_len = page_len, qi_condition = qi_condition),
{'parent': filters.get('parent'), 'txt': "%%%s%%" % txt})
+@frappe.whitelist()
def quality_inspection_query(doctype, txt, searchfield, start, page_len, filters):
return frappe.get_all('Quality Inspection',
limit_start=start,
@@ -118,4 +120,4 @@
}
}, target_doc, postprocess)
- return doc
\ No newline at end of file
+ return doc
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 0ed3b27..1f30f5a 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -413,7 +413,7 @@
continue
out[item_code] = {}
item = frappe.get_cached_doc("Item", item_code)
- get_item_tax_template({"tax_category": tax_category}, item, out[item_code])
+ get_item_tax_template({"company": company, "tax_category": tax_category}, item, out[item_code])
out[item_code]["item_tax_rate"] = get_item_tax_map(company, out[item_code].get("item_tax_template"), as_json=True)
return out
@@ -442,7 +442,8 @@
taxes_with_no_validity = []
for tax in taxes:
- if tax.valid_from:
+ tax_company = frappe.get_value("Item Tax Template", tax.item_tax_template, 'company')
+ if tax.valid_from and tax_company == args['company']:
# In purchase Invoice first preference will be given to supplier invoice date
# if supplier date is not present then posting date
validation_date = args.get('transaction_date') or args.get('bill_date') or args.get('posting_date')
@@ -450,7 +451,8 @@
if getdate(tax.valid_from) <= getdate(validation_date):
taxes_with_validity.append(tax)
else:
- taxes_with_no_validity.append(tax)
+ if tax_company == args['company']:
+ taxes_with_no_validity.append(tax)
if taxes_with_validity:
taxes = sorted(taxes_with_validity, key = lambda i: i.valid_from, reverse=True)
@@ -636,6 +638,10 @@
if args.get('transaction_date'):
conditions += """ and %(transaction_date)s between
ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31')"""
+
+ if args.get('posting_date'):
+ conditions += """ and %(posting_date)s between
+ ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31')"""
return frappe.db.sql(""" select name, price_list_rate, uom
from `tabItem Price` {conditions}
@@ -657,6 +663,7 @@
"supplier": args.get('supplier'),
"uom": args.get('uom'),
"transaction_date": args.get('transaction_date'),
+ "posting_date": args.get('posting_date'),
}
item_price_data = 0
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index 2359648..5bf85d1 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -120,6 +120,16 @@
def validate_rate_with_reference_doc(self, ref_details):
+ buying_doctypes = ["Purchase Order", "Purchase Invoice", "Purchase Receipt"]
+ selling_doctypes = ["Sales Invoice", "Delivery Note"]
+
+ if self.doctype in buying_doctypes:
+ to_disable = "Maintain same rate throughout Purchase cycle"
+ settings_page = "Buying Settings"
+ else:
+ to_disable = "Maintain same rate throughout Sales cycle"
+ settings_page = "Selling Settings"
+
for ref_dt, ref_dn_field, ref_link_field in ref_details:
for d in self.get("items"):
if d.get(ref_link_field):
@@ -129,8 +139,8 @@
frappe.msgprint(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4}) ")
.format(d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate))
frappe.throw(_("To allow different rates, disable the {0} checkbox in {1}.")
- .format(frappe.bold(_("Maintain Same Rate Throughout Sales Cycle")),
- get_link_to_form("Selling Settings", "Selling Settings", frappe.bold("Selling Settings"))))
+ .format(frappe.bold(_(to_disable)),
+ get_link_to_form(settings_page, settings_page, frappe.bold(settings_page))))
def get_link_filters(self, for_doctype):
if hasattr(self, "prev_link_mapper") and self.prev_link_mapper.get(for_doctype):