Merge branch 'rebrand-ui' of https://github.com/frappe/erpnext into rebrand-ui
This commit is contained in:
commit
5ee7bca185
@ -53,7 +53,7 @@
|
|||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"label": "Goods and Services Tax (GST India)",
|
"label": "Goods and Services Tax (GST India)",
|
||||||
"links": "[\n {\n \"label\": \"GST Settings\",\n \"name\": \"GST Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"GST HSN Code\",\n \"name\": \"GST HSN Code\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-1\",\n \"name\": \"GSTR-1\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-2\",\n \"name\": \"GSTR-2\",\n \"type\": \"report\"\n },\n {\n \"label\": \"GSTR 3B Report\",\n \"name\": \"GSTR 3B Report\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Sales Register\",\n \"name\": \"GST Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Purchase Register\",\n \"name\": \"GST Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Sales Register\",\n \"name\": \"GST Itemised Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Purchase Register\",\n \"name\": \"GST Itemised Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"country\": \"India\",\n \"description\": \"C-Form records\",\n \"label\": \"C-Form\",\n \"name\": \"C-Form\",\n \"type\": \"doctype\"\n }\n]"
|
"links": "[\n {\n \"label\": \"GST Settings\",\n \"name\": \"GST Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"GST HSN Code\",\n \"name\": \"GST HSN Code\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-1\",\n \"name\": \"GSTR-1\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-2\",\n \"name\": \"GSTR-2\",\n \"type\": \"report\"\n },\n {\n \"label\": \"GSTR 3B Report\",\n \"name\": \"GSTR 3B Report\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Sales Register\",\n \"name\": \"GST Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Purchase Register\",\n \"name\": \"GST Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Sales Register\",\n \"name\": \"GST Itemised Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Purchase Register\",\n \"name\": \"GST Itemised Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"country\": \"India\",\n \"description\": \"C-Form records\",\n \"label\": \"C-Form\",\n \"name\": \"C-Form\",\n \"type\": \"doctype\"\n },\n {\n \"country\": \"India\",\n \"label\": \"Lower Deduction Certificate\",\n \"name\": \"Lower Deduction Certificate\",\n \"type\": \"doctype\"\n }\n]"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -99,7 +99,7 @@
|
|||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"label": "Accounting",
|
"label": "Accounting",
|
||||||
"modified": "2020-09-09 11:45:33.766400",
|
"modified": "2020-10-08 20:31:46.022470",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounting",
|
"name": "Accounting",
|
||||||
|
@ -117,7 +117,9 @@ class Account(NestedSet):
|
|||||||
|
|
||||||
for d in frappe.db.get_values('Account', filters=filters, fieldname=["company", "name"], as_dict=True):
|
for d in frappe.db.get_values('Account', filters=filters, fieldname=["company", "name"], as_dict=True):
|
||||||
parent_acc_name_map[d["company"]] = d["name"]
|
parent_acc_name_map[d["company"]] = d["name"]
|
||||||
|
|
||||||
if not parent_acc_name_map: return
|
if not parent_acc_name_map: return
|
||||||
|
|
||||||
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
|
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
|
||||||
|
|
||||||
def validate_group_or_ledger(self):
|
def validate_group_or_ledger(self):
|
||||||
@ -289,10 +291,30 @@ def validate_account_number(name, account_number, company):
|
|||||||
.format(account_number, account_with_same_number))
|
.format(account_number, account_with_same_number))
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def update_account_number(name, account_name, account_number=None):
|
def update_account_number(name, account_name, account_number=None, from_descendant=False):
|
||||||
|
|
||||||
account = frappe.db.get_value("Account", name, "company", as_dict=True)
|
account = frappe.db.get_value("Account", name, "company", as_dict=True)
|
||||||
if not account: return
|
if not account: return
|
||||||
|
|
||||||
|
old_acc_name, old_acc_number = frappe.db.get_value('Account', name, \
|
||||||
|
["account_name", "account_number"])
|
||||||
|
|
||||||
|
# check if account exists in parent company
|
||||||
|
ancestors = get_ancestors_of("Company", account.company)
|
||||||
|
allow_independent_account_creation = frappe.get_value("Company", account.company, "allow_account_creation_against_child_company")
|
||||||
|
|
||||||
|
if ancestors and not allow_independent_account_creation:
|
||||||
|
for ancestor in ancestors:
|
||||||
|
if frappe.db.get_value("Account", {'account_name': old_acc_name, 'company': ancestor}, 'name'):
|
||||||
|
# same account in parent company exists
|
||||||
|
allow_child_account_creation = _("Allow Account Creation Against Child Company")
|
||||||
|
|
||||||
|
message = _("Account {0} exists in parent company {1}.").format(frappe.bold(old_acc_name), frappe.bold(ancestor))
|
||||||
|
message += "<br>" + _("Renaming it is only allowed via parent company {0}, \
|
||||||
|
to avoid mismatch.").format(frappe.bold(ancestor)) + "<br><br>"
|
||||||
|
message += _("To overrule this, enable '{0}' in company {1}").format(allow_child_account_creation, frappe.bold(account.company))
|
||||||
|
|
||||||
|
frappe.throw(message, title=_("Rename Not Allowed"))
|
||||||
|
|
||||||
validate_account_number(name, account_number, account.company)
|
validate_account_number(name, account_number, account.company)
|
||||||
if account_number:
|
if account_number:
|
||||||
frappe.db.set_value("Account", name, "account_number", account_number.strip())
|
frappe.db.set_value("Account", name, "account_number", account_number.strip())
|
||||||
@ -300,6 +322,12 @@ def update_account_number(name, account_name, account_number=None):
|
|||||||
frappe.db.set_value("Account", name, "account_number", "")
|
frappe.db.set_value("Account", name, "account_number", "")
|
||||||
frappe.db.set_value("Account", name, "account_name", account_name.strip())
|
frappe.db.set_value("Account", name, "account_name", account_name.strip())
|
||||||
|
|
||||||
|
if not from_descendant:
|
||||||
|
# Update and rename in child company accounts as well
|
||||||
|
descendants = get_descendants_of('Company', account.company)
|
||||||
|
if descendants:
|
||||||
|
sync_update_account_number_in_child(descendants, old_acc_name, account_name, account_number, old_acc_number)
|
||||||
|
|
||||||
new_name = get_account_autoname(account_number, account_name, account.company)
|
new_name = get_account_autoname(account_number, account_name, account.company)
|
||||||
if name != new_name:
|
if name != new_name:
|
||||||
frappe.rename_doc("Account", name, new_name, force=1)
|
frappe.rename_doc("Account", name, new_name, force=1)
|
||||||
@ -330,3 +358,14 @@ def get_root_company(company):
|
|||||||
# return the topmost company in the hierarchy
|
# return the topmost company in the hierarchy
|
||||||
ancestors = get_ancestors_of('Company', company, "lft asc")
|
ancestors = get_ancestors_of('Company', company, "lft asc")
|
||||||
return [ancestors[0]] if ancestors else []
|
return [ancestors[0]] if ancestors else []
|
||||||
|
|
||||||
|
def sync_update_account_number_in_child(descendants, old_acc_name, account_name, account_number=None, old_acc_number=None):
|
||||||
|
filters = {
|
||||||
|
"company": ["in", descendants],
|
||||||
|
"account_name": old_acc_name,
|
||||||
|
}
|
||||||
|
if old_acc_number:
|
||||||
|
filters["account_number"] = old_acc_number
|
||||||
|
|
||||||
|
for d in frappe.db.get_values('Account', filters=filters, fieldname=["company", "name"], as_dict=True):
|
||||||
|
update_account_number(d["name"], account_name, account_number, from_descendant=True)
|
||||||
|
@ -5,8 +5,7 @@ from __future__ import unicode_literals
|
|||||||
import unittest
|
import unittest
|
||||||
import frappe
|
import frappe
|
||||||
from erpnext.stock import get_warehouse_account, get_company_default_inventory_account
|
from erpnext.stock import get_warehouse_account, get_company_default_inventory_account
|
||||||
from erpnext.accounts.doctype.account.account import update_account_number
|
from erpnext.accounts.doctype.account.account import update_account_number, merge_account
|
||||||
from erpnext.accounts.doctype.account.account import merge_account
|
|
||||||
|
|
||||||
class TestAccount(unittest.TestCase):
|
class TestAccount(unittest.TestCase):
|
||||||
def test_rename_account(self):
|
def test_rename_account(self):
|
||||||
@ -99,7 +98,8 @@ class TestAccount(unittest.TestCase):
|
|||||||
"Softwares - _TC", doc.is_group, doc.root_type, doc.company)
|
"Softwares - _TC", doc.is_group, doc.root_type, doc.company)
|
||||||
|
|
||||||
def test_account_sync(self):
|
def test_account_sync(self):
|
||||||
del frappe.local.flags["ignore_root_company_validation"]
|
frappe.local.flags.pop("ignore_root_company_validation", None)
|
||||||
|
|
||||||
acc = frappe.new_doc("Account")
|
acc = frappe.new_doc("Account")
|
||||||
acc.account_name = "Test Sync Account"
|
acc.account_name = "Test Sync Account"
|
||||||
acc.parent_account = "Temporary Accounts - _TC3"
|
acc.parent_account = "Temporary Accounts - _TC3"
|
||||||
@ -111,6 +111,55 @@ class TestAccount(unittest.TestCase):
|
|||||||
self.assertEqual(acc_tc_4, "Test Sync Account - _TC4")
|
self.assertEqual(acc_tc_4, "Test Sync Account - _TC4")
|
||||||
self.assertEqual(acc_tc_5, "Test Sync Account - _TC5")
|
self.assertEqual(acc_tc_5, "Test Sync Account - _TC5")
|
||||||
|
|
||||||
|
def test_account_rename_sync(self):
|
||||||
|
frappe.local.flags.pop("ignore_root_company_validation", None)
|
||||||
|
|
||||||
|
acc = frappe.new_doc("Account")
|
||||||
|
acc.account_name = "Test Rename Account"
|
||||||
|
acc.parent_account = "Temporary Accounts - _TC3"
|
||||||
|
acc.company = "_Test Company 3"
|
||||||
|
acc.insert()
|
||||||
|
|
||||||
|
# Rename account in parent company
|
||||||
|
update_account_number(acc.name, "Test Rename Sync Account", "1234")
|
||||||
|
|
||||||
|
# Check if renamed in children
|
||||||
|
self.assertTrue(frappe.db.exists("Account", {'account_name': "Test Rename Sync Account", "company": "_Test Company 4", "account_number": "1234"}))
|
||||||
|
self.assertTrue(frappe.db.exists("Account", {'account_name': "Test Rename Sync Account", "company": "_Test Company 5", "account_number": "1234"}))
|
||||||
|
|
||||||
|
frappe.delete_doc("Account", "1234 - Test Rename Sync Account - _TC3")
|
||||||
|
frappe.delete_doc("Account", "1234 - Test Rename Sync Account - _TC4")
|
||||||
|
frappe.delete_doc("Account", "1234 - Test Rename Sync Account - _TC5")
|
||||||
|
|
||||||
|
def test_child_company_account_rename_sync(self):
|
||||||
|
frappe.local.flags.pop("ignore_root_company_validation", None)
|
||||||
|
|
||||||
|
acc = frappe.new_doc("Account")
|
||||||
|
acc.account_name = "Test Group Account"
|
||||||
|
acc.parent_account = "Temporary Accounts - _TC3"
|
||||||
|
acc.is_group = 1
|
||||||
|
acc.company = "_Test Company 3"
|
||||||
|
acc.insert()
|
||||||
|
|
||||||
|
self.assertTrue(frappe.db.exists("Account", {'account_name': "Test Group Account", "company": "_Test Company 4"}))
|
||||||
|
self.assertTrue(frappe.db.exists("Account", {'account_name': "Test Group Account", "company": "_Test Company 5"}))
|
||||||
|
|
||||||
|
# Try renaming child company account
|
||||||
|
acc_tc_5 = frappe.db.get_value('Account', {'account_name': "Test Group Account", "company": "_Test Company 5"})
|
||||||
|
self.assertRaises(frappe.ValidationError, update_account_number, acc_tc_5, "Test Modified Account")
|
||||||
|
|
||||||
|
# Rename child company account with allow_account_creation_against_child_company enabled
|
||||||
|
frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 1)
|
||||||
|
|
||||||
|
update_account_number(acc_tc_5, "Test Modified Account")
|
||||||
|
self.assertTrue(frappe.db.exists("Account", {'name': "Test Modified Account - _TC5", "company": "_Test Company 5"}))
|
||||||
|
|
||||||
|
frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 0)
|
||||||
|
|
||||||
|
to_delete = ["Test Group Account - _TC3", "Test Group Account - _TC4", "Test Modified Account - _TC5"]
|
||||||
|
for doc in to_delete:
|
||||||
|
frappe.delete_doc("Account", doc)
|
||||||
|
|
||||||
def _make_test_records(verbose):
|
def _make_test_records(verbose):
|
||||||
from frappe.test_runner import make_test_objects
|
from frappe.test_runner import make_test_objects
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@
|
|||||||
"default": "1",
|
"default": "1",
|
||||||
"fieldname": "unlink_advance_payment_on_cancelation_of_order",
|
"fieldname": "unlink_advance_payment_on_cancelation_of_order",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Unlink Advance Payment on Cancelation of Order"
|
"label": "Unlink Advance Payment on Cancellation of Order"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "1",
|
"default": "1",
|
||||||
@ -223,9 +223,10 @@
|
|||||||
],
|
],
|
||||||
"icon": "icon-cog",
|
"icon": "icon-cog",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-08-03 20:13:26.043092",
|
"modified": "2020-10-07 14:58:50.325577",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounts Settings",
|
"name": "Accounts Settings",
|
||||||
|
@ -1,785 +1,204 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 0,
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2016-05-16 11:42:29.632528",
|
"creation": "2016-05-16 11:42:29.632528",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"budget_against",
|
||||||
|
"company",
|
||||||
|
"cost_center",
|
||||||
|
"project",
|
||||||
|
"fiscal_year",
|
||||||
|
"column_break_3",
|
||||||
|
"monthly_distribution",
|
||||||
|
"amended_from",
|
||||||
|
"section_break_6",
|
||||||
|
"applicable_on_material_request",
|
||||||
|
"action_if_annual_budget_exceeded_on_mr",
|
||||||
|
"action_if_accumulated_monthly_budget_exceeded_on_mr",
|
||||||
|
"column_break_13",
|
||||||
|
"applicable_on_purchase_order",
|
||||||
|
"action_if_annual_budget_exceeded_on_po",
|
||||||
|
"action_if_accumulated_monthly_budget_exceeded_on_po",
|
||||||
|
"section_break_16",
|
||||||
|
"applicable_on_booking_actual_expenses",
|
||||||
|
"action_if_annual_budget_exceeded",
|
||||||
|
"action_if_accumulated_monthly_budget_exceeded",
|
||||||
|
"section_break_21",
|
||||||
|
"accounts"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "Cost Center",
|
"default": "Cost Center",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "budget_against",
|
"fieldname": "budget_against",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Budget Against",
|
"label": "Budget Against",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nCost Center\nProject",
|
"options": "\nCost Center\nProject",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Company",
|
"label": "Company",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Company",
|
"options": "Company",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "eval:doc.budget_against == 'Cost Center'",
|
"depends_on": "eval:doc.budget_against == 'Cost Center'",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "cost_center",
|
"fieldname": "cost_center",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 1,
|
"in_global_search": 1,
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Cost Center",
|
"label": "Cost Center",
|
||||||
"length": 0,
|
"options": "Cost Center"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Cost Center",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "eval:doc.budget_against == 'Project'",
|
"depends_on": "eval:doc.budget_against == 'Project'",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "project",
|
"fieldname": "project",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Project",
|
"label": "Project",
|
||||||
"length": 0,
|
"options": "Project"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Project",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "fiscal_year",
|
"fieldname": "fiscal_year",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Fiscal Year",
|
"label": "Fiscal Year",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "eval:in_list([\"Stop\", \"Warn\"], doc.action_if_accumulated_monthly_budget_exceeded_on_po || doc.action_if_accumulated_monthly_budget_exceeded_on_mr || doc.action_if_accumulated_monthly_budget_exceeded_on_actual)",
|
"depends_on": "eval:in_list([\"Stop\", \"Warn\"], doc.action_if_accumulated_monthly_budget_exceeded_on_po || doc.action_if_accumulated_monthly_budget_exceeded_on_mr || doc.action_if_accumulated_monthly_budget_exceeded_on_actual)",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "monthly_distribution",
|
"fieldname": "monthly_distribution",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"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": "Monthly Distribution",
|
"label": "Monthly Distribution",
|
||||||
"length": 0,
|
"options": "Monthly Distribution"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Monthly Distribution",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "amended_from",
|
"fieldname": "amended_from",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"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": "Amended From",
|
"label": "Amended From",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Budget",
|
"options": "Budget",
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_hide_if_no_value": 0,
|
"read_only": 1
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "section_break_6",
|
"fieldname": "section_break_6",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"label": "Control Action"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Control Action",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"default": "0",
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "applicable_on_material_request",
|
"fieldname": "applicable_on_material_request",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"label": "Applicable on Material Request"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Applicable on Material Request",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "Stop",
|
"default": "Stop",
|
||||||
"depends_on": "eval:doc.applicable_on_material_request == 1",
|
"depends_on": "eval:doc.applicable_on_material_request == 1",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "action_if_annual_budget_exceeded_on_mr",
|
"fieldname": "action_if_annual_budget_exceeded_on_mr",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"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": "Action if Annual Budget Exceeded on MR",
|
"label": "Action if Annual Budget Exceeded on MR",
|
||||||
"length": 0,
|
"options": "\nStop\nWarn\nIgnore"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nStop\nWarn\nIgnore",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "Warn",
|
"default": "Warn",
|
||||||
"depends_on": "eval:doc.applicable_on_material_request == 1",
|
"depends_on": "eval:doc.applicable_on_material_request == 1",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "action_if_accumulated_monthly_budget_exceeded_on_mr",
|
"fieldname": "action_if_accumulated_monthly_budget_exceeded_on_mr",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"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": "Action if Accumulated Monthly Budget Exceeded on MR",
|
"label": "Action if Accumulated Monthly Budget Exceeded on MR",
|
||||||
"length": 0,
|
"options": "\nStop\nWarn\nIgnore"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nStop\nWarn\nIgnore",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "column_break_13",
|
"fieldname": "column_break_13",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"default": "0",
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "applicable_on_purchase_order",
|
"fieldname": "applicable_on_purchase_order",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"label": "Applicable on Purchase Order"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Applicable on Purchase Order",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "Stop",
|
"default": "Stop",
|
||||||
"depends_on": "eval:doc.applicable_on_purchase_order == 1",
|
"depends_on": "eval:doc.applicable_on_purchase_order == 1",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "action_if_annual_budget_exceeded_on_po",
|
"fieldname": "action_if_annual_budget_exceeded_on_po",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"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": "Action if Annual Budget Exceeded on PO",
|
"label": "Action if Annual Budget Exceeded on PO",
|
||||||
"length": 0,
|
"options": "\nStop\nWarn\nIgnore"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nStop\nWarn\nIgnore",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "Warn",
|
"default": "Warn",
|
||||||
"depends_on": "eval:doc.applicable_on_purchase_order == 1",
|
"depends_on": "eval:doc.applicable_on_purchase_order == 1",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "action_if_accumulated_monthly_budget_exceeded_on_po",
|
"fieldname": "action_if_accumulated_monthly_budget_exceeded_on_po",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"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": "Action if Accumulated Monthly Budget Exceeded on PO",
|
"label": "Action if Accumulated Monthly Budget Exceeded on PO",
|
||||||
"length": 0,
|
"options": "\nStop\nWarn\nIgnore"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nStop\nWarn\nIgnore",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "section_break_16",
|
"fieldname": "section_break_16",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"default": "0",
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "applicable_on_booking_actual_expenses",
|
"fieldname": "applicable_on_booking_actual_expenses",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"label": "Applicable on booking actual expenses"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Applicable on booking actual expenses",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "Stop",
|
"default": "Stop",
|
||||||
"depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1",
|
"depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "action_if_annual_budget_exceeded",
|
"fieldname": "action_if_annual_budget_exceeded",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"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": "Action if Annual Budget Exceeded on Actual",
|
"label": "Action if Annual Budget Exceeded on Actual",
|
||||||
"length": 0,
|
"options": "\nStop\nWarn\nIgnore"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nStop\nWarn\nIgnore",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "Warn",
|
"default": "Warn",
|
||||||
"depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1",
|
"depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "action_if_accumulated_monthly_budget_exceeded",
|
"fieldname": "action_if_accumulated_monthly_budget_exceeded",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"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": "Action if Accumulated Monthly Budget Exceeded on Actual",
|
"label": "Action if Accumulated Monthly Budget Exceeded on Actual",
|
||||||
"length": 0,
|
"options": "\nStop\nWarn\nIgnore"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nStop\nWarn\nIgnore",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "section_break_21",
|
"fieldname": "section_break_21",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "",
|
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "accounts",
|
"fieldname": "accounts",
|
||||||
"fieldtype": "Table",
|
"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": "Budget Accounts",
|
"label": "Budget Accounts",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Budget Account",
|
"options": "Budget Account",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"index_web_pages_for_search": 1,
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"issingle": 0,
|
"links": [],
|
||||||
"istable": 0,
|
"modified": "2020-10-06 15:13:54.055854",
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2019-03-22 12:06:02.323099",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Budget",
|
"name": "Budget",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@ -789,26 +208,17 @@
|
|||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 1,
|
"import": 1,
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Accounts Manager",
|
"role": "Accounts Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 1,
|
"submit": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"track_changes": 1
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
@ -22,8 +22,12 @@ class JournalEntry(AccountsController):
|
|||||||
return self.voucher_type
|
return self.voucher_type
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
if self.voucher_type == 'Opening Entry':
|
||||||
|
self.is_opening = 'Yes'
|
||||||
|
|
||||||
if not self.is_opening:
|
if not self.is_opening:
|
||||||
self.is_opening='No'
|
self.is_opening='No'
|
||||||
|
|
||||||
self.clearance_date = None
|
self.clearance_date = None
|
||||||
|
|
||||||
self.validate_party()
|
self.validate_party()
|
||||||
|
@ -195,9 +195,7 @@ def create_sales_invoice_record(qty=1):
|
|||||||
|
|
||||||
def create_records():
|
def create_records():
|
||||||
# create a new loyalty Account
|
# create a new loyalty Account
|
||||||
if frappe.db.exists("Account", "Loyalty - _TC"):
|
if not frappe.db.exists("Account", "Loyalty - _TC"):
|
||||||
return
|
|
||||||
|
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Account",
|
"doctype": "Account",
|
||||||
"account_name": "Loyalty",
|
"account_name": "Loyalty",
|
||||||
@ -208,6 +206,7 @@ def create_records():
|
|||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
# create a new loyalty program Single tier
|
# create a new loyalty program Single tier
|
||||||
|
if not frappe.db.exists("Loyalty Program","Test Single Loyalty"):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Loyalty Program",
|
"doctype": "Loyalty Program",
|
||||||
"loyalty_program_name": "Test Single Loyalty",
|
"loyalty_program_name": "Test Single Loyalty",
|
||||||
@ -227,6 +226,7 @@ def create_records():
|
|||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
# create a new customer
|
# create a new customer
|
||||||
|
if not frappe.db.exists("Customer","Test Loyalty Customer"):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"customer_group": "_Test Customer Group",
|
"customer_group": "_Test Customer Group",
|
||||||
"customer_name": "Test Loyalty Customer",
|
"customer_name": "Test Loyalty Customer",
|
||||||
@ -236,6 +236,7 @@ def create_records():
|
|||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
# create a new loyalty program Multiple tier
|
# create a new loyalty program Multiple tier
|
||||||
|
if not frappe.db.exists("Loyalty Program","Test Multiple Loyalty"):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Loyalty Program",
|
"doctype": "Loyalty Program",
|
||||||
"loyalty_program_name": "Test Multiple Loyalty",
|
"loyalty_program_name": "Test Multiple Loyalty",
|
||||||
@ -262,7 +263,8 @@ def create_records():
|
|||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
# create an item
|
# create an item
|
||||||
item = frappe.get_doc({
|
if not frappe.db.exists("Item", "Loyal Item"):
|
||||||
|
frappe.get_doc({
|
||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"item_code": "Loyal Item",
|
"item_code": "Loyal Item",
|
||||||
"item_name": "Loyal Item",
|
"item_name": "Loyal Item",
|
||||||
@ -274,9 +276,10 @@ def create_records():
|
|||||||
}).insert()
|
}).insert()
|
||||||
|
|
||||||
# create item price
|
# create item price
|
||||||
|
if not frappe.db.exists("Item Price", {"price_list": "Standard Selling", "item_code": "Loyal Item"}):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Item Price",
|
"doctype": "Item Price",
|
||||||
"price_list": "Standard Selling",
|
"price_list": "Standard Selling",
|
||||||
"item_code": item.item_code,
|
"item_code": "Loyal Item",
|
||||||
"price_list_rate": 10000
|
"price_list_rate": 10000
|
||||||
}).insert()
|
}).insert()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
frappe.listview_settings['Payment Entry'] = {
|
frappe.listview_settings['Payment Entry'] = {
|
||||||
|
|
||||||
onload: function(listview) {
|
onload: function(listview) {
|
||||||
|
if (listview.page.fields_dict.party_type) {
|
||||||
listview.page.fields_dict.party_type.get_query = function() {
|
listview.page.fields_dict.party_type.get_query = function() {
|
||||||
return {
|
return {
|
||||||
"filters": {
|
"filters": {
|
||||||
@ -9,4 +10,5 @@ frappe.listview_settings['Payment Entry'] = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
@ -45,7 +45,7 @@ class TestPOSClosingEntry(unittest.TestCase):
|
|||||||
frappe.set_user("Administrator")
|
frappe.set_user("Administrator")
|
||||||
frappe.db.sql("delete from `tabPOS Profile`")
|
frappe.db.sql("delete from `tabPOS Profile`")
|
||||||
|
|
||||||
def init_user_and_profile():
|
def init_user_and_profile(**args):
|
||||||
user = 'test@example.com'
|
user = 'test@example.com'
|
||||||
test_user = frappe.get_doc('User', user)
|
test_user = frappe.get_doc('User', user)
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ def init_user_and_profile():
|
|||||||
test_user.add_roles(*roles)
|
test_user.add_roles(*roles)
|
||||||
frappe.set_user(user)
|
frappe.set_user(user)
|
||||||
|
|
||||||
pos_profile = make_pos_profile()
|
pos_profile = make_pos_profile(**args)
|
||||||
pos_profile.append('applicable_for_users', {
|
pos_profile.append('applicable_for_users', {
|
||||||
'default': 1,
|
'default': 1,
|
||||||
'user': user
|
'user': user
|
||||||
|
@ -139,7 +139,8 @@ class POSInvoice(SalesInvoice):
|
|||||||
frappe.throw(_("At least one mode of payment is required for POS invoice."))
|
frappe.throw(_("At least one mode of payment is required for POS invoice."))
|
||||||
|
|
||||||
def validate_change_account(self):
|
def validate_change_account(self):
|
||||||
if frappe.db.get_value("Account", self.account_for_change_amount, "company") != self.company:
|
if self.change_amount and self.account_for_change_amount and \
|
||||||
|
frappe.db.get_value("Account", self.account_for_change_amount, "company") != self.company:
|
||||||
frappe.throw(_("The selected change account {} doesn't belongs to Company {}.").format(self.account_for_change_amount, self.company))
|
frappe.throw(_("The selected change account {} doesn't belongs to Company {}.").format(self.account_for_change_amount, self.company))
|
||||||
|
|
||||||
def validate_change_amount(self):
|
def validate_change_amount(self):
|
||||||
|
@ -7,6 +7,8 @@ import frappe
|
|||||||
import unittest, copy, time
|
import unittest, copy, time
|
||||||
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
|
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
|
||||||
from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return
|
from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return
|
||||||
|
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||||
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
||||||
|
|
||||||
class TestPOSInvoice(unittest.TestCase):
|
class TestPOSInvoice(unittest.TestCase):
|
||||||
def test_timestamp_change(self):
|
def test_timestamp_change(self):
|
||||||
@ -221,29 +223,29 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
|
|
||||||
se = make_serialized_item(company='_Test Company with perpetual inventory',
|
se = make_serialized_item(company='_Test Company',
|
||||||
target_warehouse="Stores - TCP1", cost_center='Main - TCP1', expense_account='Cost of Goods Sold - TCP1')
|
target_warehouse="Stores - _TC", cost_center='Main - _TC', expense_account='Cost of Goods Sold - _TC')
|
||||||
|
|
||||||
serial_nos = get_serial_nos(se.get("items")[0].serial_no)
|
serial_nos = get_serial_nos(se.get("items")[0].serial_no)
|
||||||
|
|
||||||
pos = create_pos_invoice(company='_Test Company with perpetual inventory', debit_to='Debtors - TCP1',
|
pos = create_pos_invoice(company='_Test Company', debit_to='Debtors - _TC',
|
||||||
account_for_change_amount='Cash - TCP1', warehouse='Stores - TCP1', income_account='Sales - TCP1',
|
account_for_change_amount='Cash - _TC', warehouse='Stores - _TC', income_account='Sales - _TC',
|
||||||
expense_account='Cost of Goods Sold - TCP1', cost_center='Main - TCP1',
|
expense_account='Cost of Goods Sold - _TC', cost_center='Main - _TC',
|
||||||
item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
|
item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
|
||||||
|
|
||||||
pos.get("items")[0].serial_no = serial_nos[0]
|
pos.get("items")[0].serial_no = serial_nos[0]
|
||||||
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 1000})
|
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 1000})
|
||||||
|
|
||||||
pos.insert()
|
pos.insert()
|
||||||
pos.submit()
|
pos.submit()
|
||||||
|
|
||||||
pos2 = create_pos_invoice(company='_Test Company with perpetual inventory', debit_to='Debtors - TCP1',
|
pos2 = create_pos_invoice(company='_Test Company', debit_to='Debtors - _TC',
|
||||||
account_for_change_amount='Cash - TCP1', warehouse='Stores - TCP1', income_account='Sales - TCP1',
|
account_for_change_amount='Cash - _TC', warehouse='Stores - _TC', income_account='Sales - _TC',
|
||||||
expense_account='Cost of Goods Sold - TCP1', cost_center='Main - TCP1',
|
expense_account='Cost of Goods Sold - _TC', cost_center='Main - _TC',
|
||||||
item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
|
item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
|
||||||
|
|
||||||
pos2.get("items")[0].serial_no = serial_nos[0]
|
pos2.get("items")[0].serial_no = serial_nos[0]
|
||||||
pos2.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 1000})
|
pos2.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 1000})
|
||||||
|
|
||||||
self.assertRaises(frappe.ValidationError, pos2.insert)
|
self.assertRaises(frappe.ValidationError, pos2.insert)
|
||||||
|
|
||||||
@ -286,6 +288,119 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
after_redeem_lp_details = get_loyalty_program_details_with_points(inv.customer, company=inv.company, loyalty_program=inv.loyalty_program)
|
after_redeem_lp_details = get_loyalty_program_details_with_points(inv.customer, company=inv.company, loyalty_program=inv.loyalty_program)
|
||||||
self.assertEqual(after_redeem_lp_details.loyalty_points, 9)
|
self.assertEqual(after_redeem_lp_details.loyalty_points, 9)
|
||||||
|
|
||||||
|
def test_merging_into_sales_invoice_with_discount(self):
|
||||||
|
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
|
||||||
|
from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import merge_pos_invoices
|
||||||
|
|
||||||
|
frappe.db.sql("delete from `tabPOS Invoice`")
|
||||||
|
test_user, pos_profile = init_user_and_profile()
|
||||||
|
pos_inv = create_pos_invoice(rate=300, additional_discount_percentage=10, do_not_submit=1)
|
||||||
|
pos_inv.append('payments', {
|
||||||
|
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 270
|
||||||
|
})
|
||||||
|
pos_inv.submit()
|
||||||
|
|
||||||
|
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
|
||||||
|
pos_inv2.append('payments', {
|
||||||
|
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3200
|
||||||
|
})
|
||||||
|
pos_inv2.submit()
|
||||||
|
|
||||||
|
merge_pos_invoices()
|
||||||
|
|
||||||
|
pos_inv.load_from_db()
|
||||||
|
rounded_total = frappe.db.get_value("Sales Invoice", pos_inv.consolidated_invoice, "rounded_total")
|
||||||
|
self.assertEqual(rounded_total, 3470)
|
||||||
|
frappe.set_user("Administrator")
|
||||||
|
|
||||||
|
def test_merging_into_sales_invoice_with_discount_and_inclusive_tax(self):
|
||||||
|
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
|
||||||
|
from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import merge_pos_invoices
|
||||||
|
|
||||||
|
frappe.db.sql("delete from `tabPOS Invoice`")
|
||||||
|
test_user, pos_profile = init_user_and_profile()
|
||||||
|
pos_inv = create_pos_invoice(rate=300, do_not_submit=1)
|
||||||
|
pos_inv.append('payments', {
|
||||||
|
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300
|
||||||
|
})
|
||||||
|
pos_inv.append('taxes', {
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "_Test Account Service Tax - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Service Tax",
|
||||||
|
"rate": 14,
|
||||||
|
'included_in_print_rate': 1
|
||||||
|
})
|
||||||
|
pos_inv.submit()
|
||||||
|
|
||||||
|
pos_inv2 = create_pos_invoice(rate=300, qty=2, do_not_submit=1)
|
||||||
|
pos_inv2.additional_discount_percentage = 10
|
||||||
|
pos_inv2.append('payments', {
|
||||||
|
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 540
|
||||||
|
})
|
||||||
|
pos_inv2.append('taxes', {
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "_Test Account Service Tax - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Service Tax",
|
||||||
|
"rate": 14,
|
||||||
|
'included_in_print_rate': 1
|
||||||
|
})
|
||||||
|
pos_inv2.submit()
|
||||||
|
|
||||||
|
merge_pos_invoices()
|
||||||
|
|
||||||
|
pos_inv.load_from_db()
|
||||||
|
rounded_total = frappe.db.get_value("Sales Invoice", pos_inv.consolidated_invoice, "rounded_total")
|
||||||
|
self.assertEqual(rounded_total, 840)
|
||||||
|
frappe.set_user("Administrator")
|
||||||
|
|
||||||
|
def test_merging_with_validate_selling_price(self):
|
||||||
|
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
|
||||||
|
from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import merge_pos_invoices
|
||||||
|
|
||||||
|
if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"):
|
||||||
|
frappe.db.set_value("Selling Settings", "Selling Settings", "validate_selling_price", 1)
|
||||||
|
|
||||||
|
make_purchase_receipt(item_code="_Test Item", warehouse="_Test Warehouse - _TC", qty=1, rate=300)
|
||||||
|
frappe.db.sql("delete from `tabPOS Invoice`")
|
||||||
|
test_user, pos_profile = init_user_and_profile()
|
||||||
|
pos_inv = create_pos_invoice(rate=300, do_not_submit=1)
|
||||||
|
pos_inv.append('payments', {
|
||||||
|
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300
|
||||||
|
})
|
||||||
|
pos_inv.append('taxes', {
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "_Test Account Service Tax - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Service Tax",
|
||||||
|
"rate": 14,
|
||||||
|
'included_in_print_rate': 1
|
||||||
|
})
|
||||||
|
self.assertRaises(frappe.ValidationError, pos_inv.submit)
|
||||||
|
|
||||||
|
pos_inv2 = create_pos_invoice(rate=400, do_not_submit=1)
|
||||||
|
pos_inv2.append('payments', {
|
||||||
|
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 400
|
||||||
|
})
|
||||||
|
pos_inv2.append('taxes', {
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "_Test Account Service Tax - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Service Tax",
|
||||||
|
"rate": 14,
|
||||||
|
'included_in_print_rate': 1
|
||||||
|
})
|
||||||
|
pos_inv2.submit()
|
||||||
|
|
||||||
|
merge_pos_invoices()
|
||||||
|
|
||||||
|
pos_inv2.load_from_db()
|
||||||
|
rounded_total = frappe.db.get_value("Sales Invoice", pos_inv2.consolidated_invoice, "rounded_total")
|
||||||
|
self.assertEqual(rounded_total, 400)
|
||||||
|
frappe.set_user("Administrator")
|
||||||
|
frappe.db.set_value("Selling Settings", "Selling Settings", "validate_selling_price", 0)
|
||||||
|
|
||||||
def create_pos_invoice(**args):
|
def create_pos_invoice(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
pos_profile = None
|
pos_profile = None
|
||||||
@ -294,12 +409,11 @@ def create_pos_invoice(**args):
|
|||||||
pos_profile.save()
|
pos_profile.save()
|
||||||
|
|
||||||
pos_inv = frappe.new_doc("POS Invoice")
|
pos_inv = frappe.new_doc("POS Invoice")
|
||||||
|
pos_inv.update(args)
|
||||||
pos_inv.update_stock = 1
|
pos_inv.update_stock = 1
|
||||||
pos_inv.is_pos = 1
|
pos_inv.is_pos = 1
|
||||||
pos_inv.pos_profile = args.pos_profile or pos_profile.name
|
pos_inv.pos_profile = args.pos_profile or pos_profile.name
|
||||||
|
|
||||||
pos_inv.set_missing_values()
|
|
||||||
|
|
||||||
if args.posting_date:
|
if args.posting_date:
|
||||||
pos_inv.set_posting_time = 1
|
pos_inv.set_posting_time = 1
|
||||||
pos_inv.posting_date = args.posting_date or frappe.utils.nowdate()
|
pos_inv.posting_date = args.posting_date or frappe.utils.nowdate()
|
||||||
@ -313,6 +427,8 @@ def create_pos_invoice(**args):
|
|||||||
pos_inv.conversion_rate = args.conversion_rate or 1
|
pos_inv.conversion_rate = args.conversion_rate or 1
|
||||||
pos_inv.account_for_change_amount = args.account_for_change_amount or "Cash - _TC"
|
pos_inv.account_for_change_amount = args.account_for_change_amount or "Cash - _TC"
|
||||||
|
|
||||||
|
pos_inv.set_missing_values()
|
||||||
|
|
||||||
pos_inv.append("items", {
|
pos_inv.append("items", {
|
||||||
"item_code": args.item or args.item_code or "_Test Item",
|
"item_code": args.item or args.item_code or "_Test Item",
|
||||||
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
||||||
|
@ -96,17 +96,28 @@ class POSInvoiceMergeLog(Document):
|
|||||||
loyalty_amount_sum += doc.loyalty_amount
|
loyalty_amount_sum += doc.loyalty_amount
|
||||||
|
|
||||||
for item in doc.get('items'):
|
for item in doc.get('items'):
|
||||||
|
found = False
|
||||||
|
for i in items:
|
||||||
|
if (i.item_code == item.item_code and not i.serial_no and not i.batch_no and
|
||||||
|
i.uom == item.uom and i.net_rate == item.net_rate):
|
||||||
|
found = True
|
||||||
|
i.qty = i.qty + item.qty
|
||||||
|
if not found:
|
||||||
|
item.rate = item.net_rate
|
||||||
items.append(item)
|
items.append(item)
|
||||||
|
|
||||||
for tax in doc.get('taxes'):
|
for tax in doc.get('taxes'):
|
||||||
found = False
|
found = False
|
||||||
for t in taxes:
|
for t in taxes:
|
||||||
if t.account_head == tax.account_head and t.cost_center == tax.cost_center and t.rate == tax.rate:
|
if t.account_head == tax.account_head and t.cost_center == tax.cost_center:
|
||||||
t.tax_amount = flt(t.tax_amount) + flt(tax.tax_amount)
|
t.tax_amount = flt(t.tax_amount) + flt(tax.tax_amount_after_discount_amount)
|
||||||
t.base_tax_amount = flt(t.base_tax_amount) + flt(tax.base_tax_amount)
|
t.base_tax_amount = flt(t.base_tax_amount) + flt(tax.base_tax_amount_after_discount_amount)
|
||||||
found = True
|
found = True
|
||||||
if not found:
|
if not found:
|
||||||
tax.charge_type = 'Actual'
|
tax.charge_type = 'Actual'
|
||||||
|
tax.included_in_print_rate = 0
|
||||||
|
tax.tax_amount = tax.tax_amount_after_discount_amount
|
||||||
|
tax.base_tax_amount = tax.base_tax_amount_after_discount_amount
|
||||||
taxes.append(tax)
|
taxes.append(tax)
|
||||||
|
|
||||||
for payment in doc.get('payments'):
|
for payment in doc.get('payments'):
|
||||||
@ -127,6 +138,8 @@ class POSInvoiceMergeLog(Document):
|
|||||||
invoice.set('items', items)
|
invoice.set('items', items)
|
||||||
invoice.set('payments', payments)
|
invoice.set('payments', payments)
|
||||||
invoice.set('taxes', taxes)
|
invoice.set('taxes', taxes)
|
||||||
|
invoice.additional_discount_percentage = 0
|
||||||
|
invoice.discount_amount = 0.0
|
||||||
|
|
||||||
return invoice
|
return invoice
|
||||||
|
|
||||||
|
@ -15,15 +15,6 @@ frappe.ui.form.on("POS Profile", "onload", function(frm) {
|
|||||||
erpnext.queries.setup_queries(frm, "Warehouse", function() {
|
erpnext.queries.setup_queries(frm, "Warehouse", function() {
|
||||||
return erpnext.queries.warehouse(frm.doc);
|
return erpnext.queries.warehouse(frm.doc);
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.call({
|
|
||||||
method: "erpnext.accounts.doctype.pos_profile.pos_profile.get_series",
|
|
||||||
callback: function(r) {
|
|
||||||
if(!r.exc) {
|
|
||||||
set_field_options("naming_series", r.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on('POS Profile', {
|
frappe.ui.form.on('POS Profile', {
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
"field_order": [
|
"field_order": [
|
||||||
"disabled",
|
"disabled",
|
||||||
"section_break_2",
|
"section_break_2",
|
||||||
"naming_series",
|
|
||||||
"customer",
|
"customer",
|
||||||
"company",
|
"company",
|
||||||
"country",
|
"country",
|
||||||
@ -59,17 +58,6 @@
|
|||||||
"fieldname": "section_break_2",
|
"fieldname": "section_break_2",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "naming_series",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Series",
|
|
||||||
"no_copy": 1,
|
|
||||||
"oldfieldname": "naming_series",
|
|
||||||
"oldfieldtype": "Select",
|
|
||||||
"options": "[Select]",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "customer",
|
"fieldname": "customer",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@ -323,7 +311,7 @@
|
|||||||
"icon": "icon-cog",
|
"icon": "icon-cog",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-06-29 12:20:30.977272",
|
"modified": "2020-10-01 17:29:27.759088",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "POS Profile",
|
"name": "POS Profile",
|
||||||
|
@ -109,10 +109,6 @@ def get_child_nodes(group_type, root):
|
|||||||
return frappe.db.sql(""" Select name, lft, rgt from `tab{tab}` where
|
return frappe.db.sql(""" Select name, lft, rgt from `tab{tab}` where
|
||||||
lft >= {lft} and rgt <= {rgt} order by lft""".format(tab=group_type, lft=lft, rgt=rgt), as_dict=1)
|
lft >= {lft} and rgt <= {rgt} order by lft""".format(tab=group_type, lft=lft, rgt=rgt), as_dict=1)
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def get_series():
|
|
||||||
return frappe.get_meta("POS Invoice").get_field("naming_series").options or "s"
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@frappe.validate_and_sanitize_search_inputs
|
@frappe.validate_and_sanitize_search_inputs
|
||||||
def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):
|
def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"autoname": "field:title",
|
"autoname": "field:title",
|
||||||
@ -71,6 +72,7 @@
|
|||||||
"section_break_13",
|
"section_break_13",
|
||||||
"threshold_percentage",
|
"threshold_percentage",
|
||||||
"priority",
|
"priority",
|
||||||
|
"condition",
|
||||||
"column_break_66",
|
"column_break_66",
|
||||||
"apply_multiple_pricing_rules",
|
"apply_multiple_pricing_rules",
|
||||||
"apply_discount_on_rate",
|
"apply_discount_on_rate",
|
||||||
@ -550,11 +552,18 @@
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Promotional Scheme",
|
"label": "Promotional Scheme",
|
||||||
"options": "Promotional Scheme"
|
"options": "Promotional Scheme"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Simple Python Expression, Example: territory != 'All Territories'",
|
||||||
|
"fieldname": "condition",
|
||||||
|
"fieldtype": "Code",
|
||||||
|
"label": "Condition"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-gift",
|
"icon": "fa fa-gift",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2019-12-18 17:29:22.957077",
|
"links": [],
|
||||||
|
"modified": "2020-08-26 12:24:44.740734",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Pricing Rule",
|
"name": "Pricing Rule",
|
||||||
|
@ -6,9 +6,10 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
import json
|
import json
|
||||||
import copy
|
import copy
|
||||||
|
import re
|
||||||
|
|
||||||
from frappe import throw, _
|
from frappe import throw, _
|
||||||
from frappe.utils import flt, cint, getdate
|
from frappe.utils import flt, cint, getdate
|
||||||
|
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
from six import string_types
|
from six import string_types
|
||||||
@ -30,6 +31,7 @@ class PricingRule(Document):
|
|||||||
self.validate_max_discount()
|
self.validate_max_discount()
|
||||||
self.validate_price_list_with_currency()
|
self.validate_price_list_with_currency()
|
||||||
self.validate_dates()
|
self.validate_dates()
|
||||||
|
self.validate_condition()
|
||||||
|
|
||||||
if not self.margin_type: self.margin_rate_or_amount = 0.0
|
if not self.margin_type: self.margin_rate_or_amount = 0.0
|
||||||
|
|
||||||
@ -140,6 +142,10 @@ class PricingRule(Document):
|
|||||||
if self.valid_from and self.valid_upto and getdate(self.valid_from) > getdate(self.valid_upto):
|
if self.valid_from and self.valid_upto and getdate(self.valid_from) > getdate(self.valid_upto):
|
||||||
frappe.throw(_("Valid from date must be less than valid upto date"))
|
frappe.throw(_("Valid from date must be less than valid upto date"))
|
||||||
|
|
||||||
|
def validate_condition(self):
|
||||||
|
if self.condition and ("=" in self.condition) and re.match("""[\w\.:_]+\s*={1}\s*[\w\.@'"]+""", self.condition):
|
||||||
|
frappe.throw(_("Invalid condition expression"))
|
||||||
|
|
||||||
#--------------------------------------------------------------------------------
|
#--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
@ -430,6 +430,33 @@ class TestPricingRule(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertTrue(details)
|
self.assertTrue(details)
|
||||||
|
|
||||||
|
def test_pricing_rule_for_condition(self):
|
||||||
|
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule")
|
||||||
|
|
||||||
|
make_pricing_rule(selling=1, margin_type="Percentage", \
|
||||||
|
condition="customer=='_Test Customer 1' and is_return==0", discount_percentage=10)
|
||||||
|
|
||||||
|
# Incorrect Customer and Correct is_return value
|
||||||
|
si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 2", is_return=0)
|
||||||
|
si.items[0].price_list_rate = 1000
|
||||||
|
si.submit()
|
||||||
|
item = si.items[0]
|
||||||
|
self.assertEquals(item.rate, 100)
|
||||||
|
|
||||||
|
# Correct Customer and Incorrect is_return value
|
||||||
|
si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 1", is_return=1, qty=-1)
|
||||||
|
si.items[0].price_list_rate = 1000
|
||||||
|
si.submit()
|
||||||
|
item = si.items[0]
|
||||||
|
self.assertEquals(item.rate, 100)
|
||||||
|
|
||||||
|
# Correct Customer and correct is_return value
|
||||||
|
si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 1", is_return=0)
|
||||||
|
si.items[0].price_list_rate = 1000
|
||||||
|
si.submit()
|
||||||
|
item = si.items[0]
|
||||||
|
self.assertEquals(item.rate, 900)
|
||||||
|
|
||||||
def make_pricing_rule(**args):
|
def make_pricing_rule(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|
||||||
@ -448,7 +475,8 @@ def make_pricing_rule(**args):
|
|||||||
"discount_percentage": args.discount_percentage or 0.0,
|
"discount_percentage": args.discount_percentage or 0.0,
|
||||||
"rate": args.rate or 0.0,
|
"rate": args.rate or 0.0,
|
||||||
"margin_type": args.margin_type,
|
"margin_type": args.margin_type,
|
||||||
"margin_rate_or_amount": args.margin_rate_or_amount or 0.0
|
"margin_rate_or_amount": args.margin_rate_or_amount or 0.0,
|
||||||
|
"condition": args.condition or ''
|
||||||
})
|
})
|
||||||
|
|
||||||
apply_on = doc.apply_on.replace(' ', '_').lower()
|
apply_on = doc.apply_on.replace(' ', '_').lower()
|
||||||
|
@ -37,6 +37,8 @@ def get_pricing_rules(args, doc=None):
|
|||||||
|
|
||||||
rules = []
|
rules = []
|
||||||
|
|
||||||
|
pricing_rules = filter_pricing_rule_based_on_condition(pricing_rules, doc)
|
||||||
|
|
||||||
if not pricing_rules: return []
|
if not pricing_rules: return []
|
||||||
|
|
||||||
if apply_multiple_pricing_rules(pricing_rules):
|
if apply_multiple_pricing_rules(pricing_rules):
|
||||||
@ -51,6 +53,23 @@ def get_pricing_rules(args, doc=None):
|
|||||||
|
|
||||||
return rules
|
return rules
|
||||||
|
|
||||||
|
def filter_pricing_rule_based_on_condition(pricing_rules, doc=None):
|
||||||
|
filtered_pricing_rules = []
|
||||||
|
if doc:
|
||||||
|
for pricing_rule in pricing_rules:
|
||||||
|
if pricing_rule.condition:
|
||||||
|
try:
|
||||||
|
if frappe.safe_eval(pricing_rule.condition, None, doc.as_dict()):
|
||||||
|
filtered_pricing_rules.append(pricing_rule)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
filtered_pricing_rules.append(pricing_rule)
|
||||||
|
else:
|
||||||
|
filtered_pricing_rules = pricing_rules
|
||||||
|
|
||||||
|
return filtered_pricing_rules
|
||||||
|
|
||||||
def _get_pricing_rules(apply_on, args, values):
|
def _get_pricing_rules(apply_on, args, values):
|
||||||
apply_on_field = frappe.scrub(apply_on)
|
apply_on_field = frappe.scrub(apply_on)
|
||||||
|
|
||||||
|
@ -711,7 +711,8 @@ class PurchaseInvoice(BuyingController):
|
|||||||
item.item_tax_amount / self.conversion_rate)
|
item.item_tax_amount / self.conversion_rate)
|
||||||
}, item=item))
|
}, item=item))
|
||||||
else:
|
else:
|
||||||
cwip_account = get_asset_account("capital_work_in_progress_account", company = self.company)
|
cwip_account = get_asset_account("capital_work_in_progress_account",
|
||||||
|
asset_category=item.asset_category,company=self.company)
|
||||||
|
|
||||||
cwip_account_currency = get_account_currency(cwip_account)
|
cwip_account_currency = get_account_currency(cwip_account)
|
||||||
gl_entries.append(self.get_gl_dict({
|
gl_entries.append(self.get_gl_dict({
|
||||||
|
@ -1002,7 +1002,8 @@ def make_purchase_invoice(**args):
|
|||||||
"cost_center": args.cost_center or "_Test Cost Center - _TC",
|
"cost_center": args.cost_center or "_Test Cost Center - _TC",
|
||||||
"project": args.project,
|
"project": args.project,
|
||||||
"rejected_warehouse": args.rejected_warehouse or "",
|
"rejected_warehouse": args.rejected_warehouse or "",
|
||||||
"rejected_serial_no": args.rejected_serial_no or ""
|
"rejected_serial_no": args.rejected_serial_no or "",
|
||||||
|
"asset_location": args.location or ""
|
||||||
})
|
})
|
||||||
|
|
||||||
if args.get_taxes_and_charges:
|
if args.get_taxes_and_charges:
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
"is_return",
|
"is_return",
|
||||||
"column_break1",
|
"column_break1",
|
||||||
"company",
|
"company",
|
||||||
|
"company_tax_id",
|
||||||
"posting_date",
|
"posting_date",
|
||||||
"posting_time",
|
"posting_time",
|
||||||
"set_posting_time",
|
"set_posting_time",
|
||||||
@ -1825,7 +1826,7 @@
|
|||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"hide_days": 1,
|
"hide_days": 1,
|
||||||
"hide_seconds": 1,
|
"hide_seconds": 1,
|
||||||
"label": "Sales Team1",
|
"label": "Sales Contributions and Incentives",
|
||||||
"oldfieldname": "sales_team",
|
"oldfieldname": "sales_team",
|
||||||
"oldfieldtype": "Table",
|
"oldfieldtype": "Table",
|
||||||
"options": "Sales Team",
|
"options": "Sales Team",
|
||||||
@ -1926,6 +1927,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
|
"depends_on": "eval:(doc.is_pos && doc.is_consolidated)",
|
||||||
"fieldname": "is_consolidated",
|
"fieldname": "is_consolidated",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Is Consolidated",
|
"label": "Is Consolidated",
|
||||||
@ -1940,13 +1942,20 @@
|
|||||||
"hide_seconds": 1,
|
"hide_seconds": 1,
|
||||||
"label": "Is Internal Customer",
|
"label": "Is Internal Customer",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "company.tax_id",
|
||||||
|
"fieldname": "company_tax_id",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Company Tax ID",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 181,
|
"idx": 181,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-08-27 01:56:28.532140",
|
"modified": "2020-10-09 15:59:57.544736",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice",
|
"name": "Sales Invoice",
|
||||||
|
@ -428,7 +428,7 @@ class SalesInvoice(SellingController):
|
|||||||
if pos.get('account_for_change_amount'):
|
if pos.get('account_for_change_amount'):
|
||||||
self.account_for_change_amount = pos.get('account_for_change_amount')
|
self.account_for_change_amount = pos.get('account_for_change_amount')
|
||||||
|
|
||||||
for fieldname in ('naming_series', 'currency', 'letter_head', 'tc_name',
|
for fieldname in ('currency', 'letter_head', 'tc_name',
|
||||||
'company', 'select_print_heading', 'write_off_account', 'taxes_and_charges',
|
'company', 'select_print_heading', 'write_off_account', 'taxes_and_charges',
|
||||||
'write_off_cost_center', 'apply_discount_on', 'cost_center'):
|
'write_off_cost_center', 'apply_discount_on', 'cost_center'):
|
||||||
if (not for_validate) or (for_validate and not self.get(fieldname)):
|
if (not for_validate) or (for_validate and not self.get(fieldname)):
|
||||||
|
@ -13,8 +13,7 @@ def get_data():
|
|||||||
'Auto Repeat': 'reference_document',
|
'Auto Repeat': 'reference_document',
|
||||||
},
|
},
|
||||||
'internal_links': {
|
'internal_links': {
|
||||||
'Sales Order': ['items', 'sales_order'],
|
'Sales Order': ['items', 'sales_order']
|
||||||
'Delivery Note': ['items', 'delivery_note']
|
|
||||||
},
|
},
|
||||||
'transactions': [
|
'transactions': [
|
||||||
{
|
{
|
||||||
|
@ -345,6 +345,7 @@ class Subscription(Document):
|
|||||||
invoice.set_taxes()
|
invoice.set_taxes()
|
||||||
|
|
||||||
# Due date
|
# Due date
|
||||||
|
if self.days_until_due:
|
||||||
invoice.append(
|
invoice.append(
|
||||||
'payment_schedule',
|
'payment_schedule',
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,8 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
import unittest
|
import unittest
|
||||||
from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup, IncorrectSupplierType, ConflictingTaxRule, get_tax_template
|
from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup, IncorrectSupplierType, ConflictingTaxRule, get_tax_template
|
||||||
|
from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity
|
||||||
|
from erpnext.crm.doctype.opportunity.opportunity import make_quotation
|
||||||
|
|
||||||
test_records = frappe.get_test_records('Tax Rule')
|
test_records = frappe.get_test_records('Tax Rule')
|
||||||
|
|
||||||
@ -144,6 +146,23 @@ class TestTaxRule(unittest.TestCase):
|
|||||||
self.assertEqual(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
|
self.assertEqual(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
|
||||||
"_Test Sales Taxes and Charges Template 1 - _TC")
|
"_Test Sales Taxes and Charges Template 1 - _TC")
|
||||||
|
|
||||||
|
def test_taxes_fetch_via_tax_rule(self):
|
||||||
|
make_tax_rule(customer= "_Test Customer", billing_city = "_Test City",
|
||||||
|
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)
|
||||||
|
|
||||||
|
# create opportunity for customer
|
||||||
|
opportunity = make_opportunity(with_items=1)
|
||||||
|
|
||||||
|
# make quotation from opportunity
|
||||||
|
quotation = make_quotation(opportunity.name)
|
||||||
|
quotation.save()
|
||||||
|
|
||||||
|
self.assertEqual(quotation.taxes_and_charges, "_Test Sales Taxes and Charges Template - _TC")
|
||||||
|
|
||||||
|
# Check if accounts heads and rate fetched are also fetched from tax template or not
|
||||||
|
self.assertTrue(len(quotation.taxes) > 0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def make_tax_rule(**args):
|
def make_tax_rule(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
@ -106,6 +106,7 @@ def get_tds_amount(suppliers, net_total, company, tax_details, fiscal_year_detai
|
|||||||
from `tabGL Entry`
|
from `tabGL Entry`
|
||||||
where company = %s and
|
where company = %s and
|
||||||
party in %s and fiscal_year=%s and credit > 0
|
party in %s and fiscal_year=%s and credit > 0
|
||||||
|
and is_opening = 'No'
|
||||||
""", (company, tuple(suppliers), fiscal_year), as_dict=1)
|
""", (company, tuple(suppliers), fiscal_year), as_dict=1)
|
||||||
|
|
||||||
vouchers = [d.voucher_no for d in entries]
|
vouchers = [d.voucher_no for d in entries]
|
||||||
@ -192,6 +193,7 @@ def get_advance_vouchers(suppliers, fiscal_year=None, company=None, from_date=No
|
|||||||
select distinct voucher_no
|
select distinct voucher_no
|
||||||
from `tabGL Entry`
|
from `tabGL Entry`
|
||||||
where party in %s and %s and debit > 0
|
where party in %s and %s and debit > 0
|
||||||
|
and is_opening = 'No'
|
||||||
""", (tuple(suppliers), condition)) or []
|
""", (tuple(suppliers), condition)) or []
|
||||||
|
|
||||||
def get_debit_note_amount(suppliers, year_start_date, year_end_date, company=None):
|
def get_debit_note_amount(suppliers, year_start_date, year_end_date, company=None):
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/accounts",
|
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/accounts",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_complete": 0,
|
"is_complete": 0,
|
||||||
"modified": "2020-07-08 14:06:09.033880",
|
"modified": "2020-10-15 13:52:40.068450",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounts",
|
"name": "Accounts",
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
{
|
{
|
||||||
"action": "Go to Page",
|
"action": "Go to Page",
|
||||||
|
"callback_message": "Great! Let's move to the next step!",
|
||||||
|
"callback_title": "Awesome Work",
|
||||||
"creation": "2020-05-13 19:58:20.928127",
|
"creation": "2020-05-13 19:58:20.928127",
|
||||||
|
"description": "# Chart Of Accounts\n\n**The Chart of Accounts is the blueprint of the accounts in your organization.**\n\nThe overall structure of your Chart of Accounts is based on a system of double entry\naccounting that has become a standard all over the world to quantify how a\ncompany is doing financially.\n\nChart of Accounts is a tree view of the names of the Accounts (Ledgers and\nGroups) that a Company requires to manage its books of accounts. ERPNext sets\nup a simple chart of accounts for each Company you create, but you can\nmodify it according to your needs and legal requirements.\n\nFor each company, Chart of Accounts signifies the way to classify the accounting entries, mostly\nbased on statutory (tax, compliance to government regulations) requirements.\n\nThe Chart of Accounts helps you to answer questions like:\n\n * What is your organization worth?\n * How much debt have you taken?\n * How much profit are you making (and hence paying tax)?\n * How much are you selling?\n * What is your expense break-up?\n",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Onboarding Step",
|
"doctype": "Onboarding Step",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
|
"intro_video_url": "https://www.youtube.com/embed/AcfMCT7wLLo",
|
||||||
"is_complete": 0,
|
"is_complete": 0,
|
||||||
"is_mandatory": 0,
|
"is_mandatory": 0,
|
||||||
"is_single": 0,
|
"is_single": 0,
|
||||||
"is_skipped": 0,
|
"is_skipped": 0,
|
||||||
"modified": "2020-05-14 17:40:28.410447",
|
"modified": "2020-10-15 13:12:04.771355",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"name": "Chart Of Accounts",
|
"name": "Chart Of Accounts",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"action": "Create Entry",
|
"action": "Create Entry",
|
||||||
"creation": "2020-05-14 17:53:00.876946",
|
"creation": "2020-05-14 17:53:00.876946",
|
||||||
|
"description": "# Account Settings\n\nThis is a crucial piece of configuration. There are various account settings in ERPNext to restrict and configure actions in the Accounting module.\n\nThe following settings are avaialble for you to configure\n\n1. Account Freezing \n2. Credit and Overbilling\n3. Invoicing and Tax Automations\n4. Balance Sheet configurations\n\nThere's much more, you can check it all out in this step",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Onboarding Step",
|
"doctype": "Onboarding Step",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
@ -8,7 +9,7 @@
|
|||||||
"is_mandatory": 0,
|
"is_mandatory": 0,
|
||||||
"is_single": 1,
|
"is_single": 1,
|
||||||
"is_skipped": 0,
|
"is_skipped": 0,
|
||||||
"modified": "2020-05-14 18:06:25.212923",
|
"modified": "2020-10-15 13:45:14.687458",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"name": "Configure Account Settings",
|
"name": "Configure Account Settings",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
{
|
{
|
||||||
"action": "Create Entry",
|
"action": "Create Entry",
|
||||||
"creation": "2020-05-14 17:46:41.831517",
|
"creation": "2020-05-14 17:46:41.831517",
|
||||||
|
"description": "# Customer\n\nA customer, who is sometimes known as a client, buyer, or purchaser is the one who receives goods, services, products, or ideas, from a seller for a monetary consideration.\n\n### Creating a customer is easy and can be done in the following steps\n\n1. Go to the Customer list and click on New.\n2. Enter Full Name of the customer.\n3. Select **Company** if the customer represents a company or **Individual** otherwise in Type field.\n4. Select a Customer Group. A few groups are included by default, you can create additional groups if you need.\n5. Select the Territory.\n6. If the customer is being created against a lead, you can select the same in From Lead field.\n7. Save.\n\nUp next is a video about customers and suppliers that will give you more clarity on these concepts in ERPNext",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Onboarding Step",
|
"doctype": "Onboarding Step",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
|
"intro_video_url": "https://www.youtube.com/watch?v=zsrrVDk6VBs",
|
||||||
"is_complete": 0,
|
"is_complete": 0,
|
||||||
"is_mandatory": 0,
|
"is_mandatory": 0,
|
||||||
"is_single": 0,
|
"is_single": 0,
|
||||||
"is_skipped": 0,
|
"is_skipped": 0,
|
||||||
"modified": "2020-06-01 13:16:19.731719",
|
"modified": "2020-10-15 13:37:59.699228",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"name": "Create a Customer",
|
"name": "Create a Customer",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"action": "Create Entry",
|
"action": "Create Entry",
|
||||||
"creation": "2020-05-12 18:16:06.624554",
|
"creation": "2020-05-12 18:16:06.624554",
|
||||||
|
"description": "## Creating Products\n\nIn ERPNext, any product or a service offered by your company is called an Item. The term Item is also applicable to raw materials or components of products yet to be produced (before they can be sold to customers). ERPNext allows you to manage all sorts of items like raw-materials, sub-assemblies, finished goods, item variants, and service items.\n\nERPNext is optimized for itemized management of your sales and purchase. If you are in services, you can create an Item for each service that you offer. Completing the Item Master is very essential for the successful implementation of ERPNext.\n\nYou can access the Item section\n\n`Desk > Stock > Item`\n\n\n",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Onboarding Step",
|
"doctype": "Onboarding Step",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
@ -8,7 +9,7 @@
|
|||||||
"is_mandatory": 0,
|
"is_mandatory": 0,
|
||||||
"is_single": 0,
|
"is_single": 0,
|
||||||
"is_skipped": 0,
|
"is_skipped": 0,
|
||||||
"modified": "2020-05-12 18:30:02.489949",
|
"modified": "2020-10-15 13:30:46.817174",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"name": "Create a Product",
|
"name": "Create a Product",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"action": "Create Entry",
|
"action": "Create Entry",
|
||||||
"creation": "2020-05-14 22:09:10.043554",
|
"creation": "2020-05-14 22:09:10.043554",
|
||||||
|
"description": "## Let's add your Suppliers\n\nSuppliers are companies or individuals who provide you with products or services. A supplier may be distinguished from a contractor or subcontractor, who commonly adds specialized input to deliverables. A supplier is also known as a vendor. There are different types of suppliers based on the goods and products they supply.\n\nERPNext allows you to create your own categories of suppliers. These categories are known as Supplier Groups. For example, if your suppliers are mainly pharmaceutical companies and FMCG distributors, you can create a new Supplier Groups for them and name the groups accordingly.",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Onboarding Step",
|
"doctype": "Onboarding Step",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
@ -8,7 +9,7 @@
|
|||||||
"is_mandatory": 0,
|
"is_mandatory": 0,
|
||||||
"is_single": 0,
|
"is_single": 0,
|
||||||
"is_skipped": 0,
|
"is_skipped": 0,
|
||||||
"modified": "2020-05-14 22:09:10.043554",
|
"modified": "2020-10-15 13:32:39.651700",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"name": "Create a Supplier",
|
"name": "Create a Supplier",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"action": "Create Entry",
|
"action": "Create Entry",
|
||||||
"creation": "2020-05-14 22:10:07.049704",
|
"creation": "2020-05-14 22:10:07.049704",
|
||||||
|
"description": "# What's a Purchase Invoice?\n\nA Purchase Invoice is a bill you receive from your Suppliers against which you need to make the payment.\nPurchase Invoice is the exact opposite of your Sales Invoice. Here you accrue expenses to your Supplier. Making a Purchase Invoice is very similar to making a Purchase Order.\n\n\n\n",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Onboarding Step",
|
"doctype": "Onboarding Step",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
@ -8,7 +9,7 @@
|
|||||||
"is_mandatory": 0,
|
"is_mandatory": 0,
|
||||||
"is_single": 0,
|
"is_single": 0,
|
||||||
"is_skipped": 0,
|
"is_skipped": 0,
|
||||||
"modified": "2020-05-14 22:10:07.049704",
|
"modified": "2020-10-15 13:33:56.079882",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"name": "Create Your First Purchase Invoice",
|
"name": "Create Your First Purchase Invoice",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"action": "Create Entry",
|
"action": "Create Entry",
|
||||||
"creation": "2020-05-14 17:48:21.019019",
|
"creation": "2020-05-14 17:48:21.019019",
|
||||||
|
"description": "# All about sales invoice\n\nA Sales Invoice is a bill that you send to your Customers against which the Customer makes the payment. Sales Invoice is an accounting transaction. On submission of Sales Invoice, the system updates the receivable and books income against a Customer Account.\n\nHere's the flow of how a sales invoice is generally created\n\n\n",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Onboarding Step",
|
"doctype": "Onboarding Step",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
@ -8,7 +9,7 @@
|
|||||||
"is_mandatory": 0,
|
"is_mandatory": 0,
|
||||||
"is_single": 0,
|
"is_single": 0,
|
||||||
"is_skipped": 0,
|
"is_skipped": 0,
|
||||||
"modified": "2020-05-14 17:48:21.019019",
|
"modified": "2020-10-15 13:39:43.970254",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"name": "Create Your First Sales Invoice",
|
"name": "Create Your First Sales Invoice",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"action": "Create Entry",
|
"action": "Create Entry",
|
||||||
"creation": "2020-05-13 19:29:43.844463",
|
"creation": "2020-05-13 19:29:43.844463",
|
||||||
|
"description": "# Setting up Taxes\n\nOne of the primary motivators for compulsory use of accounting tools is the calculation of taxes. ERPNext allows you to make configurable tax templates that you can apply to your sales or purchase transactions.\n\nThe templates created from this form can be used in Sales Orders and Sales Invoices. The way ERPNext sets up taxes is via templates. Other types of charges that may apply to your invoices (like shipping, insurance etc.) can also be configured as taxes.\n\nFor Tax Accounts that you want to use in the tax templates, go to:\n\n`> Home > Accounting > Chart of Accounts`\n\nSelect an account and click on edit. Select the 'Account Type' as 'Tax' for the account.\nIn this step we will guide you towards making the sales and taxes template.",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Onboarding Step",
|
"doctype": "Onboarding Step",
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
@ -8,7 +9,7 @@
|
|||||||
"is_mandatory": 0,
|
"is_mandatory": 0,
|
||||||
"is_single": 0,
|
"is_single": 0,
|
||||||
"is_skipped": 0,
|
"is_skipped": 0,
|
||||||
"modified": "2020-05-14 17:40:16.014413",
|
"modified": "2020-10-15 13:21:17.333438",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"name": "Setup Taxes",
|
"name": "Setup Taxes",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
@ -3,6 +3,14 @@
|
|||||||
|
|
||||||
frappe.query_reports["Bank Reconciliation Statement"] = {
|
frappe.query_reports["Bank Reconciliation Statement"] = {
|
||||||
"filters": [
|
"filters": [
|
||||||
|
{
|
||||||
|
"fieldname":"company",
|
||||||
|
"label": __("Company"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Company",
|
||||||
|
"reqd": 1,
|
||||||
|
"default": frappe.defaults.get_user_default("Company")
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"account",
|
"fieldname":"account",
|
||||||
"label": __("Bank Account"),
|
"label": __("Bank Account"),
|
||||||
@ -12,11 +20,14 @@ frappe.query_reports["Bank Reconciliation Statement"] = {
|
|||||||
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "",
|
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "",
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"get_query": function() {
|
"get_query": function() {
|
||||||
|
var company = frappe.query_report.get_filter_value('company')
|
||||||
return {
|
return {
|
||||||
"query": "erpnext.controllers.queries.get_account_list",
|
"query": "erpnext.controllers.queries.get_account_list",
|
||||||
"filters": [
|
"filters": [
|
||||||
['Account', 'account_type', 'in', 'Bank, Cash'],
|
['Account', 'account_type', 'in', 'Bank, Cash'],
|
||||||
['Account', 'is_group', '=', 0],
|
['Account', 'is_group', '=', 0],
|
||||||
|
['Account', 'disabled', '=', 0],
|
||||||
|
['Account', 'company', '=', company],
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
76
erpnext/accounts/report/pos_register/pos_register.js
Normal file
76
erpnext/accounts/report/pos_register/pos_register.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
frappe.query_reports["POS Register"] = {
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"fieldname":"company",
|
||||||
|
"label": __("Company"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Company",
|
||||||
|
"default": frappe.defaults.get_user_default("Company"),
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"from_date",
|
||||||
|
"label": __("From Date"),
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
|
||||||
|
"reqd": 1,
|
||||||
|
"width": "60px"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"to_date",
|
||||||
|
"label": __("To Date"),
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"default": frappe.datetime.get_today(),
|
||||||
|
"reqd": 1,
|
||||||
|
"width": "60px"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"pos_profile",
|
||||||
|
"label": __("POS Profile"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "POS Profile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"cashier",
|
||||||
|
"label": __("Cashier"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"customer",
|
||||||
|
"label": __("Customer"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Customer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"mode_of_payment",
|
||||||
|
"label": __("Payment Method"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Mode of Payment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"group_by",
|
||||||
|
"label": __("Group by"),
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"options": ["", "POS Profile", "Cashier", "Payment Method", "Customer"],
|
||||||
|
"default": "POS Profile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"is_return",
|
||||||
|
"label": __("Is Return"),
|
||||||
|
"fieldtype": "Check"
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"formatter": function(value, row, column, data, default_formatter) {
|
||||||
|
value = default_formatter(value, row, column, data);
|
||||||
|
if (data && data.bold) {
|
||||||
|
value = value.bold();
|
||||||
|
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
30
erpnext/accounts/report/pos_register/pos_register.json
Normal file
30
erpnext/accounts/report/pos_register/pos_register.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"columns": [],
|
||||||
|
"creation": "2020-09-10 19:25:03.766871",
|
||||||
|
"disable_prepared_report": 0,
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"filters": [],
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"json": "{}",
|
||||||
|
"modified": "2020-09-10 19:25:15.851331",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "POS Register",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"prepared_report": 0,
|
||||||
|
"ref_doctype": "POS Invoice",
|
||||||
|
"report_name": "POS Register",
|
||||||
|
"report_type": "Script Report",
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"role": "Accounts Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Accounts User"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
222
erpnext/accounts/report/pos_register/pos_register.py
Normal file
222
erpnext/accounts/report/pos_register/pos_register.py
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _, _dict
|
||||||
|
from erpnext import get_company_currency, get_default_company
|
||||||
|
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
if not filters:
|
||||||
|
return [], []
|
||||||
|
|
||||||
|
validate_filters(filters)
|
||||||
|
|
||||||
|
columns = get_columns(filters)
|
||||||
|
|
||||||
|
group_by_field = get_group_by_field(filters.get("group_by"))
|
||||||
|
|
||||||
|
pos_entries = get_pos_entries(filters, group_by_field)
|
||||||
|
if group_by_field != "mode_of_payment":
|
||||||
|
concat_mode_of_payments(pos_entries)
|
||||||
|
|
||||||
|
# return only entries if group by is unselected
|
||||||
|
if not group_by_field:
|
||||||
|
return columns, pos_entries
|
||||||
|
|
||||||
|
# handle grouping
|
||||||
|
invoice_map, grouped_data = {}, []
|
||||||
|
for d in pos_entries:
|
||||||
|
invoice_map.setdefault(d[group_by_field], []).append(d)
|
||||||
|
|
||||||
|
for key in invoice_map:
|
||||||
|
invoices = invoice_map[key]
|
||||||
|
grouped_data += invoices
|
||||||
|
add_subtotal_row(grouped_data, invoices, group_by_field, key)
|
||||||
|
|
||||||
|
# move group by column to first position
|
||||||
|
column_index = next((index for (index, d) in enumerate(columns) if d["fieldname"] == group_by_field), None)
|
||||||
|
columns.insert(0, columns.pop(column_index))
|
||||||
|
|
||||||
|
return columns, grouped_data
|
||||||
|
|
||||||
|
def get_pos_entries(filters, group_by_field):
|
||||||
|
conditions = get_conditions(filters)
|
||||||
|
order_by = "p.posting_date"
|
||||||
|
select_mop_field, from_sales_invoice_payment, group_by_mop_condition = "", "", ""
|
||||||
|
if group_by_field == "mode_of_payment":
|
||||||
|
select_mop_field = ", sip.mode_of_payment"
|
||||||
|
from_sales_invoice_payment = ", `tabSales Invoice Payment` sip"
|
||||||
|
group_by_mop_condition = "sip.parent = p.name AND ifnull(sip.base_amount, 0) != 0 AND"
|
||||||
|
order_by += ", sip.mode_of_payment"
|
||||||
|
|
||||||
|
elif group_by_field:
|
||||||
|
order_by += ", p.{}".format(group_by_field)
|
||||||
|
|
||||||
|
return frappe.db.sql(
|
||||||
|
"""
|
||||||
|
SELECT
|
||||||
|
p.posting_date, p.name as pos_invoice, p.pos_profile,
|
||||||
|
p.owner, p.base_grand_total as grand_total, p.base_paid_amount as paid_amount,
|
||||||
|
p.customer, p.is_return {select_mop_field}
|
||||||
|
FROM
|
||||||
|
`tabPOS Invoice` p {from_sales_invoice_payment}
|
||||||
|
WHERE
|
||||||
|
{group_by_mop_condition}
|
||||||
|
{conditions}
|
||||||
|
ORDER BY
|
||||||
|
{order_by}
|
||||||
|
""".format(
|
||||||
|
select_mop_field=select_mop_field,
|
||||||
|
from_sales_invoice_payment=from_sales_invoice_payment,
|
||||||
|
group_by_mop_condition=group_by_mop_condition,
|
||||||
|
conditions=conditions,
|
||||||
|
order_by=order_by
|
||||||
|
), filters, as_dict=1)
|
||||||
|
|
||||||
|
def concat_mode_of_payments(pos_entries):
|
||||||
|
mode_of_payments = get_mode_of_payments(set([d.pos_invoice for d in pos_entries]))
|
||||||
|
for entry in pos_entries:
|
||||||
|
if mode_of_payments.get(entry.pos_invoice):
|
||||||
|
entry.mode_of_payment = ", ".join(mode_of_payments.get(entry.pos_invoice, []))
|
||||||
|
|
||||||
|
def add_subtotal_row(data, group_invoices, group_by_field, group_by_value):
|
||||||
|
grand_total = sum([d.grand_total for d in group_invoices])
|
||||||
|
paid_amount = sum([d.paid_amount for d in group_invoices])
|
||||||
|
data.append({
|
||||||
|
group_by_field: group_by_value,
|
||||||
|
"grand_total": grand_total,
|
||||||
|
"paid_amount": paid_amount,
|
||||||
|
"bold": 1
|
||||||
|
})
|
||||||
|
data.append({})
|
||||||
|
|
||||||
|
def validate_filters(filters):
|
||||||
|
if not filters.get("company"):
|
||||||
|
frappe.throw(_("{0} is mandatory").format(_("Company")))
|
||||||
|
|
||||||
|
if not filters.get("from_date") and not filters.get("to_date"):
|
||||||
|
frappe.throw(_("{0} and {1} are mandatory").format(frappe.bold(_("From Date")), frappe.bold(_("To Date"))))
|
||||||
|
|
||||||
|
if filters.from_date > filters.to_date:
|
||||||
|
frappe.throw(_("From Date must be before To Date"))
|
||||||
|
|
||||||
|
if (filters.get("pos_profile") and filters.get("group_by") == _('POS Profile')):
|
||||||
|
frappe.throw(_("Can not filter based on POS Profile, if grouped by POS Profile"))
|
||||||
|
|
||||||
|
if (filters.get("customer") and filters.get("group_by") == _('Customer')):
|
||||||
|
frappe.throw(_("Can not filter based on Customer, if grouped by Customer"))
|
||||||
|
|
||||||
|
if (filters.get("owner") and filters.get("group_by") == _('Cashier')):
|
||||||
|
frappe.throw(_("Can not filter based on Cashier, if grouped by Cashier"))
|
||||||
|
|
||||||
|
if (filters.get("mode_of_payment") and filters.get("group_by") == _('Payment Method')):
|
||||||
|
frappe.throw(_("Can not filter based on Payment Method, if grouped by Payment Method"))
|
||||||
|
|
||||||
|
def get_conditions(filters):
|
||||||
|
conditions = "company = %(company)s AND posting_date >= %(from_date)s AND posting_date <= %(to_date)s".format(
|
||||||
|
company=filters.get("company"),
|
||||||
|
from_date=filters.get("from_date"),
|
||||||
|
to_date=filters.get("to_date"))
|
||||||
|
|
||||||
|
if filters.get("pos_profile"):
|
||||||
|
conditions += " AND pos_profile = %(pos_profile)s".format(pos_profile=filters.get("pos_profile"))
|
||||||
|
|
||||||
|
if filters.get("owner"):
|
||||||
|
conditions += " AND owner = %(owner)s".format(owner=filters.get("owner"))
|
||||||
|
|
||||||
|
if filters.get("customer"):
|
||||||
|
conditions += " AND customer = %(customer)s".format(customer=filters.get("customer"))
|
||||||
|
|
||||||
|
if filters.get("is_return"):
|
||||||
|
conditions += " AND is_return = %(is_return)s".format(is_return=filters.get("is_return"))
|
||||||
|
|
||||||
|
if filters.get("mode_of_payment"):
|
||||||
|
conditions += """
|
||||||
|
AND EXISTS(
|
||||||
|
SELECT name FROM `tabSales Invoice Payment` sip
|
||||||
|
WHERE parent=p.name AND ifnull(sip.mode_of_payment, '') = %(mode_of_payment)s
|
||||||
|
)"""
|
||||||
|
|
||||||
|
return conditions
|
||||||
|
|
||||||
|
def get_group_by_field(group_by):
|
||||||
|
group_by_field = ""
|
||||||
|
|
||||||
|
if group_by == "POS Profile":
|
||||||
|
group_by_field = "pos_profile"
|
||||||
|
elif group_by == "Cashier":
|
||||||
|
group_by_field = "owner"
|
||||||
|
elif group_by == "Customer":
|
||||||
|
group_by_field = "customer"
|
||||||
|
elif group_by == "Payment Method":
|
||||||
|
group_by_field = "mode_of_payment"
|
||||||
|
|
||||||
|
return group_by_field
|
||||||
|
|
||||||
|
def get_columns(filters):
|
||||||
|
columns = [
|
||||||
|
{
|
||||||
|
"label": _("Posting Date"),
|
||||||
|
"fieldname": "posting_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"width": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("POS Invoice"),
|
||||||
|
"fieldname": "pos_invoice",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "POS Invoice",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Customer"),
|
||||||
|
"fieldname": "customer",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Customer",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("POS Profile"),
|
||||||
|
"fieldname": "pos_profile",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "POS Profile",
|
||||||
|
"width": 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Cashier"),
|
||||||
|
"fieldname": "owner",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "User",
|
||||||
|
"width": 140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Grand Total"),
|
||||||
|
"fieldname": "grand_total",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"options": "company:currency",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Paid Amount"),
|
||||||
|
"fieldname": "paid_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"options": "company:currency",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Payment Method"),
|
||||||
|
"fieldname": "mode_of_payment",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"width": 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Is Return"),
|
||||||
|
"fieldname": "is_return",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"width": 80
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return columns
|
@ -32,12 +32,12 @@ def execute(filters=None):
|
|||||||
|
|
||||||
chart = get_chart_data(filters, columns, income, expense, net_profit_loss)
|
chart = get_chart_data(filters, columns, income, expense, net_profit_loss)
|
||||||
|
|
||||||
default_currency = frappe.get_cached_value('Company', filters.company, "default_currency")
|
currency = filters.presentation_currency or frappe.get_cached_value('Company', filters.company, "default_currency")
|
||||||
report_summary = get_report_summary(period_list, filters.periodicity, income, expense, net_profit_loss, default_currency)
|
report_summary = get_report_summary(period_list, filters.periodicity, income, expense, net_profit_loss, currency)
|
||||||
|
|
||||||
return columns, data, None, chart, report_summary
|
return columns, data, None, chart, report_summary
|
||||||
|
|
||||||
def get_report_summary(period_list, periodicity, income, expense, net_profit_loss, default_currency, consolidated=False):
|
def get_report_summary(period_list, periodicity, income, expense, net_profit_loss, currency, consolidated=False):
|
||||||
net_income, net_expense, net_profit = 0.0, 0.0, 0.0
|
net_income, net_expense, net_profit = 0.0, 0.0, 0.0
|
||||||
|
|
||||||
for period in period_list:
|
for period in period_list:
|
||||||
@ -63,14 +63,14 @@ def get_report_summary(period_list, periodicity, income, expense, net_profit_los
|
|||||||
"value": net_income,
|
"value": net_income,
|
||||||
"label": income_label,
|
"label": income_label,
|
||||||
"datatype": "Currency",
|
"datatype": "Currency",
|
||||||
"currency": income[-1].get('currency') if income else default_currency
|
"currency": currency
|
||||||
},
|
},
|
||||||
{ "type": "separator", "value": "-"},
|
{ "type": "separator", "value": "-"},
|
||||||
{
|
{
|
||||||
"value": net_expense,
|
"value": net_expense,
|
||||||
"label": expense_label,
|
"label": expense_label,
|
||||||
"datatype": "Currency",
|
"datatype": "Currency",
|
||||||
"currency": expense[-1].get('currency') if expense else default_currency
|
"currency": currency
|
||||||
},
|
},
|
||||||
{ "type": "separator", "value": "=", "color": "blue"},
|
{ "type": "separator", "value": "=", "color": "blue"},
|
||||||
{
|
{
|
||||||
@ -78,7 +78,7 @@ def get_report_summary(period_list, periodicity, income, expense, net_profit_los
|
|||||||
"indicator": "Green" if net_profit > 0 else "Red",
|
"indicator": "Green" if net_profit > 0 else "Red",
|
||||||
"label": profit_label,
|
"label": profit_label,
|
||||||
"datatype": "Currency",
|
"datatype": "Currency",
|
||||||
"currency": net_profit_loss.get("currency") if net_profit_loss else default_currency
|
"currency": currency
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -72,6 +72,12 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Finance Book",
|
"options": "Finance Book",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "presentation_currency",
|
||||||
|
"label": __("Currency"),
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"options": erpnext.get_presentation_currency_list()
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "with_period_closing_entry",
|
"fieldname": "with_period_closing_entry",
|
||||||
"label": __("Period Closing Entry"),
|
"label": __("Period Closing Entry"),
|
||||||
|
@ -56,7 +56,7 @@ def get_data(filters):
|
|||||||
accounts = frappe.db.sql("""select name, account_number, parent_account, account_name, root_type, report_type, lft, rgt
|
accounts = frappe.db.sql("""select name, account_number, parent_account, account_name, root_type, report_type, lft, rgt
|
||||||
|
|
||||||
from `tabAccount` where company=%s order by lft""", filters.company, as_dict=True)
|
from `tabAccount` where company=%s order by lft""", filters.company, as_dict=True)
|
||||||
company_currency = erpnext.get_company_currency(filters.company)
|
company_currency = filters.presentation_currency or erpnext.get_company_currency(filters.company)
|
||||||
|
|
||||||
if not accounts:
|
if not accounts:
|
||||||
return None
|
return None
|
||||||
|
@ -683,6 +683,7 @@ def get_outstanding_invoices(party_type, party, account, condition=None, filters
|
|||||||
where
|
where
|
||||||
party_type = %(party_type)s and party = %(party)s
|
party_type = %(party_type)s and party = %(party)s
|
||||||
and account = %(account)s and {dr_or_cr} > 0
|
and account = %(account)s and {dr_or_cr} > 0
|
||||||
|
and is_cancelled=0
|
||||||
{condition}
|
{condition}
|
||||||
and ((voucher_type = 'Journal Entry'
|
and ((voucher_type = 'Journal Entry'
|
||||||
and (against_voucher = '' or against_voucher is null))
|
and (against_voucher = '' or against_voucher is null))
|
||||||
@ -705,6 +706,7 @@ def get_outstanding_invoices(party_type, party, account, condition=None, filters
|
|||||||
and account = %(account)s
|
and account = %(account)s
|
||||||
and {payment_dr_or_cr} > 0
|
and {payment_dr_or_cr} > 0
|
||||||
and against_voucher is not null and against_voucher != ''
|
and against_voucher is not null and against_voucher != ''
|
||||||
|
and is_cancelled=0
|
||||||
group by against_voucher_type, against_voucher
|
group by against_voucher_type, against_voucher
|
||||||
""".format(payment_dr_or_cr=payment_dr_or_cr), {
|
""".format(payment_dr_or_cr=payment_dr_or_cr), {
|
||||||
"party_type": party_type,
|
"party_type": party_type,
|
||||||
|
@ -466,29 +466,37 @@ class Asset(AccountsController):
|
|||||||
|
|
||||||
def validate_make_gl_entry(self):
|
def validate_make_gl_entry(self):
|
||||||
purchase_document = self.get_purchase_document()
|
purchase_document = self.get_purchase_document()
|
||||||
asset_bought_with_invoice = purchase_document == self.purchase_invoice
|
if not purchase_document:
|
||||||
fixed_asset_account, cwip_account = self.get_asset_accounts()
|
|
||||||
cwip_enabled = is_cwip_accounting_enabled(self.asset_category)
|
|
||||||
# check if expense already has been booked in case of cwip was enabled after purchasing asset
|
|
||||||
expense_booked = False
|
|
||||||
cwip_booked = False
|
|
||||||
|
|
||||||
if asset_bought_with_invoice:
|
|
||||||
expense_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""",
|
|
||||||
(purchase_document, fixed_asset_account), as_dict=1)
|
|
||||||
else:
|
|
||||||
cwip_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""",
|
|
||||||
(purchase_document, cwip_account), as_dict=1)
|
|
||||||
|
|
||||||
if cwip_enabled and (expense_booked or not cwip_booked):
|
|
||||||
# if expense has already booked from invoice or cwip is booked from receipt
|
|
||||||
return False
|
return False
|
||||||
elif not cwip_enabled and (not expense_booked or cwip_booked):
|
|
||||||
# if cwip is disabled but expense hasn't been booked yet
|
asset_bought_with_invoice = (purchase_document == self.purchase_invoice)
|
||||||
return True
|
fixed_asset_account = self.get_fixed_asset_account()
|
||||||
elif cwip_enabled:
|
|
||||||
# default condition
|
cwip_enabled = is_cwip_accounting_enabled(self.asset_category)
|
||||||
|
cwip_account = self.get_cwip_account(cwip_enabled=cwip_enabled)
|
||||||
|
|
||||||
|
query = """SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s"""
|
||||||
|
if asset_bought_with_invoice:
|
||||||
|
# with invoice purchase either expense or cwip has been booked
|
||||||
|
expense_booked = frappe.db.sql(query, (purchase_document, fixed_asset_account), as_dict=1)
|
||||||
|
if expense_booked:
|
||||||
|
# if expense is already booked from invoice then do not make gl entries regardless of cwip enabled/disabled
|
||||||
|
return False
|
||||||
|
|
||||||
|
cwip_booked = frappe.db.sql(query, (purchase_document, cwip_account), as_dict=1)
|
||||||
|
if cwip_booked:
|
||||||
|
# if cwip is booked from invoice then make gl entries regardless of cwip enabled/disabled
|
||||||
return True
|
return True
|
||||||
|
else:
|
||||||
|
# with receipt purchase either cwip has been booked or no entries have been made
|
||||||
|
if not cwip_account:
|
||||||
|
# if cwip account isn't available do not make gl entries
|
||||||
|
return False
|
||||||
|
|
||||||
|
cwip_booked = frappe.db.sql(query, (purchase_document, cwip_account), as_dict=1)
|
||||||
|
# if cwip is not booked from receipt then do not make gl entries
|
||||||
|
# if cwip is booked from receipt then make gl entries
|
||||||
|
return cwip_booked
|
||||||
|
|
||||||
def get_purchase_document(self):
|
def get_purchase_document(self):
|
||||||
asset_bought_with_invoice = self.purchase_invoice and frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')
|
asset_bought_with_invoice = self.purchase_invoice and frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')
|
||||||
@ -496,20 +504,25 @@ class Asset(AccountsController):
|
|||||||
|
|
||||||
return purchase_document
|
return purchase_document
|
||||||
|
|
||||||
def get_asset_accounts(self):
|
def get_fixed_asset_account(self):
|
||||||
fixed_asset_account = get_asset_category_account('fixed_asset_account', asset=self.name,
|
return get_asset_category_account('fixed_asset_account', None, self.name, None, self.asset_category, self.company)
|
||||||
asset_category = self.asset_category, company = self.company)
|
|
||||||
|
|
||||||
cwip_account = get_asset_account("capital_work_in_progress_account",
|
def get_cwip_account(self, cwip_enabled=False):
|
||||||
self.name, self.asset_category, self.company)
|
cwip_account = None
|
||||||
|
try:
|
||||||
|
cwip_account = get_asset_account("capital_work_in_progress_account", self.name, self.asset_category, self.company)
|
||||||
|
except:
|
||||||
|
# if no cwip account found in category or company and "cwip is enabled" then raise else silently pass
|
||||||
|
if cwip_enabled:
|
||||||
|
raise
|
||||||
|
|
||||||
return fixed_asset_account, cwip_account
|
return cwip_account
|
||||||
|
|
||||||
def make_gl_entries(self):
|
def make_gl_entries(self):
|
||||||
gl_entries = []
|
gl_entries = []
|
||||||
|
|
||||||
purchase_document = self.get_purchase_document()
|
purchase_document = self.get_purchase_document()
|
||||||
fixed_asset_account, cwip_account = self.get_asset_accounts()
|
fixed_asset_account, cwip_account = self.get_fixed_asset_account(), self.get_cwip_account()
|
||||||
|
|
||||||
if (purchase_document and self.purchase_receipt_amount and self.available_for_use_date <= nowdate()):
|
if (purchase_document and self.purchase_receipt_amount and self.available_for_use_date <= nowdate()):
|
||||||
|
|
||||||
@ -561,14 +574,18 @@ class Asset(AccountsController):
|
|||||||
return 100 * (1 - flt(depreciation_rate, float_precision))
|
return 100 * (1 - flt(depreciation_rate, float_precision))
|
||||||
|
|
||||||
def update_maintenance_status():
|
def update_maintenance_status():
|
||||||
assets = frappe.get_all('Asset', filters = {'docstatus': 1, 'maintenance_required': 1})
|
assets = frappe.get_all(
|
||||||
|
"Asset", filters={"docstatus": 1, "maintenance_required": 1}
|
||||||
|
)
|
||||||
|
|
||||||
for asset in assets:
|
for asset in assets:
|
||||||
asset = frappe.get_doc("Asset", asset.name)
|
asset = frappe.get_doc("Asset", asset.name)
|
||||||
if frappe.db.exists('Asset Maintenance Task', {'parent': asset.name, 'next_due_date': today()}):
|
if frappe.db.exists("Asset Repair", {"asset_name": asset.name, "repair_status": "Pending"}):
|
||||||
asset.set_status('In Maintenance')
|
asset.set_status("Out of Order")
|
||||||
if frappe.db.exists('Asset Repair', {'asset_name': asset.name, 'repair_status': 'Pending'}):
|
elif frappe.db.exists("Asset Maintenance Task", {"parent": asset.name, "next_due_date": today()}):
|
||||||
asset.set_status('Out of Order')
|
asset.set_status("In Maintenance")
|
||||||
|
else:
|
||||||
|
asset.set_status()
|
||||||
|
|
||||||
def make_post_gl_entry():
|
def make_post_gl_entry():
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ from frappe.utils import cstr, nowdate, getdate, flt, get_last_day, add_days, ad
|
|||||||
from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset
|
from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset
|
||||||
from erpnext.assets.doctype.asset.asset import make_sales_invoice
|
from erpnext.assets.doctype.asset.asset import make_sales_invoice
|
||||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
||||||
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||||
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice as make_invoice
|
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice as make_invoice
|
||||||
|
|
||||||
class TestAsset(unittest.TestCase):
|
class TestAsset(unittest.TestCase):
|
||||||
@ -558,81 +559,6 @@ class TestAsset(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(gle, expected_gle)
|
self.assertEqual(gle, expected_gle)
|
||||||
|
|
||||||
def test_gle_with_cwip_toggling(self):
|
|
||||||
# TEST: purchase an asset with cwip enabled and then disable cwip and try submitting the asset
|
|
||||||
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
|
|
||||||
|
|
||||||
pr = make_purchase_receipt(item_code="Macbook Pro",
|
|
||||||
qty=1, rate=5000, do_not_submit=True, location="Test Location")
|
|
||||||
pr.set('taxes', [{
|
|
||||||
'category': 'Total',
|
|
||||||
'add_deduct_tax': 'Add',
|
|
||||||
'charge_type': 'On Net Total',
|
|
||||||
'account_head': '_Test Account Service Tax - _TC',
|
|
||||||
'description': '_Test Account Service Tax',
|
|
||||||
'cost_center': 'Main - _TC',
|
|
||||||
'rate': 5.0
|
|
||||||
}, {
|
|
||||||
'category': 'Valuation and Total',
|
|
||||||
'add_deduct_tax': 'Add',
|
|
||||||
'charge_type': 'On Net Total',
|
|
||||||
'account_head': '_Test Account Shipping Charges - _TC',
|
|
||||||
'description': '_Test Account Shipping Charges',
|
|
||||||
'cost_center': 'Main - _TC',
|
|
||||||
'rate': 5.0
|
|
||||||
}])
|
|
||||||
pr.submit()
|
|
||||||
expected_gle = (
|
|
||||||
("Asset Received But Not Billed - _TC", 0.0, 5250.0),
|
|
||||||
("CWIP Account - _TC", 5250.0, 0.0)
|
|
||||||
)
|
|
||||||
pr_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
|
|
||||||
where voucher_type='Purchase Receipt' and voucher_no = %s
|
|
||||||
order by account""", pr.name)
|
|
||||||
self.assertEqual(pr_gle, expected_gle)
|
|
||||||
|
|
||||||
pi = make_invoice(pr.name)
|
|
||||||
pi.submit()
|
|
||||||
expected_gle = (
|
|
||||||
("_Test Account Service Tax - _TC", 250.0, 0.0),
|
|
||||||
("_Test Account Shipping Charges - _TC", 250.0, 0.0),
|
|
||||||
("Asset Received But Not Billed - _TC", 5250.0, 0.0),
|
|
||||||
("Creditors - _TC", 0.0, 5500.0),
|
|
||||||
("Expenses Included In Asset Valuation - _TC", 0.0, 250.0),
|
|
||||||
)
|
|
||||||
pi_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
|
|
||||||
where voucher_type='Purchase Invoice' and voucher_no = %s
|
|
||||||
order by account""", pi.name)
|
|
||||||
self.assertEqual(pi_gle, expected_gle)
|
|
||||||
|
|
||||||
asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
|
|
||||||
asset_doc = frappe.get_doc('Asset', asset)
|
|
||||||
month_end_date = get_last_day(nowdate())
|
|
||||||
asset_doc.available_for_use_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15)
|
|
||||||
self.assertEqual(asset_doc.gross_purchase_amount, 5250.0)
|
|
||||||
asset_doc.append("finance_books", {
|
|
||||||
"expected_value_after_useful_life": 200,
|
|
||||||
"depreciation_method": "Straight Line",
|
|
||||||
"total_number_of_depreciations": 3,
|
|
||||||
"frequency_of_depreciation": 10,
|
|
||||||
"depreciation_start_date": month_end_date
|
|
||||||
})
|
|
||||||
|
|
||||||
# disable cwip and try submitting
|
|
||||||
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
|
|
||||||
asset_doc.submit()
|
|
||||||
# asset should have gl entries even if cwip is disabled
|
|
||||||
expected_gle = (
|
|
||||||
("_Test Fixed Asset - _TC", 5250.0, 0.0),
|
|
||||||
("CWIP Account - _TC", 0.0, 5250.0)
|
|
||||||
)
|
|
||||||
gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
|
|
||||||
where voucher_type='Asset' and voucher_no = %s
|
|
||||||
order by account""", asset_doc.name)
|
|
||||||
self.assertEqual(gle, expected_gle)
|
|
||||||
|
|
||||||
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
|
|
||||||
|
|
||||||
def test_expense_head(self):
|
def test_expense_head(self):
|
||||||
pr = make_purchase_receipt(item_code="Macbook Pro",
|
pr = make_purchase_receipt(item_code="Macbook Pro",
|
||||||
qty=2, rate=200000.0, location="Test Location")
|
qty=2, rate=200000.0, location="Test Location")
|
||||||
@ -641,6 +567,74 @@ class TestAsset(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEquals('Asset Received But Not Billed - _TC', doc.items[0].expense_account)
|
self.assertEquals('Asset Received But Not Billed - _TC', doc.items[0].expense_account)
|
||||||
|
|
||||||
|
def test_asset_cwip_toggling_cases(self):
|
||||||
|
cwip = frappe.db.get_value("Asset Category", "Computers", "enable_cwip_accounting")
|
||||||
|
name = frappe.db.get_value("Asset Category Account", filters={"parent": "Computers"}, fieldname=["name"])
|
||||||
|
cwip_acc = "CWIP Account - _TC"
|
||||||
|
|
||||||
|
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
|
||||||
|
frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", "")
|
||||||
|
frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", "")
|
||||||
|
|
||||||
|
# case 0 -- PI with cwip disable, Asset with cwip disabled, No cwip account set
|
||||||
|
pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
|
||||||
|
asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
|
||||||
|
asset_doc = frappe.get_doc('Asset', asset)
|
||||||
|
asset_doc.available_for_use_date = nowdate()
|
||||||
|
asset_doc.calculate_depreciation = 0
|
||||||
|
asset_doc.submit()
|
||||||
|
gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
|
||||||
|
self.assertFalse(gle)
|
||||||
|
|
||||||
|
# case 1 -- PR with cwip disabled, Asset with cwip enabled
|
||||||
|
pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location")
|
||||||
|
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
|
||||||
|
frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc)
|
||||||
|
asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
|
||||||
|
asset_doc = frappe.get_doc('Asset', asset)
|
||||||
|
asset_doc.available_for_use_date = nowdate()
|
||||||
|
asset_doc.calculate_depreciation = 0
|
||||||
|
asset_doc.submit()
|
||||||
|
gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
|
||||||
|
self.assertFalse(gle)
|
||||||
|
|
||||||
|
# case 2 -- PR with cwip enabled, Asset with cwip disabled
|
||||||
|
pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location")
|
||||||
|
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
|
||||||
|
asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
|
||||||
|
asset_doc = frappe.get_doc('Asset', asset)
|
||||||
|
asset_doc.available_for_use_date = nowdate()
|
||||||
|
asset_doc.calculate_depreciation = 0
|
||||||
|
asset_doc.submit()
|
||||||
|
gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
|
||||||
|
self.assertTrue(gle)
|
||||||
|
|
||||||
|
# case 3 -- PI with cwip disabled, Asset with cwip enabled
|
||||||
|
pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
|
||||||
|
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
|
||||||
|
asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
|
||||||
|
asset_doc = frappe.get_doc('Asset', asset)
|
||||||
|
asset_doc.available_for_use_date = nowdate()
|
||||||
|
asset_doc.calculate_depreciation = 0
|
||||||
|
asset_doc.submit()
|
||||||
|
gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
|
||||||
|
self.assertFalse(gle)
|
||||||
|
|
||||||
|
# case 4 -- PI with cwip enabled, Asset with cwip disabled
|
||||||
|
pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
|
||||||
|
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
|
||||||
|
asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
|
||||||
|
asset_doc = frappe.get_doc('Asset', asset)
|
||||||
|
asset_doc.available_for_use_date = nowdate()
|
||||||
|
asset_doc.calculate_depreciation = 0
|
||||||
|
asset_doc.submit()
|
||||||
|
gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
|
||||||
|
self.assertTrue(gle)
|
||||||
|
|
||||||
|
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", cwip)
|
||||||
|
frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc)
|
||||||
|
frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", cwip_acc)
|
||||||
|
|
||||||
def create_asset_data():
|
def create_asset_data():
|
||||||
if not frappe.db.exists("Asset Category", "Computers"):
|
if not frappe.db.exists("Asset Category", "Computers"):
|
||||||
create_asset_category()
|
create_asset_category()
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import cint
|
from frappe.utils import cint, get_link_to_form
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class AssetCategory(Document):
|
class AssetCategory(Document):
|
||||||
@ -13,6 +13,7 @@ class AssetCategory(Document):
|
|||||||
self.validate_finance_books()
|
self.validate_finance_books()
|
||||||
self.validate_account_types()
|
self.validate_account_types()
|
||||||
self.validate_account_currency()
|
self.validate_account_currency()
|
||||||
|
self.valide_cwip_account()
|
||||||
|
|
||||||
def validate_finance_books(self):
|
def validate_finance_books(self):
|
||||||
for d in self.finance_books:
|
for d in self.finance_books:
|
||||||
@ -59,6 +60,21 @@ class AssetCategory(Document):
|
|||||||
.format(d.idx, frappe.unscrub(key_to_match), frappe.bold(selected_account), frappe.bold(expected_key_type)),
|
.format(d.idx, frappe.unscrub(key_to_match), frappe.bold(selected_account), frappe.bold(expected_key_type)),
|
||||||
title=_("Invalid Account"))
|
title=_("Invalid Account"))
|
||||||
|
|
||||||
|
def valide_cwip_account(self):
|
||||||
|
if self.enable_cwip_accounting:
|
||||||
|
missing_cwip_accounts_for_company = []
|
||||||
|
for d in self.accounts:
|
||||||
|
if (not d.capital_work_in_progress_account and
|
||||||
|
not frappe.db.get_value("Company", d.company_name, "capital_work_in_progress_account")):
|
||||||
|
missing_cwip_accounts_for_company.append(get_link_to_form("Company", d.company_name))
|
||||||
|
|
||||||
|
if missing_cwip_accounts_for_company:
|
||||||
|
msg = _("""To enable Capital Work in Progress Accounting, """)
|
||||||
|
msg += _("""you must select Capital Work in Progress Account in accounts table""")
|
||||||
|
msg += "<br><br>"
|
||||||
|
msg += _("You can also set default CWIP account in Company {}").format(", ".join(missing_cwip_accounts_for_company))
|
||||||
|
frappe.throw(msg, title=_("Missing Account"))
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_asset_category_account(fieldname, item=None, asset=None, account=None, asset_category = None, company = None):
|
def get_asset_category_account(fieldname, item=None, asset=None, account=None, asset_category = None, company = None):
|
||||||
|
@ -27,3 +27,21 @@ class TestAssetCategory(unittest.TestCase):
|
|||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def test_cwip_accounting(self):
|
||||||
|
company_cwip_acc = frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account")
|
||||||
|
frappe.db.set_value("Company", "_Test Company", "capital_work_in_progress_account", "")
|
||||||
|
|
||||||
|
asset_category = frappe.new_doc("Asset Category")
|
||||||
|
asset_category.asset_category_name = "Computers"
|
||||||
|
asset_category.enable_cwip_accounting = 1
|
||||||
|
|
||||||
|
asset_category.total_number_of_depreciations = 3
|
||||||
|
asset_category.frequency_of_depreciation = 3
|
||||||
|
asset_category.append("accounts", {
|
||||||
|
"company_name": "_Test Company",
|
||||||
|
"fixed_asset_account": "_Test Fixed Asset - _TC",
|
||||||
|
"accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
|
||||||
|
"depreciation_expense_account": "_Test Depreciations - _TC"
|
||||||
|
})
|
||||||
|
|
||||||
|
self.assertRaises(frappe.ValidationError, asset_category.insert)
|
@ -33,7 +33,7 @@
|
|||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"label": "Other Reports",
|
"label": "Other Reports",
|
||||||
"links": "[\n {\n \"is_query_report\": true,\n \"label\": \"Items To Be Requested\",\n \"name\": \"Items To Be Requested\",\n \"onboard\": 1,\n \"reference_doctype\": \"Item\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Item-wise Purchase History\",\n \"name\": \"Item-wise Purchase History\",\n \"onboard\": 1,\n \"reference_doctype\": \"Item\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Purchase Receipt Trends\",\n \"name\": \"Purchase Receipt Trends\",\n \"reference_doctype\": \"Purchase Receipt\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Purchase Invoice Trends\",\n \"name\": \"Purchase Invoice Trends\",\n \"reference_doctype\": \"Purchase Invoice\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Subcontracted Raw Materials To Be Transferred\",\n \"name\": \"Subcontracted Raw Materials To Be Transferred\",\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Subcontracted Item To Be Received\",\n \"name\": \"Subcontracted Item To Be Received\",\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Quoted Item Comparison\",\n \"name\": \"Quoted Item Comparison\",\n \"onboard\": 1,\n \"reference_doctype\": \"Supplier Quotation\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Material Requests for which Supplier Quotations are not created\",\n \"name\": \"Material Requests for which Supplier Quotations are not created\",\n \"reference_doctype\": \"Material Request\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Supplier Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"reference_doctype\": \"Address\",\n \"route_options\": {\n \"party_type\": \"Supplier\"\n },\n \"type\": \"report\"\n }\n]"
|
"links": "[\n {\n \"is_query_report\": true,\n \"label\": \"Items To Be Requested\",\n \"name\": \"Items To Be Requested\",\n \"onboard\": 1,\n \"reference_doctype\": \"Item\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Item-wise Purchase History\",\n \"name\": \"Item-wise Purchase History\",\n \"onboard\": 1,\n \"reference_doctype\": \"Item\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Purchase Receipt Trends\",\n \"name\": \"Purchase Receipt Trends\",\n \"reference_doctype\": \"Purchase Receipt\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Purchase Invoice Trends\",\n \"name\": \"Purchase Invoice Trends\",\n \"reference_doctype\": \"Purchase Invoice\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Subcontracted Raw Materials To Be Transferred\",\n \"name\": \"Subcontracted Raw Materials To Be Transferred\",\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Subcontracted Item To Be Received\",\n \"name\": \"Subcontracted Item To Be Received\",\n \"reference_doctype\": \"Purchase Order\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Supplier Quotation Comparison\",\n \"name\": \"Supplier Quotation Comparison\",\n \"onboard\": 1,\n \"reference_doctype\": \"Supplier Quotation\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Material Requests for which Supplier Quotations are not created\",\n \"name\": \"Material Requests for which Supplier Quotations are not created\",\n \"reference_doctype\": \"Material Request\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"Supplier Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"reference_doctype\": \"Address\",\n \"route_options\": {\n \"party_type\": \"Supplier\"\n },\n \"type\": \"report\"\n }\n]"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -61,7 +61,7 @@
|
|||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"label": "Buying",
|
"label": "Buying",
|
||||||
"modified": "2020-06-30 18:36:53.390498",
|
"modified": "2020-09-30 14:40:55.638458",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Buying",
|
"name": "Buying",
|
||||||
|
@ -1084,7 +1084,7 @@
|
|||||||
"idx": 105,
|
"idx": 105,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-09-14 14:36:12.418690",
|
"modified": "2020-10-07 14:31:57.661221",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order",
|
"name": "Purchase Order",
|
||||||
@ -1130,11 +1130,11 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"search_fields": "status, transaction_date, supplier,grand_total",
|
"search_fields": "status, transaction_date, supplier, grand_total",
|
||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"timeline_field": "supplier",
|
"timeline_field": "supplier",
|
||||||
"title_field": "supplier",
|
"title_field": "supplier_name",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
@ -651,12 +651,12 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
make_subcontracted_item(item_code)
|
make_subcontracted_item(item_code)
|
||||||
|
|
||||||
po = create_purchase_order(item_code=item_code, qty=1,
|
po = create_purchase_order(item_code=item_code, qty=1,
|
||||||
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
|
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC", include_exploded_items=1)
|
||||||
|
|
||||||
name = frappe.db.get_value('BOM', {'item': item_code}, 'name')
|
name = frappe.db.get_value('BOM', {'item': item_code}, 'name')
|
||||||
bom = frappe.get_doc('BOM', name)
|
bom = frappe.get_doc('BOM', name)
|
||||||
|
|
||||||
exploded_items = sorted([d.item_code for d in bom.exploded_items])
|
exploded_items = sorted([d.item_code for d in bom.exploded_items if not d.get('sourced_by_supplier')])
|
||||||
supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
|
supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
|
||||||
self.assertEquals(exploded_items, supplied_items)
|
self.assertEquals(exploded_items, supplied_items)
|
||||||
|
|
||||||
@ -664,7 +664,7 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC", include_exploded_items=0)
|
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC", include_exploded_items=0)
|
||||||
|
|
||||||
supplied_items1 = sorted([d.rm_item_code for d in po1.supplied_items])
|
supplied_items1 = sorted([d.rm_item_code for d in po1.supplied_items])
|
||||||
bom_items = sorted([d.item_code for d in bom.items])
|
bom_items = sorted([d.item_code for d in bom.items if not d.get('sourced_by_supplier')])
|
||||||
|
|
||||||
self.assertEquals(supplied_items1, bom_items)
|
self.assertEquals(supplied_items1, bom_items)
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ frappe.ui.form.on("Request for Quotation",{
|
|||||||
dialog.hide();
|
dialog.hide();
|
||||||
return frappe.call({
|
return frappe.call({
|
||||||
type: "GET",
|
type: "GET",
|
||||||
method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.make_supplier_quotation",
|
method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.make_supplier_quotation_from_rfq",
|
||||||
args: {
|
args: {
|
||||||
"source_name": doc.name,
|
"source_name": doc.name,
|
||||||
"for_supplier": args.supplier
|
"for_supplier": args.supplier
|
||||||
|
@ -214,10 +214,10 @@ def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
and `tabDynamic Link`.link_name like %(txt)s) and `tabContact`.name = `tabDynamic Link`.parent
|
and `tabDynamic Link`.link_name like %(txt)s) and `tabContact`.name = `tabDynamic Link`.parent
|
||||||
limit %(start)s, %(page_len)s""", {"start": start, "page_len":page_len, "txt": "%%%s%%" % txt, "name": filters.get('supplier')})
|
limit %(start)s, %(page_len)s""", {"start": start, "page_len":page_len, "txt": "%%%s%%" % txt, "name": filters.get('supplier')})
|
||||||
|
|
||||||
# This method is used to make supplier quotation from material request form.
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_supplier_quotation(source_name, for_supplier, target_doc=None):
|
def make_supplier_quotation_from_rfq(source_name, target_doc=None, for_supplier=None):
|
||||||
def postprocess(source, target_doc):
|
def postprocess(source, target_doc):
|
||||||
|
if for_supplier:
|
||||||
target_doc.supplier = for_supplier
|
target_doc.supplier = for_supplier
|
||||||
args = get_party_details(for_supplier, party_type="Supplier", ignore_permissions=True)
|
args = get_party_details(for_supplier, party_type="Supplier", ignore_permissions=True)
|
||||||
target_doc.currency = args.currency or get_party_account_currency('Supplier', for_supplier, source.company)
|
target_doc.currency = args.currency or get_party_account_currency('Supplier', for_supplier, source.company)
|
||||||
@ -354,3 +354,32 @@ def get_supplier_tag():
|
|||||||
frappe.cache().hset("Supplier", "Tags", tags)
|
frappe.cache().hset("Supplier", "Tags", tags)
|
||||||
|
|
||||||
return frappe.cache().hget("Supplier", "Tags")
|
return frappe.cache().hget("Supplier", "Tags")
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
@frappe.validate_and_sanitize_search_inputs
|
||||||
|
def get_rfq_containing_supplier(doctype, txt, searchfield, start, page_len, filters):
|
||||||
|
conditions = ""
|
||||||
|
if txt:
|
||||||
|
conditions += "and rfq.name like '%%"+txt+"%%' "
|
||||||
|
|
||||||
|
if filters.get("transaction_date"):
|
||||||
|
conditions += "and rfq.transaction_date = '{0}'".format(filters.get("transaction_date"))
|
||||||
|
|
||||||
|
rfq_data = frappe.db.sql("""
|
||||||
|
select
|
||||||
|
distinct rfq.name, rfq.transaction_date,
|
||||||
|
rfq.company
|
||||||
|
from
|
||||||
|
`tabRequest for Quotation` rfq, `tabRequest for Quotation Supplier` rfq_supplier
|
||||||
|
where
|
||||||
|
rfq.name = rfq_supplier.parent
|
||||||
|
and rfq_supplier.supplier = '{0}'
|
||||||
|
and rfq.docstatus = 1
|
||||||
|
and rfq.company = '{1}'
|
||||||
|
{2}
|
||||||
|
order by rfq.transaction_date ASC
|
||||||
|
limit %(page_len)s offset %(start)s """ \
|
||||||
|
.format(filters.get("supplier"), filters.get("company"), conditions),
|
||||||
|
{"page_len": page_len, "start": start}, as_dict=1)
|
||||||
|
|
||||||
|
return rfq_data
|
@ -9,7 +9,7 @@ import frappe
|
|||||||
from frappe.utils import nowdate
|
from frappe.utils import nowdate
|
||||||
from erpnext.stock.doctype.item.test_item import make_item
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
||||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
|
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation_from_rfq
|
||||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
|
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
|
||||||
from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity
|
from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity
|
||||||
from erpnext.crm.doctype.opportunity.opportunity import make_request_for_quotation as make_rfq
|
from erpnext.crm.doctype.opportunity.opportunity import make_request_for_quotation as make_rfq
|
||||||
@ -22,7 +22,7 @@ class TestRequestforQuotation(unittest.TestCase):
|
|||||||
self.assertEqual(rfq.get('suppliers')[1].quote_status, 'Pending')
|
self.assertEqual(rfq.get('suppliers')[1].quote_status, 'Pending')
|
||||||
|
|
||||||
# Submit the first supplier quotation
|
# Submit the first supplier quotation
|
||||||
sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
|
sq = make_supplier_quotation_from_rfq(rfq.name, for_supplier=rfq.get('suppliers')[0].supplier)
|
||||||
sq.submit()
|
sq.submit()
|
||||||
|
|
||||||
# No Quote first supplier quotation
|
# No Quote first supplier quotation
|
||||||
@ -37,10 +37,10 @@ class TestRequestforQuotation(unittest.TestCase):
|
|||||||
def test_make_supplier_quotation(self):
|
def test_make_supplier_quotation(self):
|
||||||
rfq = make_request_for_quotation()
|
rfq = make_request_for_quotation()
|
||||||
|
|
||||||
sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
|
sq = make_supplier_quotation_from_rfq(rfq.name, for_supplier=rfq.get('suppliers')[0].supplier)
|
||||||
sq.submit()
|
sq.submit()
|
||||||
|
|
||||||
sq1 = make_supplier_quotation(rfq.name, rfq.get('suppliers')[1].supplier)
|
sq1 = make_supplier_quotation_from_rfq(rfq.name, for_supplier=rfq.get('suppliers')[1].supplier)
|
||||||
sq1.submit()
|
sq1.submit()
|
||||||
|
|
||||||
self.assertEqual(sq.supplier, rfq.get('suppliers')[0].supplier)
|
self.assertEqual(sq.supplier, rfq.get('suppliers')[0].supplier)
|
||||||
@ -62,7 +62,7 @@ class TestRequestforQuotation(unittest.TestCase):
|
|||||||
|
|
||||||
rfq = make_request_for_quotation(supplier_data=supplier_wt_appos)
|
rfq = make_request_for_quotation(supplier_data=supplier_wt_appos)
|
||||||
|
|
||||||
sq = make_supplier_quotation(rfq.name, supplier_wt_appos[0].get("supplier"))
|
sq = make_supplier_quotation_from_rfq(rfq.name, for_supplier=supplier_wt_appos[0].get("supplier"))
|
||||||
sq.submit()
|
sq.submit()
|
||||||
|
|
||||||
frappe.form_dict = frappe.local("form_dict")
|
frappe.form_dict = frappe.local("form_dict")
|
||||||
|
@ -8,8 +8,7 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext
|
|||||||
setup: function() {
|
setup: function() {
|
||||||
this.frm.custom_make_buttons = {
|
this.frm.custom_make_buttons = {
|
||||||
'Purchase Order': 'Purchase Order',
|
'Purchase Order': 'Purchase Order',
|
||||||
'Quotation': 'Quotation',
|
'Quotation': 'Quotation'
|
||||||
'Subscription': 'Subscription'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._super();
|
this._super();
|
||||||
@ -28,12 +27,6 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext
|
|||||||
cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
|
cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
|
||||||
cur_frm.add_custom_button(__("Quotation"), this.make_quotation,
|
cur_frm.add_custom_button(__("Quotation"), this.make_quotation,
|
||||||
__('Create'));
|
__('Create'));
|
||||||
|
|
||||||
if(!this.frm.doc.auto_repeat) {
|
|
||||||
cur_frm.add_custom_button(__('Subscription'), function() {
|
|
||||||
erpnext.utils.make_subscription(me.frm.doc.doctype, me.frm.doc.name)
|
|
||||||
}, __('Create'))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (this.frm.doc.docstatus===0) {
|
else if (this.frm.doc.docstatus===0) {
|
||||||
|
|
||||||
@ -54,6 +47,27 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, __("Get items from"));
|
}, __("Get items from"));
|
||||||
|
|
||||||
|
this.frm.add_custom_button(__("Request for Quotation"),
|
||||||
|
function() {
|
||||||
|
if (!me.frm.doc.supplier) {
|
||||||
|
frappe.throw({message:__("Please select a Supplier"), title:__("Mandatory")})
|
||||||
|
}
|
||||||
|
erpnext.utils.map_current_doc({
|
||||||
|
method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.make_supplier_quotation_from_rfq",
|
||||||
|
source_doctype: "Request for Quotation",
|
||||||
|
target: me.frm,
|
||||||
|
setters: {
|
||||||
|
company: me.frm.doc.company,
|
||||||
|
transaction_date: null
|
||||||
|
},
|
||||||
|
get_query_filters: {
|
||||||
|
supplier: me.frm.doc.supplier
|
||||||
|
},
|
||||||
|
get_query_method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.get_rfq_containing_supplier"
|
||||||
|
|
||||||
|
})
|
||||||
|
}, __("Get items from"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -159,6 +159,7 @@
|
|||||||
"default": "Today",
|
"default": "Today",
|
||||||
"fieldname": "transaction_date",
|
"fieldname": "transaction_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
|
"in_list_view": 1,
|
||||||
"label": "Date",
|
"label": "Date",
|
||||||
"oldfieldname": "transaction_date",
|
"oldfieldname": "transaction_date",
|
||||||
"oldfieldtype": "Date",
|
"oldfieldtype": "Date",
|
||||||
@ -798,6 +799,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "valid_till",
|
"fieldname": "valid_till",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
|
"in_list_view": 1,
|
||||||
"label": "Valid Till"
|
"label": "Valid Till"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -805,7 +807,7 @@
|
|||||||
"idx": 29,
|
"idx": 29,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-07-18 05:10:45.556792",
|
"modified": "2020-10-01 20:56:17.932007",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Supplier Quotation",
|
"name": "Supplier Quotation",
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
"item_name",
|
"item_name",
|
||||||
"column_break_3",
|
"column_break_3",
|
||||||
"lead_time_days",
|
"lead_time_days",
|
||||||
|
"expected_delivery_date",
|
||||||
|
"is_free_item",
|
||||||
"section_break_5",
|
"section_break_5",
|
||||||
"description",
|
"description",
|
||||||
"item_group",
|
"item_group",
|
||||||
@ -19,20 +21,18 @@
|
|||||||
"col_break1",
|
"col_break1",
|
||||||
"image",
|
"image",
|
||||||
"image_view",
|
"image_view",
|
||||||
"manufacture_details",
|
|
||||||
"manufacturer",
|
|
||||||
"column_break_15",
|
|
||||||
"manufacturer_part_no",
|
|
||||||
"quantity_and_rate",
|
"quantity_and_rate",
|
||||||
"qty",
|
"qty",
|
||||||
"stock_uom",
|
"stock_uom",
|
||||||
"price_list_rate",
|
|
||||||
"discount_percentage",
|
|
||||||
"discount_amount",
|
|
||||||
"col_break2",
|
"col_break2",
|
||||||
"uom",
|
"uom",
|
||||||
"conversion_factor",
|
"conversion_factor",
|
||||||
"stock_qty",
|
"stock_qty",
|
||||||
|
"sec_break_price_list",
|
||||||
|
"price_list_rate",
|
||||||
|
"discount_percentage",
|
||||||
|
"discount_amount",
|
||||||
|
"col_break_price_list",
|
||||||
"base_price_list_rate",
|
"base_price_list_rate",
|
||||||
"sec_break1",
|
"sec_break1",
|
||||||
"rate",
|
"rate",
|
||||||
@ -42,7 +42,6 @@
|
|||||||
"base_rate",
|
"base_rate",
|
||||||
"base_amount",
|
"base_amount",
|
||||||
"pricing_rules",
|
"pricing_rules",
|
||||||
"is_free_item",
|
|
||||||
"section_break_24",
|
"section_break_24",
|
||||||
"net_rate",
|
"net_rate",
|
||||||
"net_amount",
|
"net_amount",
|
||||||
@ -56,7 +55,6 @@
|
|||||||
"weight_uom",
|
"weight_uom",
|
||||||
"warehouse_and_reference",
|
"warehouse_and_reference",
|
||||||
"warehouse",
|
"warehouse",
|
||||||
"project",
|
|
||||||
"prevdoc_doctype",
|
"prevdoc_doctype",
|
||||||
"material_request",
|
"material_request",
|
||||||
"sales_order",
|
"sales_order",
|
||||||
@ -65,13 +63,19 @@
|
|||||||
"material_request_item",
|
"material_request_item",
|
||||||
"request_for_quotation_item",
|
"request_for_quotation_item",
|
||||||
"item_tax_rate",
|
"item_tax_rate",
|
||||||
|
"manufacture_details",
|
||||||
|
"manufacturer",
|
||||||
|
"column_break_15",
|
||||||
|
"manufacturer_part_no",
|
||||||
|
"ad_sec_break",
|
||||||
|
"project",
|
||||||
"section_break_44",
|
"section_break_44",
|
||||||
"page_break"
|
"page_break"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"bold": 1,
|
"bold": 1,
|
||||||
"columns": 4,
|
"columns": 2,
|
||||||
"fieldname": "item_code",
|
"fieldname": "item_code",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
@ -107,7 +111,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "lead_time_days",
|
"fieldname": "lead_time_days",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"label": "Lead Time in days"
|
"label": "Supplier Lead Time (days)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
@ -162,7 +166,6 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "stock_uom",
|
"fieldname": "stock_uom",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Stock UOM",
|
"label": "Stock UOM",
|
||||||
"options": "UOM",
|
"options": "UOM",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
@ -196,6 +199,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "uom",
|
"fieldname": "uom",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
"label": "UOM",
|
"label": "UOM",
|
||||||
"options": "UOM",
|
"options": "UOM",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
@ -289,14 +293,6 @@
|
|||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "is_free_item",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Is Free Item",
|
|
||||||
"print_hide": 1,
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_24",
|
"fieldname": "section_break_24",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break"
|
||||||
@ -528,12 +524,43 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "column_break_15",
|
"fieldname": "column_break_15",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "sec_break_price_list",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "col_break_price_list",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsible": 1,
|
||||||
|
"fieldname": "ad_sec_break",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Accounting Dimensions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"depends_on": "is_free_item",
|
||||||
|
"fieldname": "is_free_item",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Is Free Item",
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
|
"bold": 1,
|
||||||
|
"fieldname": "expected_delivery_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"label": "Expected Delivery Date"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-07 18:35:51.175947",
|
"modified": "2020-10-01 16:34:39.703033",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Supplier Quotation Item",
|
"name": "Supplier Quotation Item",
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"add_total_row": 0,
|
|
||||||
"apply_user_permissions": 1,
|
|
||||||
"creation": "2016-07-21 08:31:05.890362",
|
|
||||||
"disabled": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "Report",
|
|
||||||
"idx": 2,
|
|
||||||
"is_standard": "Yes",
|
|
||||||
"modified": "2017-02-24 20:04:58.784351",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Buying",
|
|
||||||
"name": "Quoted Item Comparison",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"ref_doctype": "Supplier Quotation",
|
|
||||||
"report_name": "Quoted Item Comparison",
|
|
||||||
"report_type": "Script Report",
|
|
||||||
"roles": [
|
|
||||||
{
|
|
||||||
"role": "Manufacturing Manager"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "Purchase Manager"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "Purchase User"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "Stock User"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.query_reports["Quoted Item Comparison"] = {
|
frappe.query_reports["Supplier Quotation Comparison"] = {
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
@ -78,6 +78,13 @@ frappe.query_reports["Quoted Item Comparison"] = {
|
|||||||
return { filters: { "docstatus": ["<", 2] } }
|
return { filters: { "docstatus": ["<", 2] } }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"group_by",
|
||||||
|
"label": __("Group by"),
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"options": [__("Group by Supplier"), __("Group by Item")],
|
||||||
|
"default": __("Group by Supplier")
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldtype: "Check",
|
fieldtype: "Check",
|
||||||
label: __("Include Expired"),
|
label: __("Include Expired"),
|
||||||
@ -98,6 +105,9 @@ frappe.query_reports["Quoted Item Comparison"] = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(column.fieldname === "price_per_unit" && data.price_per_unit && data.min && data.min === 1){
|
||||||
|
value = `<div style="color:green">${value}</div>`;
|
||||||
|
}
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"apply_user_permissions": 1,
|
||||||
|
"creation": "2016-07-21 08:31:05.890362",
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"idx": 2,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"modified": "2017-02-24 20:04:58.784351",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Buying",
|
||||||
|
"name": "Supplier Quotation Comparison",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"ref_doctype": "Supplier Quotation",
|
||||||
|
"report_name": "Supplier Quotation Comparison",
|
||||||
|
"report_type": "Script Report",
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"role": "Manufacturing Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Purchase Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Purchase User"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Stock User"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -12,9 +12,9 @@ def execute(filters=None):
|
|||||||
if not filters:
|
if not filters:
|
||||||
return [], []
|
return [], []
|
||||||
|
|
||||||
|
columns = get_columns(filters)
|
||||||
conditions = get_conditions(filters)
|
conditions = get_conditions(filters)
|
||||||
supplier_quotation_data = get_data(filters, conditions)
|
supplier_quotation_data = get_data(filters, conditions)
|
||||||
columns = get_columns()
|
|
||||||
|
|
||||||
data, chart_data = prepare_data(supplier_quotation_data, filters)
|
data, chart_data = prepare_data(supplier_quotation_data, filters)
|
||||||
message = get_message()
|
message = get_message()
|
||||||
@ -41,9 +41,13 @@ def get_conditions(filters):
|
|||||||
return conditions
|
return conditions
|
||||||
|
|
||||||
def get_data(filters, conditions):
|
def get_data(filters, conditions):
|
||||||
supplier_quotation_data = frappe.db.sql("""SELECT
|
supplier_quotation_data = frappe.db.sql("""
|
||||||
sqi.parent, sqi.item_code, sqi.qty, sqi.rate, sqi.uom, sqi.request_for_quotation,
|
SELECT
|
||||||
sqi.lead_time_days, sq.supplier, sq.valid_till
|
sqi.parent, sqi.item_code,
|
||||||
|
sqi.qty, sqi.stock_qty, sqi.amount,
|
||||||
|
sqi.uom, sqi.stock_uom,
|
||||||
|
sqi.request_for_quotation,
|
||||||
|
sqi.lead_time_days, sq.supplier as supplier_name, sq.valid_till
|
||||||
FROM
|
FROM
|
||||||
`tabSupplier Quotation Item` sqi,
|
`tabSupplier Quotation Item` sqi,
|
||||||
`tabSupplier Quotation` sq
|
`tabSupplier Quotation` sq
|
||||||
@ -58,16 +62,18 @@ def get_data(filters, conditions):
|
|||||||
return supplier_quotation_data
|
return supplier_quotation_data
|
||||||
|
|
||||||
def prepare_data(supplier_quotation_data, filters):
|
def prepare_data(supplier_quotation_data, filters):
|
||||||
out, suppliers, qty_list, chart_data = [], [], [], []
|
out, groups, qty_list, suppliers, chart_data = [], [], [], [], []
|
||||||
supplier_wise_map = defaultdict(list)
|
group_wise_map = defaultdict(list)
|
||||||
supplier_qty_price_map = {}
|
supplier_qty_price_map = {}
|
||||||
|
|
||||||
|
group_by_field = "supplier_name" if filters.get("group_by") == "Group by Supplier" else "item_code"
|
||||||
company_currency = frappe.db.get_default("currency")
|
company_currency = frappe.db.get_default("currency")
|
||||||
float_precision = cint(frappe.db.get_default("float_precision")) or 2
|
float_precision = cint(frappe.db.get_default("float_precision")) or 2
|
||||||
|
|
||||||
for data in supplier_quotation_data:
|
for data in supplier_quotation_data:
|
||||||
supplier = data.get("supplier")
|
group = data.get(group_by_field) # get item or supplier value for this row
|
||||||
supplier_currency = frappe.db.get_value("Supplier", data.get("supplier"), "default_currency")
|
|
||||||
|
supplier_currency = frappe.db.get_value("Supplier", data.get("supplier_name"), "default_currency")
|
||||||
|
|
||||||
if supplier_currency:
|
if supplier_currency:
|
||||||
exchange_rate = get_exchange_rate(supplier_currency, company_currency)
|
exchange_rate = get_exchange_rate(supplier_currency, company_currency)
|
||||||
@ -75,38 +81,55 @@ def prepare_data(supplier_quotation_data, filters):
|
|||||||
exchange_rate = 1
|
exchange_rate = 1
|
||||||
|
|
||||||
row = {
|
row = {
|
||||||
"item_code": data.get('item_code'),
|
"item_code": "" if group_by_field=="item_code" else data.get("item_code"), # leave blank if group by field
|
||||||
|
"supplier_name": "" if group_by_field=="supplier_name" else data.get("supplier_name"),
|
||||||
"quotation": data.get("parent"),
|
"quotation": data.get("parent"),
|
||||||
"qty": data.get("qty"),
|
"qty": data.get("qty"),
|
||||||
"price": flt(data.get("rate") * exchange_rate, float_precision),
|
"price": flt(data.get("amount") * exchange_rate, float_precision),
|
||||||
"uom": data.get("uom"),
|
"uom": data.get("uom"),
|
||||||
|
"stock_uom": data.get('stock_uom'),
|
||||||
"request_for_quotation": data.get("request_for_quotation"),
|
"request_for_quotation": data.get("request_for_quotation"),
|
||||||
"valid_till": data.get('valid_till'),
|
"valid_till": data.get('valid_till'),
|
||||||
"lead_time_days": data.get('lead_time_days')
|
"lead_time_days": data.get('lead_time_days')
|
||||||
}
|
}
|
||||||
|
row["price_per_unit"] = flt(row["price"]) / (flt(data.get("stock_qty")) or 1)
|
||||||
|
|
||||||
# map for report view of form {'supplier1':[{},{},...]}
|
# map for report view of form {'supplier1'/'item1':[{},{},...]}
|
||||||
supplier_wise_map[supplier].append(row)
|
group_wise_map[group].append(row)
|
||||||
|
|
||||||
# map for chart preparation of the form {'supplier1': {'qty': 'price'}}
|
# map for chart preparation of the form {'supplier1': {'qty': 'price'}}
|
||||||
|
supplier = data.get("supplier_name")
|
||||||
if filters.get("item_code"):
|
if filters.get("item_code"):
|
||||||
if not supplier in supplier_qty_price_map:
|
if not supplier in supplier_qty_price_map:
|
||||||
supplier_qty_price_map[supplier] = {}
|
supplier_qty_price_map[supplier] = {}
|
||||||
supplier_qty_price_map[supplier][row["qty"]] = row["price"]
|
supplier_qty_price_map[supplier][row["qty"]] = row["price"]
|
||||||
|
|
||||||
|
groups.append(group)
|
||||||
suppliers.append(supplier)
|
suppliers.append(supplier)
|
||||||
qty_list.append(data.get("qty"))
|
qty_list.append(data.get("qty"))
|
||||||
|
|
||||||
|
groups = list(set(groups))
|
||||||
suppliers = list(set(suppliers))
|
suppliers = list(set(suppliers))
|
||||||
qty_list = list(set(qty_list))
|
qty_list = list(set(qty_list))
|
||||||
|
|
||||||
|
highlight_min_price = group_by_field == "item_code" or filters.get("item_code")
|
||||||
|
|
||||||
# final data format for report view
|
# final data format for report view
|
||||||
for supplier in suppliers:
|
for group in groups:
|
||||||
supplier_wise_map[supplier][0].update({"supplier_name": supplier})
|
group_entries = group_wise_map[group] # all entries pertaining to item/supplier
|
||||||
for entry in supplier_wise_map[supplier]:
|
group_entries[0].update({group_by_field : group}) # Add item/supplier name in first group row
|
||||||
|
|
||||||
|
if highlight_min_price:
|
||||||
|
prices = [group_entry["price_per_unit"] for group_entry in group_entries]
|
||||||
|
min_price = min(prices)
|
||||||
|
|
||||||
|
for entry in group_entries:
|
||||||
|
if highlight_min_price and entry["price_per_unit"] == min_price:
|
||||||
|
entry["min"] = 1
|
||||||
out.append(entry)
|
out.append(entry)
|
||||||
|
|
||||||
if filters.get("item_code"):
|
if filters.get("item_code"):
|
||||||
|
# render chart only for one item comparison
|
||||||
chart_data = prepare_chart_data(suppliers, qty_list, supplier_qty_price_map)
|
chart_data = prepare_chart_data(suppliers, qty_list, supplier_qty_price_map)
|
||||||
|
|
||||||
return out, chart_data
|
return out, chart_data
|
||||||
@ -145,8 +168,9 @@ def prepare_chart_data(suppliers, qty_list, supplier_qty_price_map):
|
|||||||
|
|
||||||
return chart_data
|
return chart_data
|
||||||
|
|
||||||
def get_columns():
|
def get_columns(filters):
|
||||||
columns = [{
|
group_by_columns = [
|
||||||
|
{
|
||||||
"fieldname": "supplier_name",
|
"fieldname": "supplier_name",
|
||||||
"label": _("Supplier"),
|
"label": _("Supplier"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@ -158,8 +182,10 @@ def get_columns():
|
|||||||
"label": _("Item"),
|
"label": _("Item"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Item",
|
"options": "Item",
|
||||||
"width": 200
|
"width": 150
|
||||||
},
|
}]
|
||||||
|
|
||||||
|
columns = [
|
||||||
{
|
{
|
||||||
"fieldname": "uom",
|
"fieldname": "uom",
|
||||||
"label": _("UOM"),
|
"label": _("UOM"),
|
||||||
@ -180,6 +206,20 @@ def get_columns():
|
|||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"width": 110
|
"width": 110
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "stock_uom",
|
||||||
|
"label": _("Stock UOM"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "UOM",
|
||||||
|
"width": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "price_per_unit",
|
||||||
|
"label": _("Price per Unit (Stock UOM)"),
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"options": "Company:company:default_currency",
|
||||||
|
"width": 120
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "quotation",
|
"fieldname": "quotation",
|
||||||
"label": _("Supplier Quotation"),
|
"label": _("Supplier Quotation"),
|
||||||
@ -205,9 +245,12 @@ def get_columns():
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Request for Quotation",
|
"options": "Request for Quotation",
|
||||||
"width": 150
|
"width": 150
|
||||||
}
|
}]
|
||||||
]
|
|
||||||
|
|
||||||
|
if filters.get("group_by") == "Group by Item":
|
||||||
|
group_by_columns.reverse()
|
||||||
|
|
||||||
|
columns[0:0] = group_by_columns # add positioned group by columns to the report
|
||||||
return columns
|
return columns
|
||||||
|
|
||||||
def get_message():
|
def get_message():
|
@ -1242,7 +1242,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
|||||||
try:
|
try:
|
||||||
doc.check_permission(perm_type)
|
doc.check_permission(perm_type)
|
||||||
except frappe.PermissionError:
|
except frappe.PermissionError:
|
||||||
actions = { 'create': 'add', 'write': 'update', 'cancel': 'remove' }
|
actions = { 'create': 'add', 'write': 'update'}
|
||||||
|
|
||||||
frappe.throw(_("You do not have permissions to {} items in a {}.")
|
frappe.throw(_("You do not have permissions to {} items in a {}.")
|
||||||
.format(actions[perm_type], parent_doctype), title=_("Insufficient Permissions"))
|
.format(actions[perm_type], parent_doctype), title=_("Insufficient Permissions"))
|
||||||
@ -1285,7 +1285,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
|||||||
sales_doctypes = ['Sales Order', 'Sales Invoice', 'Delivery Note', 'Quotation']
|
sales_doctypes = ['Sales Order', 'Sales Invoice', 'Delivery Note', 'Quotation']
|
||||||
parent = frappe.get_doc(parent_doctype, parent_doctype_name)
|
parent = frappe.get_doc(parent_doctype, parent_doctype_name)
|
||||||
|
|
||||||
check_doc_permissions(parent, 'cancel')
|
check_doc_permissions(parent, 'write')
|
||||||
validate_and_delete_children(parent, data)
|
validate_and_delete_children(parent, data)
|
||||||
|
|
||||||
for d in data:
|
for d in data:
|
||||||
@ -1319,24 +1319,26 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
|||||||
validate_quantity(child_item, d)
|
validate_quantity(child_item, d)
|
||||||
|
|
||||||
child_item.qty = flt(d.get("qty"))
|
child_item.qty = flt(d.get("qty"))
|
||||||
precision = child_item.precision("rate") or 2
|
rate_precision = child_item.precision("rate") or 2
|
||||||
|
conv_fac_precision = child_item.precision("conversion_factor") or 2
|
||||||
|
qty_precision = child_item.precision("qty") or 2
|
||||||
|
|
||||||
if flt(child_item.billed_amt, precision) > flt(flt(d.get("rate")) * flt(d.get("qty")), precision):
|
if flt(child_item.billed_amt, rate_precision) > flt(flt(d.get("rate"), rate_precision) * flt(d.get("qty"), qty_precision), rate_precision):
|
||||||
frappe.throw(_("Row #{0}: Cannot set Rate if amount is greater than billed amount for Item {1}.")
|
frappe.throw(_("Row #{0}: Cannot set Rate if amount is greater than billed amount for Item {1}.")
|
||||||
.format(child_item.idx, child_item.item_code))
|
.format(child_item.idx, child_item.item_code))
|
||||||
else:
|
else:
|
||||||
child_item.rate = flt(d.get("rate"))
|
child_item.rate = flt(d.get("rate"), rate_precision)
|
||||||
|
|
||||||
if d.get("conversion_factor"):
|
if d.get("conversion_factor"):
|
||||||
if child_item.stock_uom == child_item.uom:
|
if child_item.stock_uom == child_item.uom:
|
||||||
child_item.conversion_factor = 1
|
child_item.conversion_factor = 1
|
||||||
else:
|
else:
|
||||||
child_item.conversion_factor = flt(d.get('conversion_factor'))
|
child_item.conversion_factor = flt(d.get('conversion_factor'), conv_fac_precision)
|
||||||
|
|
||||||
if d.get("uom"):
|
if d.get("uom"):
|
||||||
child_item.uom = d.get("uom")
|
child_item.uom = d.get("uom")
|
||||||
conversion_factor = flt(get_conversion_factor(child_item.item_code, child_item.uom).get("conversion_factor"))
|
conversion_factor = flt(get_conversion_factor(child_item.item_code, child_item.uom).get("conversion_factor"))
|
||||||
child_item.conversion_factor = flt(d.get('conversion_factor')) or conversion_factor
|
child_item.conversion_factor = flt(d.get('conversion_factor'), conv_fac_precision) or conversion_factor
|
||||||
|
|
||||||
if d.get("delivery_date") and parent_doctype == 'Sales Order':
|
if d.get("delivery_date") and parent_doctype == 'Sales Order':
|
||||||
child_item.delivery_date = d.get('delivery_date')
|
child_item.delivery_date = d.get('delivery_date')
|
||||||
|
@ -847,6 +847,7 @@ def get_items_from_bom(item_code, bom, exploded_item=1):
|
|||||||
where
|
where
|
||||||
t2.parent = t1.name and t1.item = %s
|
t2.parent = t1.name and t1.item = %s
|
||||||
and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
|
and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
|
||||||
|
and t2.sourced_by_supplier = 0
|
||||||
and t2.item_code = t3.name""".format(doctype),
|
and t2.item_code = t3.name""".format(doctype),
|
||||||
(item_code, bom), as_dict=1)
|
(item_code, bom), as_dict=1)
|
||||||
|
|
||||||
|
@ -368,13 +368,17 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
searchfields = meta.get_search_fields()
|
searchfields = meta.get_search_fields()
|
||||||
|
|
||||||
search_columns = ''
|
search_columns = ''
|
||||||
|
search_cond = ''
|
||||||
|
|
||||||
if searchfields:
|
if searchfields:
|
||||||
search_columns = ", " + ", ".join(searchfields)
|
search_columns = ", " + ", ".join(searchfields)
|
||||||
|
search_cond = " or " + " or ".join([field + " like %(txt)s" for field in searchfields])
|
||||||
|
|
||||||
if args.get('warehouse'):
|
if args.get('warehouse'):
|
||||||
searchfields = ['batch.' + field for field in searchfields]
|
searchfields = ['batch.' + field for field in searchfields]
|
||||||
if searchfields:
|
if searchfields:
|
||||||
search_columns = ", " + ", ".join(searchfields)
|
search_columns = ", " + ", ".join(searchfields)
|
||||||
|
search_cond = " or " + " or ".join([field + " like %(txt)s" for field in searchfields])
|
||||||
|
|
||||||
batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom,
|
batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom,
|
||||||
concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date)
|
concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date)
|
||||||
@ -387,7 +391,8 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
and sle.warehouse = %(warehouse)s
|
and sle.warehouse = %(warehouse)s
|
||||||
and (sle.batch_no like %(txt)s
|
and (sle.batch_no like %(txt)s
|
||||||
or batch.expiry_date like %(txt)s
|
or batch.expiry_date like %(txt)s
|
||||||
or batch.manufacturing_date like %(txt)s)
|
or batch.manufacturing_date like %(txt)s
|
||||||
|
{search_cond})
|
||||||
and batch.docstatus < 2
|
and batch.docstatus < 2
|
||||||
{cond}
|
{cond}
|
||||||
{match_conditions}
|
{match_conditions}
|
||||||
@ -397,7 +402,8 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
search_columns = search_columns,
|
search_columns = search_columns,
|
||||||
cond=cond,
|
cond=cond,
|
||||||
match_conditions=get_match_cond(doctype),
|
match_conditions=get_match_cond(doctype),
|
||||||
having_clause = having_clause
|
having_clause = having_clause,
|
||||||
|
search_cond = search_cond
|
||||||
), args)
|
), args)
|
||||||
|
|
||||||
return batch_nos
|
return batch_nos
|
||||||
@ -409,12 +415,15 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
and item = %(item_code)s
|
and item = %(item_code)s
|
||||||
and (name like %(txt)s
|
and (name like %(txt)s
|
||||||
or expiry_date like %(txt)s
|
or expiry_date like %(txt)s
|
||||||
or manufacturing_date like %(txt)s)
|
or manufacturing_date like %(txt)s
|
||||||
|
{search_cond})
|
||||||
and docstatus < 2
|
and docstatus < 2
|
||||||
{0}
|
{0}
|
||||||
{match_conditions}
|
{match_conditions}
|
||||||
|
|
||||||
order by expiry_date, name desc
|
order by expiry_date, name desc
|
||||||
limit %(start)s, %(page_len)s""".format(cond, search_columns = search_columns, match_conditions=get_match_cond(doctype)), args)
|
limit %(start)s, %(page_len)s""".format(cond, search_columns = search_columns,
|
||||||
|
search_cond = search_cond, match_conditions=get_match_cond(doctype)), args)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
@ -3,13 +3,14 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import cint, flt, cstr, comma_or
|
from frappe.utils import cint, flt, cstr, comma_or, get_link_to_form
|
||||||
from frappe import _, throw
|
from frappe import _, throw
|
||||||
from erpnext.stock.get_item_details import get_bin_details
|
from erpnext.stock.get_item_details import get_bin_details
|
||||||
from erpnext.stock.utils import get_incoming_rate
|
from erpnext.stock.utils import get_incoming_rate
|
||||||
from erpnext.stock.get_item_details import get_conversion_factor
|
from erpnext.stock.get_item_details import get_conversion_factor
|
||||||
from erpnext.stock.doctype.item.item import set_item_default
|
from erpnext.stock.doctype.item.item import set_item_default
|
||||||
from frappe.contacts.doctype.address.address import get_address_display
|
from frappe.contacts.doctype.address.address import get_address_display
|
||||||
|
from erpnext.controllers.accounts_controller import get_taxes_and_charges
|
||||||
|
|
||||||
from erpnext.controllers.stock_controller import StockController
|
from erpnext.controllers.stock_controller import StockController
|
||||||
|
|
||||||
@ -53,10 +54,10 @@ class SellingController(StockController):
|
|||||||
super(SellingController, self).set_missing_values(for_validate)
|
super(SellingController, self).set_missing_values(for_validate)
|
||||||
|
|
||||||
# set contact and address details for customer, if they are not mentioned
|
# set contact and address details for customer, if they are not mentioned
|
||||||
self.set_missing_lead_customer_details()
|
self.set_missing_lead_customer_details(for_validate=for_validate)
|
||||||
self.set_price_list_and_item_details(for_validate=for_validate)
|
self.set_price_list_and_item_details(for_validate=for_validate)
|
||||||
|
|
||||||
def set_missing_lead_customer_details(self):
|
def set_missing_lead_customer_details(self, for_validate=False):
|
||||||
customer, lead = None, None
|
customer, lead = None, None
|
||||||
if getattr(self, "customer", None):
|
if getattr(self, "customer", None):
|
||||||
customer = self.customer
|
customer = self.customer
|
||||||
@ -94,6 +95,11 @@ class SellingController(StockController):
|
|||||||
posting_date=self.get('transaction_date') or self.get('posting_date'),
|
posting_date=self.get('transaction_date') or self.get('posting_date'),
|
||||||
company=self.company))
|
company=self.company))
|
||||||
|
|
||||||
|
if self.get('taxes_and_charges') and not self.get('taxes') and not for_validate:
|
||||||
|
taxes = get_taxes_and_charges('Sales Taxes and Charges Template', self.taxes_and_charges)
|
||||||
|
for tax in taxes:
|
||||||
|
self.append('taxes', tax)
|
||||||
|
|
||||||
def set_price_list_and_item_details(self, for_validate=False):
|
def set_price_list_and_item_details(self, for_validate=False):
|
||||||
self.set_price_list_currency("Selling")
|
self.set_price_list_currency("Selling")
|
||||||
self.set_missing_item_details(for_validate=for_validate)
|
self.set_missing_item_details(for_validate=for_validate)
|
||||||
@ -167,12 +173,16 @@ class SellingController(StockController):
|
|||||||
|
|
||||||
def validate_selling_price(self):
|
def validate_selling_price(self):
|
||||||
def throw_message(idx, item_name, rate, ref_rate_field):
|
def throw_message(idx, item_name, rate, ref_rate_field):
|
||||||
frappe.throw(_("""Row #{}: Selling rate for item {} is lower than its {}. Selling rate should be atleast {}""")
|
bold_net_rate = frappe.bold("net rate")
|
||||||
.format(idx, item_name, ref_rate_field, rate))
|
msg = (_("""Row #{}: Selling rate for item {} is lower than its {}. Selling {} should be atleast {}""")
|
||||||
|
.format(idx, frappe.bold(item_name), frappe.bold(ref_rate_field), bold_net_rate, frappe.bold(rate)))
|
||||||
|
msg += "<br><br>"
|
||||||
|
msg += (_("""You can alternatively disable selling price validation in {} to bypass this validation.""")
|
||||||
|
.format(get_link_to_form("Selling Settings", "Selling Settings")))
|
||||||
|
frappe.throw(msg, title=_("Invalid Selling Price"))
|
||||||
|
|
||||||
if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"):
|
if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"):
|
||||||
return
|
return
|
||||||
|
|
||||||
if hasattr(self, "is_return") and self.is_return:
|
if hasattr(self, "is_return") and self.is_return:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -181,8 +191,8 @@ class SellingController(StockController):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
last_purchase_rate, is_stock_item = frappe.get_cached_value("Item", it.item_code, ["last_purchase_rate", "is_stock_item"])
|
last_purchase_rate, is_stock_item = frappe.get_cached_value("Item", it.item_code, ["last_purchase_rate", "is_stock_item"])
|
||||||
last_purchase_rate_in_sales_uom = last_purchase_rate / (it.conversion_factor or 1)
|
last_purchase_rate_in_sales_uom = last_purchase_rate * (it.conversion_factor or 1)
|
||||||
if flt(it.base_rate) < flt(last_purchase_rate_in_sales_uom):
|
if flt(it.base_net_rate) < flt(last_purchase_rate_in_sales_uom):
|
||||||
throw_message(it.idx, frappe.bold(it.item_name), last_purchase_rate_in_sales_uom, "last purchase rate")
|
throw_message(it.idx, frappe.bold(it.item_name), last_purchase_rate_in_sales_uom, "last purchase rate")
|
||||||
|
|
||||||
last_valuation_rate = frappe.db.sql("""
|
last_valuation_rate = frappe.db.sql("""
|
||||||
@ -191,8 +201,8 @@ class SellingController(StockController):
|
|||||||
ORDER BY posting_date DESC, posting_time DESC, creation DESC LIMIT 1
|
ORDER BY posting_date DESC, posting_time DESC, creation DESC LIMIT 1
|
||||||
""", (it.item_code, it.warehouse))
|
""", (it.item_code, it.warehouse))
|
||||||
if last_valuation_rate:
|
if last_valuation_rate:
|
||||||
last_valuation_rate_in_sales_uom = last_valuation_rate[0][0] / (it.conversion_factor or 1)
|
last_valuation_rate_in_sales_uom = last_valuation_rate[0][0] * (it.conversion_factor or 1)
|
||||||
if is_stock_item and flt(it.base_rate) < flt(last_valuation_rate_in_sales_uom) \
|
if is_stock_item and flt(it.base_net_rate) < flt(last_valuation_rate_in_sales_uom) \
|
||||||
and not self.get('is_internal_customer'):
|
and not self.get('is_internal_customer'):
|
||||||
throw_message(it.idx, frappe.bold(it.item_name), last_valuation_rate_in_sales_uom, "valuation rate")
|
throw_message(it.idx, frappe.bold(it.item_name), last_valuation_rate_in_sales_uom, "valuation rate")
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_p
|
|||||||
|
|
||||||
if not filters: filters = []
|
if not filters: filters = []
|
||||||
|
|
||||||
if doctype in ['Supplier Quotation', 'Purchase Invoice']:
|
if doctype in ['Supplier Quotation', 'Purchase Invoice', 'Quotation']:
|
||||||
filters.append((doctype, 'docstatus', '<', 2))
|
filters.append((doctype, 'docstatus', '<', 2))
|
||||||
else:
|
else:
|
||||||
filters.append((doctype, 'docstatus', '=', 1))
|
filters.append((doctype, 'docstatus', '=', 1))
|
||||||
|
@ -241,6 +241,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval: doc.__islocal",
|
"depends_on": "eval: doc.__islocal",
|
||||||
|
"description": "Home, Work, etc.",
|
||||||
"fieldname": "address_title",
|
"fieldname": "address_title",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Address Title"
|
"label": "Address Title"
|
||||||
@ -249,7 +250,8 @@
|
|||||||
"depends_on": "eval: doc.__islocal",
|
"depends_on": "eval: doc.__islocal",
|
||||||
"fieldname": "address_line1",
|
"fieldname": "address_line1",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Address Line 1"
|
"label": "Address Line 1",
|
||||||
|
"mandatory_depends_on": "eval: doc.address_title && doc.address_type"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval: doc.__islocal",
|
"depends_on": "eval: doc.__islocal",
|
||||||
@ -261,7 +263,8 @@
|
|||||||
"depends_on": "eval: doc.__islocal",
|
"depends_on": "eval: doc.__islocal",
|
||||||
"fieldname": "city",
|
"fieldname": "city",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "City/Town"
|
"label": "City/Town",
|
||||||
|
"mandatory_depends_on": "eval: doc.address_title && doc.address_type"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval: doc.__islocal",
|
"depends_on": "eval: doc.__islocal",
|
||||||
@ -280,6 +283,7 @@
|
|||||||
"fieldname": "country",
|
"fieldname": "country",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Country",
|
"label": "Country",
|
||||||
|
"mandatory_depends_on": "eval: doc.address_title && doc.address_type",
|
||||||
"options": "Country"
|
"options": "Country"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -449,7 +453,7 @@
|
|||||||
"idx": 5,
|
"idx": 5,
|
||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-06-18 14:39:41.835416",
|
"modified": "2020-10-13 15:24:00.094811",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "CRM",
|
"module": "CRM",
|
||||||
"name": "Lead",
|
"name": "Lead",
|
||||||
|
@ -22,14 +22,12 @@ class Lead(SellingController):
|
|||||||
load_address_and_contact(self)
|
load_address_and_contact(self)
|
||||||
|
|
||||||
def before_insert(self):
|
def before_insert(self):
|
||||||
|
if self.address_title and self.address_type:
|
||||||
self.address_doc = self.create_address()
|
self.address_doc = self.create_address()
|
||||||
self.contact_doc = self.create_contact()
|
self.contact_doc = self.create_contact()
|
||||||
|
|
||||||
def after_insert(self):
|
def after_insert(self):
|
||||||
self.update_links()
|
self.update_links()
|
||||||
# after the address and contact are created, flush the field values
|
|
||||||
# to avoid inconsistent reporting in case the documents are changed
|
|
||||||
self.flush_address_and_contact_fields()
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.set_lead_name()
|
self.set_lead_name()
|
||||||
@ -136,15 +134,6 @@ class Lead(SellingController):
|
|||||||
# skipping country since the system auto-sets it from system defaults
|
# skipping country since the system auto-sets it from system defaults
|
||||||
address = frappe.new_doc("Address")
|
address = frappe.new_doc("Address")
|
||||||
|
|
||||||
mandatory_fields = [ df.fieldname for df in address.meta.fields if df.reqd ]
|
|
||||||
|
|
||||||
if not all([self.get(field) for field in mandatory_fields]):
|
|
||||||
frappe.msgprint(_('Missing mandatory fields in address. \
|
|
||||||
{0} to create address' ).format("<a href='desk#Form/Address/New Address 1' \
|
|
||||||
> Click here </a>"),
|
|
||||||
alert=True, indicator='yellow')
|
|
||||||
return
|
|
||||||
|
|
||||||
address.update({addr_field: self.get(addr_field) for addr_field in address_fields})
|
address.update({addr_field: self.get(addr_field) for addr_field in address_fields})
|
||||||
address.update({info_field: self.get(info_field) for info_field in info_fields})
|
address.update({info_field: self.get(info_field) for info_field in info_fields})
|
||||||
address.insert()
|
address.insert()
|
||||||
@ -193,7 +182,7 @@ class Lead(SellingController):
|
|||||||
|
|
||||||
def update_links(self):
|
def update_links(self):
|
||||||
# update address links
|
# update address links
|
||||||
if self.address_doc:
|
if hasattr(self, 'address_doc'):
|
||||||
self.address_doc.append("links", {
|
self.address_doc.append("links", {
|
||||||
"link_doctype": "Lead",
|
"link_doctype": "Lead",
|
||||||
"link_name": self.name,
|
"link_name": self.name,
|
||||||
@ -210,14 +199,6 @@ class Lead(SellingController):
|
|||||||
})
|
})
|
||||||
self.contact_doc.save()
|
self.contact_doc.save()
|
||||||
|
|
||||||
def flush_address_and_contact_fields(self):
|
|
||||||
fields = ['address_type', 'address_line1', 'address_line2', 'address_title',
|
|
||||||
'city', 'county', 'country', 'fax', 'pincode', 'state']
|
|
||||||
|
|
||||||
for field in fields:
|
|
||||||
self.set(field, None)
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_customer(source_name, target_doc=None):
|
def make_customer(source_name, target_doc=None):
|
||||||
return _make_customer(source_name, target_doc)
|
return _make_customer(source_name, target_doc)
|
||||||
@ -376,3 +357,8 @@ def get_lead_with_phone_number(number):
|
|||||||
lead = leads[0].name if leads else None
|
lead = leads[0].name if leads else None
|
||||||
|
|
||||||
return lead
|
return lead
|
||||||
|
|
||||||
|
def daily_open_lead():
|
||||||
|
leads = frappe.get_all("Lead", filters = [["contact_date", "Between", [nowdate(), nowdate()]]])
|
||||||
|
for lead in leads:
|
||||||
|
frappe.db.set_value("Lead", lead.name, "status", "Open")
|
@ -11,7 +11,7 @@ from erpnext.accounts.party import get_party_account_currency
|
|||||||
from erpnext.exceptions import InvalidCurrency
|
from erpnext.exceptions import InvalidCurrency
|
||||||
from erpnext.stock.doctype.material_request.material_request import make_request_for_quotation
|
from erpnext.stock.doctype.material_request.material_request import make_request_for_quotation
|
||||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import \
|
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import \
|
||||||
make_supplier_quotation as make_quotation_from_rfq
|
make_supplier_quotation_from_rfq
|
||||||
|
|
||||||
def work():
|
def work():
|
||||||
frappe.set_user(frappe.db.get_global('demo_purchase_user'))
|
frappe.set_user(frappe.db.get_global('demo_purchase_user'))
|
||||||
@ -44,7 +44,7 @@ def work():
|
|||||||
rfq = frappe.get_doc('Request for Quotation', rfq.name)
|
rfq = frappe.get_doc('Request for Quotation', rfq.name)
|
||||||
|
|
||||||
for supplier in rfq.suppliers:
|
for supplier in rfq.suppliers:
|
||||||
supplier_quotation = make_quotation_from_rfq(rfq.name, supplier.supplier)
|
supplier_quotation = make_supplier_quotation_from_rfq(rfq.name, for_supplier=supplier.supplier)
|
||||||
supplier_quotation.save()
|
supplier_quotation.save()
|
||||||
supplier_quotation.submit()
|
supplier_quotation.submit()
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldname": "question",
|
"fieldname": "question",
|
||||||
"fieldtype": "Small Text",
|
"fieldtype": "Text Editor",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Question",
|
"label": "Question",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
@ -34,7 +34,7 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2019-05-30 18:39:21.880974",
|
"modified": "2020-09-24 18:39:21.880974",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Education",
|
"module": "Education",
|
||||||
"name": "Question",
|
"name": "Question",
|
||||||
|
@ -20,14 +20,14 @@
|
|||||||
{
|
{
|
||||||
"fetch_from": "question_link.question",
|
"fetch_from": "question_link.question",
|
||||||
"fieldname": "question",
|
"fieldname": "question",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Text Editor",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Question",
|
"label": "Question",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-06-12 12:24:02.312577",
|
"modified": "2020-09-24 12:24:02.312577",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Education",
|
"module": "Education",
|
||||||
"name": "Quiz Question",
|
"name": "Quiz Question",
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
"allow_print": 0,
|
"allow_print": 0,
|
||||||
"amount": 0.0,
|
"amount": 0.0,
|
||||||
"amount_based_on_field": 0,
|
"amount_based_on_field": 0,
|
||||||
|
"apply_document_permissions": 0,
|
||||||
"creation": "2016-09-22 13:10:10.792735",
|
"creation": "2016-09-22 13:10:10.792735",
|
||||||
"doc_type": "Student Applicant",
|
"doc_type": "Student Applicant",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
@ -16,7 +17,7 @@
|
|||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"login_required": 1,
|
"login_required": 1,
|
||||||
"max_attachment_size": 0,
|
"max_attachment_size": 0,
|
||||||
"modified": "2020-06-11 22:53:45.875310",
|
"modified": "2020-10-07 23:13:07.814941",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Education",
|
"module": "Education",
|
||||||
"name": "student-applicant",
|
"name": "student-applicant",
|
||||||
@ -157,7 +158,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_read_on_all_link_options": 0,
|
"allow_read_on_all_link_options": 0,
|
||||||
"default": "INDIAN",
|
"default": "",
|
||||||
"fieldname": "nationality",
|
"fieldname": "nationality",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
|
@ -6,7 +6,7 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
import json
|
import json
|
||||||
from frappe.utils import getdate, get_time
|
from frappe.utils import getdate, get_time, flt
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
from frappe import _
|
from frappe import _
|
||||||
import datetime
|
import datetime
|
||||||
@ -45,7 +45,7 @@ class PatientAppointment(Document):
|
|||||||
|
|
||||||
def validate_overlaps(self):
|
def validate_overlaps(self):
|
||||||
end_time = datetime.datetime.combine(getdate(self.appointment_date), get_time(self.appointment_time)) \
|
end_time = datetime.datetime.combine(getdate(self.appointment_date), get_time(self.appointment_time)) \
|
||||||
+ datetime.timedelta(minutes=float(self.duration))
|
+ datetime.timedelta(minutes=flt(self.duration))
|
||||||
|
|
||||||
overlaps = frappe.db.sql("""
|
overlaps = frappe.db.sql("""
|
||||||
select
|
select
|
||||||
|
@ -23,7 +23,6 @@ web_include_css = "assets/css/erpnext-web.css"
|
|||||||
doctype_js = {
|
doctype_js = {
|
||||||
"Communication": "public/js/communication.js",
|
"Communication": "public/js/communication.js",
|
||||||
"Event": "public/js/event.js",
|
"Event": "public/js/event.js",
|
||||||
"Website Theme": "public/js/website_theme.js",
|
|
||||||
"Newsletter": "public/js/newsletter.js"
|
"Newsletter": "public/js/newsletter.js"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +335,8 @@ scheduler_events = {
|
|||||||
"erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry.process_expired_allocation",
|
"erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry.process_expired_allocation",
|
||||||
"erpnext.hr.utils.generate_leave_encashment",
|
"erpnext.hr.utils.generate_leave_encashment",
|
||||||
"erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall.create_process_loan_security_shortfall",
|
"erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall.create_process_loan_security_shortfall",
|
||||||
"erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual_for_term_loans"
|
"erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual_for_term_loans",
|
||||||
|
"erpnext.crm.doctype.lead.lead.daily_open_lead"
|
||||||
],
|
],
|
||||||
"monthly_long": [
|
"monthly_long": [
|
||||||
"erpnext.accounts.deferred_revenue.process_deferred_accounting",
|
"erpnext.accounts.deferred_revenue.process_deferred_accounting",
|
||||||
@ -392,6 +392,9 @@ regional_overrides = {
|
|||||||
'Italy': {
|
'Italy': {
|
||||||
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.italy.utils.update_itemised_tax_data',
|
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.italy.utils.update_itemised_tax_data',
|
||||||
'erpnext.controllers.accounts_controller.validate_regional': 'erpnext.regional.italy.utils.sales_invoice_validate',
|
'erpnext.controllers.accounts_controller.validate_regional': 'erpnext.regional.italy.utils.sales_invoice_validate',
|
||||||
|
},
|
||||||
|
'Germany': {
|
||||||
|
'erpnext.controllers.accounts_controller.validate_regional': 'erpnext.regional.germany.accounts_controller.validate_regional',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
user_privacy_documents = [
|
user_privacy_documents = [
|
||||||
|
@ -27,28 +27,53 @@ frappe.ui.form.on('Appraisal', {
|
|||||||
|
|
||||||
calculate_total: function(frm) {
|
calculate_total: function(frm) {
|
||||||
let goals = frm.doc.goals || [];
|
let goals = frm.doc.goals || [];
|
||||||
let total =0;
|
let total = 0;
|
||||||
for(let i = 0; i<goals.length; i++){
|
|
||||||
|
if (goals == []) {
|
||||||
|
frm.set_value('total_score', 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (let i = 0; i<goals.length; i++) {
|
||||||
total = flt(total)+flt(goals[i].score_earned)
|
total = flt(total)+flt(goals[i].score_earned)
|
||||||
}
|
}
|
||||||
|
if (!isNaN(total)) {
|
||||||
frm.set_value('total_score', total);
|
frm.set_value('total_score', total);
|
||||||
|
frm.refresh_field('calculate_total');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
set_score_earned: function(frm) {
|
||||||
|
let goals = frm.doc.goals || [];
|
||||||
|
for (let i = 0; i<goals.length; i++) {
|
||||||
|
var d = locals[goals[i].doctype][goals[i].name];
|
||||||
|
if (d.score && d.per_weightage) {
|
||||||
|
d.score_earned = flt(d.per_weightage*d.score, precision("score_earned", d))/100;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
d.score_earned = 0;
|
||||||
|
}
|
||||||
|
refresh_field('score_earned', d.name, 'goals');
|
||||||
|
}
|
||||||
|
frm.trigger('calculate_total');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on('Appraisal Goal', {
|
frappe.ui.form.on('Appraisal Goal', {
|
||||||
score: function(frm, cdt, cdn) {
|
score: function(frm, cdt, cdn) {
|
||||||
var d = locals[cdt][cdn];
|
var d = locals[cdt][cdn];
|
||||||
if (d.score) {
|
|
||||||
if (flt(d.score) > 5) {
|
if (flt(d.score) > 5) {
|
||||||
frappe.msgprint(__("Score must be less than or equal to 5"));
|
frappe.msgprint(__("Score must be less than or equal to 5"));
|
||||||
d.score = 0;
|
d.score = 0;
|
||||||
refresh_field('score', d.name, 'goals');
|
refresh_field('score', d.name, 'goals');
|
||||||
}
|
}
|
||||||
d.score_earned = flt(d.per_weightage*d.score, precision("score_earned", d))/100;
|
else {
|
||||||
} else {
|
frm.trigger('set_score_earned');
|
||||||
d.score_earned = 0;
|
|
||||||
}
|
}
|
||||||
refresh_field('score_earned', d.name, 'goals');
|
},
|
||||||
frm.trigger('calculate_total');
|
per_weightage: function(frm) {
|
||||||
|
frm.trigger('set_score_earned');
|
||||||
|
},
|
||||||
|
goals_remove: function(frm) {
|
||||||
|
frm.trigger('set_score_earned');
|
||||||
}
|
}
|
||||||
});
|
});
|
@ -1,724 +1,220 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"beta": 0,
|
|
||||||
"creation": "2013-01-10 16:34:12",
|
"creation": "2013-01-10 16:34:12",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Setup",
|
"document_type": "Setup",
|
||||||
"editable_grid": 0,
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"employee_details",
|
||||||
|
"naming_series",
|
||||||
|
"kra_template",
|
||||||
|
"employee",
|
||||||
|
"employee_name",
|
||||||
|
"column_break0",
|
||||||
|
"status",
|
||||||
|
"start_date",
|
||||||
|
"end_date",
|
||||||
|
"department",
|
||||||
|
"section_break0",
|
||||||
|
"goals",
|
||||||
|
"total_score",
|
||||||
|
"section_break1",
|
||||||
|
"remarks",
|
||||||
|
"other_details",
|
||||||
|
"company",
|
||||||
|
"column_break_17",
|
||||||
|
"amended_from"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "employee_details",
|
"fieldname": "employee_details",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"oldfieldtype": "Section Break"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldtype": "Section 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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "",
|
|
||||||
"fieldname": "naming_series",
|
"fieldname": "naming_series",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"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": "Series",
|
"label": "Series",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "HR-APR-.YY.-.MM.",
|
"options": "HR-APR-.YY.-.MM.",
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"set_only_once": 1
|
||||||
"set_only_once": 1,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "",
|
|
||||||
"fieldname": "kra_template",
|
"fieldname": "kra_template",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Appraisal Template",
|
"label": "Appraisal Template",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "kra_template",
|
"oldfieldname": "kra_template",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "Appraisal Template",
|
"options": "Appraisal Template",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "kra_template",
|
"depends_on": "kra_template",
|
||||||
"description": "",
|
|
||||||
"fieldname": "employee",
|
"fieldname": "employee",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 1,
|
"in_global_search": 1,
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "For Employee",
|
"label": "For Employee",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "employee",
|
"oldfieldname": "employee",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "Employee",
|
"options": "Employee",
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 1,
|
"search_index": 1
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "kra_template",
|
"depends_on": "kra_template",
|
||||||
"fieldname": "employee_name",
|
"fieldname": "employee_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 1,
|
"in_global_search": 1,
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "For Employee Name",
|
"label": "For Employee Name",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "employee_name",
|
"oldfieldname": "employee_name",
|
||||||
"oldfieldtype": "Data",
|
"oldfieldtype": "Data",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "kra_template",
|
"depends_on": "kra_template",
|
||||||
"fieldname": "column_break0",
|
"fieldname": "column_break0",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldtype": "Column Break",
|
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0,
|
|
||||||
"width": "50%"
|
"width": "50%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "Draft",
|
"default": "Draft",
|
||||||
"depends_on": "kra_template",
|
"depends_on": "kra_template",
|
||||||
"fieldname": "status",
|
"fieldname": "status",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Status",
|
"label": "Status",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "status",
|
"oldfieldname": "status",
|
||||||
"oldfieldtype": "Select",
|
"oldfieldtype": "Select",
|
||||||
"options": "\nDraft\nSubmitted\nCompleted\nCancelled",
|
"options": "\nDraft\nSubmitted\nCompleted\nCancelled",
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 1,
|
"search_index": 1
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "kra_template",
|
"depends_on": "kra_template",
|
||||||
"fieldname": "start_date",
|
"fieldname": "start_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Start Date",
|
"label": "Start Date",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "start_date",
|
"oldfieldname": "start_date",
|
||||||
"oldfieldtype": "Date",
|
"oldfieldtype": "Date",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "kra_template",
|
"depends_on": "kra_template",
|
||||||
"fieldname": "end_date",
|
"fieldname": "end_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"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": "End Date",
|
"label": "End Date",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "end_date",
|
"oldfieldname": "end_date",
|
||||||
"oldfieldtype": "Date",
|
"oldfieldtype": "Date",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fetch_from": "employee.department",
|
"fetch_from": "employee.department",
|
||||||
"fieldname": "department",
|
"fieldname": "department",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"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": "Department",
|
"label": "Department",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Department",
|
"options": "Department",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "kra_template",
|
"depends_on": "kra_template",
|
||||||
"fieldname": "section_break0",
|
"fieldname": "section_break0",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Goals",
|
"label": "Goals",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldtype": "Section Break",
|
"oldfieldtype": "Section Break",
|
||||||
"options": "Simple",
|
"options": "Simple"
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "goals",
|
"fieldname": "goals",
|
||||||
"fieldtype": "Table",
|
"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": "Goals",
|
"label": "Goals",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "appraisal_details",
|
"oldfieldname": "appraisal_details",
|
||||||
"oldfieldtype": "Table",
|
"oldfieldtype": "Table",
|
||||||
"options": "Appraisal Goal",
|
"options": "Appraisal Goal"
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "calculate_total_score",
|
|
||||||
"fieldtype": "Button",
|
|
||||||
"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": "Calculate Total Score",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldtype": "Button",
|
|
||||||
"options": "calculate_total",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "total_score",
|
"fieldname": "total_score",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Total Score (Out of 5)",
|
"label": "Total Score (Out of 5)",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "total_score",
|
"oldfieldname": "total_score",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "kra_template",
|
"depends_on": "kra_template",
|
||||||
"fieldname": "section_break1",
|
"fieldname": "section_break1",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "Any other remarks, noteworthy effort that should go in the records.",
|
"description": "Any other remarks, noteworthy effort that should go in the records.",
|
||||||
"fieldname": "remarks",
|
"fieldname": "remarks",
|
||||||
"fieldtype": "Text",
|
"fieldtype": "Text",
|
||||||
"hidden": 0,
|
"label": "Remarks"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Remarks",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "kra_template",
|
"depends_on": "kra_template",
|
||||||
"fieldname": "other_details",
|
"fieldname": "other_details",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"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": "Company",
|
"label": "Company",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "company",
|
"oldfieldname": "company",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "Company",
|
"options": "Company",
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 1,
|
"remember_last_selected_value": 1,
|
||||||
"report_hide": 0,
|
"reqd": 1
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_17",
|
"fieldname": "column_break_17",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "amended_from",
|
"fieldname": "amended_from",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"ignore_user_permissions": 1,
|
"ignore_user_permissions": 1,
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Amended From",
|
"label": "Amended From",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "amended_from",
|
"oldfieldname": "amended_from",
|
||||||
"oldfieldtype": "Data",
|
"oldfieldtype": "Data",
|
||||||
"options": "Appraisal",
|
"options": "Appraisal",
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 1,
|
"report_hide": 1,
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0,
|
|
||||||
"width": "150px"
|
"width": "150px"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"icon": "fa fa-thumbs-up",
|
"icon": "fa fa-thumbs-up",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"image_view": 0,
|
"index_web_pages_for_search": 1,
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"issingle": 0,
|
"links": [],
|
||||||
"istable": 0,
|
"modified": "2020-10-03 21:48:33.297065",
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2020-09-18 17:26:09.703215",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Appraisal",
|
"name": "Appraisal",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 0,
|
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 0,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Employee",
|
"role": "Employee",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -727,15 +223,10 @@
|
|||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 0,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 1,
|
"submit": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
@ -746,30 +237,18 @@
|
|||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 0,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "HR User",
|
"role": "HR User",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 1,
|
"submit": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"search_fields": "status, employee, employee_name",
|
"search_fields": "status, employee, employee_name",
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"timeline_field": "employee",
|
"timeline_field": "employee",
|
||||||
"title_field": "employee_name",
|
"title_field": "employee_name"
|
||||||
"track_changes": 0,
|
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
@ -50,7 +50,7 @@ class Appraisal(Document):
|
|||||||
total_w += flt(d.per_weightage)
|
total_w += flt(d.per_weightage)
|
||||||
|
|
||||||
if int(total_w) != 100:
|
if int(total_w) != 100:
|
||||||
frappe.throw(_("Total weightage assigned should be 100%. It is {0}").format(str(total_w) + "%"))
|
frappe.throw(_("Total weightage assigned should be 100%.<br>It is {0}").format(str(total_w) + "%"))
|
||||||
|
|
||||||
if frappe.db.get_value("Employee", self.employee, "user_id") != \
|
if frappe.db.get_value("Employee", self.employee, "user_id") != \
|
||||||
frappe.session.user and total == 0:
|
frappe.session.user and total == 0:
|
||||||
|
@ -109,7 +109,6 @@
|
|||||||
"encashment_date",
|
"encashment_date",
|
||||||
"exit_interview_details",
|
"exit_interview_details",
|
||||||
"held_on",
|
"held_on",
|
||||||
"reason_for_resignation",
|
|
||||||
"new_workplace",
|
"new_workplace",
|
||||||
"feedback",
|
"feedback",
|
||||||
"lft",
|
"lft",
|
||||||
@ -682,7 +681,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "reason_for_leaving",
|
"fieldname": "reason_for_leaving",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Small Text",
|
||||||
"label": "Reason for Leaving",
|
"label": "Reason for Leaving",
|
||||||
"oldfieldname": "reason_for_leaving",
|
"oldfieldname": "reason_for_leaving",
|
||||||
"oldfieldtype": "Data"
|
"oldfieldtype": "Data"
|
||||||
@ -696,6 +695,7 @@
|
|||||||
"options": "\nYes\nNo"
|
"options": "\nYes\nNo"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "eval:doc.leave_encashed ==\"Yes\"",
|
||||||
"fieldname": "encashment_date",
|
"fieldname": "encashment_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Encashment Date",
|
"label": "Encashment Date",
|
||||||
@ -705,7 +705,6 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "exit_interview_details",
|
"fieldname": "exit_interview_details",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"label": "Exit Interview Details",
|
|
||||||
"oldfieldname": "col_brk6",
|
"oldfieldname": "col_brk6",
|
||||||
"oldfieldtype": "Column Break",
|
"oldfieldtype": "Column Break",
|
||||||
"width": "50%"
|
"width": "50%"
|
||||||
@ -713,18 +712,10 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "held_on",
|
"fieldname": "held_on",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Held On",
|
"label": "Exit Interview Held On",
|
||||||
"oldfieldname": "held_on",
|
"oldfieldname": "held_on",
|
||||||
"oldfieldtype": "Date"
|
"oldfieldtype": "Date"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "reason_for_resignation",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"label": "Reason for Resignation",
|
|
||||||
"oldfieldname": "reason_for_resignation",
|
|
||||||
"oldfieldtype": "Select",
|
|
||||||
"options": "\nBetter Prospects\nHealth Concerns"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "new_workplace",
|
"fieldname": "new_workplace",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
@ -809,37 +800,29 @@
|
|||||||
"fieldname": "expense_approver",
|
"fieldname": "expense_approver",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Expense Approver",
|
"label": "Expense Approver",
|
||||||
"options": "User",
|
"options": "User"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "approvers_section",
|
"fieldname": "approvers_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Approvers",
|
"label": "Approvers"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_45",
|
"fieldname": "column_break_45",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "shift_request_approver",
|
"fieldname": "shift_request_approver",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Shift Request Approver",
|
"label": "Shift Request Approver",
|
||||||
"options": "User",
|
"options": "User"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-user",
|
"icon": "fa fa-user",
|
||||||
"idx": 24,
|
"idx": 24,
|
||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-07-28 01:36:04.109189",
|
"modified": "2020-10-06 15:58:23.805489",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Employee",
|
"name": "Employee",
|
||||||
|
@ -57,6 +57,9 @@ class Employee(NestedSet):
|
|||||||
remove_user_permission(
|
remove_user_permission(
|
||||||
"Employee", self.name, existing_user_id)
|
"Employee", self.name, existing_user_id)
|
||||||
|
|
||||||
|
def after_rename(self, old, new, merge):
|
||||||
|
self.db_set("employee", new)
|
||||||
|
|
||||||
def set_employee_name(self):
|
def set_employee_name(self):
|
||||||
self.employee_name = ' '.join(filter(lambda x: x, [self.first_name, self.middle_name, self.last_name]))
|
self.employee_name = ' '.join(filter(lambda x: x, [self.first_name, self.middle_name, self.last_name]))
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
@ -32,7 +33,7 @@ class HolidayList(Document):
|
|||||||
|
|
||||||
|
|
||||||
def validate_days(self):
|
def validate_days(self):
|
||||||
if self.from_date > self.to_date:
|
if getdate(self.from_date) > getdate(self.to_date):
|
||||||
throw(_("To Date cannot be before From Date"))
|
throw(_("To Date cannot be before From Date"))
|
||||||
|
|
||||||
for day in self.get("holidays"):
|
for day in self.get("holidays"):
|
||||||
|
@ -434,7 +434,8 @@ var get_bom_material_detail= function(doc, cdt, cdn, scrap_items) {
|
|||||||
"include_item_in_manufacturing": d.include_item_in_manufacturing,
|
"include_item_in_manufacturing": d.include_item_in_manufacturing,
|
||||||
"uom": d.uom,
|
"uom": d.uom,
|
||||||
"stock_uom": d.stock_uom,
|
"stock_uom": d.stock_uom,
|
||||||
"conversion_factor": d.conversion_factor
|
"conversion_factor": d.conversion_factor,
|
||||||
|
"sourced_by_supplier": d.sourced_by_supplier
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
d = locals[cdt][cdn];
|
d = locals[cdt][cdn];
|
||||||
@ -616,6 +617,22 @@ frappe.ui.form.on("BOM Item", "item_code", function(frm, cdt, cdn) {
|
|||||||
refresh_field("allow_alternative_item", d.name, d.parentfield);
|
refresh_field("allow_alternative_item", d.name, d.parentfield);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frappe.ui.form.on("BOM Item", "sourced_by_supplier", function(frm, cdt, cdn) {
|
||||||
|
var d = locals[cdt][cdn];
|
||||||
|
if (d.sourced_by_supplier) {
|
||||||
|
d.rate = 0;
|
||||||
|
refresh_field("rate", d.name, d.parentfield);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
frappe.ui.form.on("BOM Item", "rate", function(frm, cdt, cdn) {
|
||||||
|
var d = locals[cdt][cdn];
|
||||||
|
if (d.sourced_by_supplier) {
|
||||||
|
d.rate = 0;
|
||||||
|
refresh_field("rate", d.name, d.parentfield);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
frappe.ui.form.on("BOM Operation", "operations_remove", function(frm) {
|
frappe.ui.form.on("BOM Operation", "operations_remove", function(frm) {
|
||||||
erpnext.bom.calculate_op_cost(frm.doc);
|
erpnext.bom.calculate_op_cost(frm.doc);
|
||||||
erpnext.bom.calculate_total(frm.doc);
|
erpnext.bom.calculate_total(frm.doc);
|
||||||
|
@ -137,7 +137,8 @@ class BOM(WebsiteGenerator):
|
|||||||
"qty": item.qty,
|
"qty": item.qty,
|
||||||
"uom": item.uom,
|
"uom": item.uom,
|
||||||
"stock_uom": item.stock_uom,
|
"stock_uom": item.stock_uom,
|
||||||
"conversion_factor": item.conversion_factor
|
"conversion_factor": item.conversion_factor,
|
||||||
|
"sourced_by_supplier": item.sourced_by_supplier
|
||||||
})
|
})
|
||||||
for r in ret:
|
for r in ret:
|
||||||
if not item.get(r):
|
if not item.get(r):
|
||||||
@ -172,7 +173,8 @@ class BOM(WebsiteGenerator):
|
|||||||
'qty' : args.get("qty") or args.get("stock_qty") or 1,
|
'qty' : args.get("qty") or args.get("stock_qty") or 1,
|
||||||
'stock_qty' : args.get("qty") or args.get("stock_qty") or 1,
|
'stock_qty' : args.get("qty") or args.get("stock_qty") or 1,
|
||||||
'base_rate' : flt(rate) * (flt(self.conversion_rate) or 1),
|
'base_rate' : flt(rate) * (flt(self.conversion_rate) or 1),
|
||||||
'include_item_in_manufacturing': cint(args['transfer_for_manufacture']) or 0
|
'include_item_in_manufacturing': cint(args['transfer_for_manufacture']) or 0,
|
||||||
|
'sourced_by_supplier' : args['sourced_by_supplier'] or 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret_item
|
return ret_item
|
||||||
@ -191,8 +193,8 @@ class BOM(WebsiteGenerator):
|
|||||||
if arg.get('scrap_items'):
|
if arg.get('scrap_items'):
|
||||||
rate = get_valuation_rate(arg)
|
rate = get_valuation_rate(arg)
|
||||||
elif arg:
|
elif arg:
|
||||||
#Customer Provided parts will have zero rate
|
#Customer Provided parts and Supplier sourced parts will have zero rate
|
||||||
if not frappe.db.get_value('Item', arg["item_code"], 'is_customer_provided_item'):
|
if not frappe.db.get_value('Item', arg["item_code"], 'is_customer_provided_item') and not arg.get('sourced_by_supplier'):
|
||||||
if arg.get('bom_no') and self.set_rate_of_sub_assembly_item_based_on_bom:
|
if arg.get('bom_no') and self.set_rate_of_sub_assembly_item_based_on_bom:
|
||||||
rate = flt(self.get_bom_unitcost(arg['bom_no'])) * (arg.get("conversion_factor") or 1)
|
rate = flt(self.get_bom_unitcost(arg['bom_no'])) * (arg.get("conversion_factor") or 1)
|
||||||
else:
|
else:
|
||||||
@ -205,7 +207,6 @@ class BOM(WebsiteGenerator):
|
|||||||
else:
|
else:
|
||||||
frappe.msgprint(_("{0} not found for item {1}")
|
frappe.msgprint(_("{0} not found for item {1}")
|
||||||
.format(self.rm_cost_as_per, arg["item_code"]), alert=True)
|
.format(self.rm_cost_as_per, arg["item_code"]), alert=True)
|
||||||
|
|
||||||
return flt(rate) * flt(self.plc_conversion_rate or 1) / (self.conversion_rate or 1)
|
return flt(rate) * flt(self.plc_conversion_rate or 1) / (self.conversion_rate or 1)
|
||||||
|
|
||||||
def update_cost(self, update_parent=True, from_child_bom=False, save=True):
|
def update_cost(self, update_parent=True, from_child_bom=False, save=True):
|
||||||
@ -221,7 +222,8 @@ class BOM(WebsiteGenerator):
|
|||||||
"qty": d.qty,
|
"qty": d.qty,
|
||||||
"uom": d.uom,
|
"uom": d.uom,
|
||||||
"stock_uom": d.stock_uom,
|
"stock_uom": d.stock_uom,
|
||||||
"conversion_factor": d.conversion_factor
|
"conversion_factor": d.conversion_factor,
|
||||||
|
"sourced_by_supplier": d.sourced_by_supplier
|
||||||
})
|
})
|
||||||
|
|
||||||
if rate:
|
if rate:
|
||||||
@ -495,7 +497,8 @@ class BOM(WebsiteGenerator):
|
|||||||
'stock_uom' : d.stock_uom,
|
'stock_uom' : d.stock_uom,
|
||||||
'stock_qty' : flt(d.stock_qty),
|
'stock_qty' : flt(d.stock_qty),
|
||||||
'rate' : flt(d.base_rate) / (flt(d.conversion_factor) or 1.0),
|
'rate' : flt(d.base_rate) / (flt(d.conversion_factor) or 1.0),
|
||||||
'include_item_in_manufacturing': d.include_item_in_manufacturing
|
'include_item_in_manufacturing': d.include_item_in_manufacturing,
|
||||||
|
'sourced_by_supplier': d.sourced_by_supplier
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def company_currency(self):
|
def company_currency(self):
|
||||||
@ -521,6 +524,7 @@ class BOM(WebsiteGenerator):
|
|||||||
bom_item.stock_qty,
|
bom_item.stock_qty,
|
||||||
bom_item.rate,
|
bom_item.rate,
|
||||||
bom_item.include_item_in_manufacturing,
|
bom_item.include_item_in_manufacturing,
|
||||||
|
bom_item.sourced_by_supplier,
|
||||||
bom_item.stock_qty / ifnull(bom.quantity, 1) AS qty_consumed_per_unit
|
bom_item.stock_qty / ifnull(bom.quantity, 1) AS qty_consumed_per_unit
|
||||||
FROM `tabBOM Explosion Item` bom_item, tabBOM bom
|
FROM `tabBOM Explosion Item` bom_item, tabBOM bom
|
||||||
WHERE
|
WHERE
|
||||||
@ -539,7 +543,8 @@ class BOM(WebsiteGenerator):
|
|||||||
'stock_uom' : d['stock_uom'],
|
'stock_uom' : d['stock_uom'],
|
||||||
'stock_qty' : d['qty_consumed_per_unit'] * stock_qty,
|
'stock_qty' : d['qty_consumed_per_unit'] * stock_qty,
|
||||||
'rate' : flt(d['rate']),
|
'rate' : flt(d['rate']),
|
||||||
'include_item_in_manufacturing': d.get('include_item_in_manufacturing', 0)
|
'include_item_in_manufacturing': d.get('include_item_in_manufacturing', 0),
|
||||||
|
'sourced_by_supplier': d.get('sourced_by_supplier', 0)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def add_exploded_items(self):
|
def add_exploded_items(self):
|
||||||
@ -679,7 +684,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
|
|||||||
is_stock_item=is_stock_item,
|
is_stock_item=is_stock_item,
|
||||||
qty_field="stock_qty",
|
qty_field="stock_qty",
|
||||||
select_columns = """, bom_item.source_warehouse, bom_item.operation,
|
select_columns = """, bom_item.source_warehouse, bom_item.operation,
|
||||||
bom_item.include_item_in_manufacturing, bom_item.description, bom_item.rate,
|
bom_item.include_item_in_manufacturing, bom_item.description, bom_item.rate, bom_item.sourced_by_supplier,
|
||||||
(Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s limit 1) as idx""")
|
(Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s limit 1) as idx""")
|
||||||
|
|
||||||
items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True)
|
items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True)
|
||||||
@ -692,7 +697,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
|
|||||||
query = query.format(table="BOM Item", where_conditions="", is_stock_item=is_stock_item,
|
query = query.format(table="BOM Item", where_conditions="", is_stock_item=is_stock_item,
|
||||||
qty_field="stock_qty" if fetch_qty_in_stock_uom else "qty",
|
qty_field="stock_qty" if fetch_qty_in_stock_uom else "qty",
|
||||||
select_columns = """, bom_item.uom, bom_item.conversion_factor, bom_item.source_warehouse,
|
select_columns = """, bom_item.uom, bom_item.conversion_factor, bom_item.source_warehouse,
|
||||||
bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing,
|
bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing, bom_item.sourced_by_supplier,
|
||||||
bom_item.description, bom_item.base_rate as rate """)
|
bom_item.description, bom_item.base_rate as rate """)
|
||||||
items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True)
|
items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True)
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ from frappe.test_runner import make_test_records
|
|||||||
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
|
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
|
||||||
from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost
|
from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost
|
||||||
from six import string_types
|
from six import string_types
|
||||||
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
|
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
|
||||||
|
|
||||||
test_records = frappe.get_test_records('BOM')
|
test_records = frappe.get_test_records('BOM')
|
||||||
|
|
||||||
@ -138,6 +140,73 @@ class TestBOM(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(bom.items[0].rate, 20)
|
self.assertEqual(bom.items[0].rate, 20)
|
||||||
|
|
||||||
|
def test_subcontractor_sourced_item(self):
|
||||||
|
item_code = "_Test Subcontracted FG Item 1"
|
||||||
|
|
||||||
|
if not frappe.db.exists('Item', item_code):
|
||||||
|
make_item(item_code, {
|
||||||
|
'is_stock_item': 1,
|
||||||
|
'is_sub_contracted_item': 1,
|
||||||
|
'stock_uom': 'Nos'
|
||||||
|
})
|
||||||
|
|
||||||
|
if not frappe.db.exists('Item', "Test Extra Item 1"):
|
||||||
|
make_item("Test Extra Item 1", {
|
||||||
|
'is_stock_item': 1,
|
||||||
|
'stock_uom': 'Nos'
|
||||||
|
})
|
||||||
|
|
||||||
|
if not frappe.db.exists('Item', "Test Extra Item 2"):
|
||||||
|
make_item("Test Extra Item 2", {
|
||||||
|
'is_stock_item': 1,
|
||||||
|
'stock_uom': 'Nos'
|
||||||
|
})
|
||||||
|
|
||||||
|
if not frappe.db.exists('Item', "Test Extra Item 3"):
|
||||||
|
make_item("Test Extra Item 3", {
|
||||||
|
'is_stock_item': 1,
|
||||||
|
'stock_uom': 'Nos'
|
||||||
|
})
|
||||||
|
bom = frappe.get_doc({
|
||||||
|
'doctype': 'BOM',
|
||||||
|
'is_default': 1,
|
||||||
|
'item': item_code,
|
||||||
|
'currency': 'USD',
|
||||||
|
'quantity': 1,
|
||||||
|
'company': '_Test Company'
|
||||||
|
})
|
||||||
|
|
||||||
|
for item in ["Test Extra Item 1", "Test Extra Item 2"]:
|
||||||
|
item_doc = frappe.get_doc('Item', item)
|
||||||
|
|
||||||
|
bom.append('items', {
|
||||||
|
'item_code': item,
|
||||||
|
'qty': 1,
|
||||||
|
'uom': item_doc.stock_uom,
|
||||||
|
'stock_uom': item_doc.stock_uom,
|
||||||
|
'rate': item_doc.valuation_rate
|
||||||
|
})
|
||||||
|
|
||||||
|
bom.append('items', {
|
||||||
|
'item_code': "Test Extra Item 3",
|
||||||
|
'qty': 1,
|
||||||
|
'uom': item_doc.stock_uom,
|
||||||
|
'stock_uom': item_doc.stock_uom,
|
||||||
|
'rate': 0,
|
||||||
|
'sourced_by_supplier': 1
|
||||||
|
})
|
||||||
|
bom.insert(ignore_permissions=True)
|
||||||
|
bom.update_cost()
|
||||||
|
bom.submit()
|
||||||
|
# test that sourced_by_supplier rate is zero even after updating cost
|
||||||
|
self.assertEqual(bom.items[2].rate, 0)
|
||||||
|
# test in Purchase Order sourced_by_supplier is not added to Supplied Item
|
||||||
|
po = create_purchase_order(item_code=item_code, qty=1,
|
||||||
|
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
|
||||||
|
bom_items = sorted([d.item_code for d in bom.items if d.sourced_by_supplier != 1])
|
||||||
|
supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
|
||||||
|
self.assertEquals(bom_items, supplied_items)
|
||||||
|
|
||||||
def get_default_bom(item_code="_Test FG Item 2"):
|
def get_default_bom(item_code="_Test FG Item 2"):
|
||||||
return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})
|
return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})
|
||||||
|
|
||||||
|
@ -1,626 +1,181 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"autoname": "hash",
|
"autoname": "hash",
|
||||||
"beta": 0,
|
|
||||||
"creation": "2013-03-07 11:42:57",
|
"creation": "2013-03-07 11:42:57",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Setup",
|
"document_type": "Setup",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"item_code",
|
||||||
|
"item_name",
|
||||||
|
"cb",
|
||||||
|
"source_warehouse",
|
||||||
|
"operation",
|
||||||
|
"section_break_3",
|
||||||
|
"description",
|
||||||
|
"column_break_2",
|
||||||
|
"image",
|
||||||
|
"image_view",
|
||||||
|
"section_break_4",
|
||||||
|
"stock_qty",
|
||||||
|
"rate",
|
||||||
|
"qty_consumed_per_unit",
|
||||||
|
"column_break_8",
|
||||||
|
"stock_uom",
|
||||||
|
"amount",
|
||||||
|
"include_item_in_manufacturing",
|
||||||
|
"sourced_by_supplier"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "item_code",
|
"fieldname": "item_code",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 1,
|
"in_global_search": 1,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Item Code",
|
"label": "Item Code",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "item_code",
|
"oldfieldname": "item_code",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "Item",
|
"options": "Item",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "item_name",
|
"fieldname": "item_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 1,
|
"in_global_search": 1,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Item Name",
|
"label": "Item Name",
|
||||||
"length": 0,
|
"read_only": 1
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "cb",
|
"fieldname": "cb",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "source_warehouse",
|
"fieldname": "source_warehouse",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"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": "Source Warehouse",
|
"label": "Source Warehouse",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Warehouse",
|
"options": "Warehouse",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "operation",
|
"fieldname": "operation",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"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": "Operation",
|
"label": "Operation",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Operation",
|
"options": "Operation",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "section_break_3",
|
"fieldname": "section_break_3",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "description",
|
"fieldname": "description",
|
||||||
"fieldtype": "Text Editor",
|
"fieldtype": "Text Editor",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Description",
|
"label": "Description",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "description",
|
"oldfieldname": "description",
|
||||||
"oldfieldtype": "Text",
|
"oldfieldtype": "Text",
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"print_width": "300px",
|
"print_width": "300px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0,
|
|
||||||
"width": "300px"
|
"width": "300px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_2",
|
"fieldname": "column_break_2",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "image",
|
"fieldname": "image",
|
||||||
"fieldtype": "Attach",
|
"fieldtype": "Attach",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Image",
|
"label": "Image",
|
||||||
"length": 0,
|
"print_hide": 1
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "image_view",
|
"fieldname": "image_view",
|
||||||
"fieldtype": "Image",
|
"fieldtype": "Image",
|
||||||
"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": "Image View",
|
"label": "Image View",
|
||||||
"length": 0,
|
"options": "image"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "image",
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "section_break_4",
|
"fieldname": "section_break_4",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "stock_qty",
|
"fieldname": "stock_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Stock Qty",
|
"label": "Stock Qty",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "qty",
|
"oldfieldname": "qty",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "rate",
|
"fieldname": "rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Rate",
|
"label": "Rate",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "standard_rate",
|
"oldfieldname": "standard_rate",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "qty_consumed_per_unit",
|
"fieldname": "qty_consumed_per_unit",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Qty Consumed Per Unit",
|
"label": "Qty Consumed Per Unit",
|
||||||
"length": 0,
|
"read_only": 1
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_8",
|
"fieldname": "column_break_8",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "stock_uom",
|
"fieldname": "stock_uom",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"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": "Stock UOM",
|
"label": "Stock UOM",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "stock_uom",
|
"oldfieldname": "stock_uom",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "UOM",
|
"options": "UOM",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "amount",
|
"fieldname": "amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Amount",
|
"label": "Amount",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "amount_as_per_sr",
|
"oldfieldname": "amount_as_per_sr",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"permlevel": 0,
|
"read_only": 1
|
||||||
"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,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"default": "0",
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "include_item_in_manufacturing",
|
"fieldname": "include_item_in_manufacturing",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"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": "Include Item In Manufacturing",
|
"label": "Include Item In Manufacturing",
|
||||||
"length": 0,
|
"read_only": 1
|
||||||
"no_copy": 0,
|
},
|
||||||
"permlevel": 0,
|
{
|
||||||
"precision": "",
|
"default": "0",
|
||||||
"print_hide": 0,
|
"fieldname": "sourced_by_supplier",
|
||||||
"print_hide_if_no_value": 0,
|
"fieldtype": "Check",
|
||||||
"read_only": 1,
|
"label": "Sourced by Supplier",
|
||||||
"remember_last_selected_value": 0,
|
"read_only": 1
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"image_view": 0,
|
"index_web_pages_for_search": 1,
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"links": [],
|
||||||
"modified": "2018-11-20 19:04:59.813773",
|
"modified": "2020-10-08 16:21:29.386212",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "BOM Explosion Item",
|
"name": "BOM Explosion Item",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 0,
|
"sort_field": "modified",
|
||||||
"read_only": 0,
|
"sort_order": "DESC",
|
||||||
"read_only_onload": 0,
|
"track_changes": 1
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"track_changes": 1,
|
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
@ -37,7 +37,9 @@
|
|||||||
"section_break_27",
|
"section_break_27",
|
||||||
"has_variants",
|
"has_variants",
|
||||||
"include_item_in_manufacturing",
|
"include_item_in_manufacturing",
|
||||||
"original_item"
|
"original_item",
|
||||||
|
"column_break_33",
|
||||||
|
"sourced_by_supplier"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -272,12 +274,23 @@
|
|||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_33",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "sourced_by_supplier",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Sourced by Supplier"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-09 14:30:26.535546",
|
"modified": "2020-10-08 14:19:37.563300",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "BOM Item",
|
"name": "BOM Item",
|
||||||
|
@ -381,7 +381,6 @@ class ProductionPlan(Document):
|
|||||||
"transaction_date": nowdate(),
|
"transaction_date": nowdate(),
|
||||||
"status": "Draft",
|
"status": "Draft",
|
||||||
"company": self.company,
|
"company": self.company,
|
||||||
"requested_by": frappe.session.user,
|
|
||||||
'material_request_type': material_request_type,
|
'material_request_type': material_request_type,
|
||||||
'customer': item_doc.customer or ''
|
'customer': item_doc.customer or ''
|
||||||
})
|
})
|
||||||
|
@ -434,7 +434,7 @@ class WorkOrder(Document):
|
|||||||
elif flt(d.completed_qty) <= max_allowed_qty_for_wo:
|
elif flt(d.completed_qty) <= max_allowed_qty_for_wo:
|
||||||
d.status = "Completed"
|
d.status = "Completed"
|
||||||
else:
|
else:
|
||||||
frappe.throw(_("Completed Qty can not be greater than 'Qty to Manufacture'"))
|
frappe.throw(_("Completed Qty cannot be greater than 'Qty to Manufacture'"))
|
||||||
|
|
||||||
def set_actual_dates(self):
|
def set_actual_dates(self):
|
||||||
if self.get("operations"):
|
if self.get("operations"):
|
||||||
|
@ -224,7 +224,8 @@ def trigger_razorpay_subscription(*args, **kwargs):
|
|||||||
member.subscription_activated = 1
|
member.subscription_activated = 1
|
||||||
member.save(ignore_permissions=True)
|
member.save(ignore_permissions=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log = frappe.log_error(e, "Error creating membership entry")
|
message = "{0}\n\n{1}\n\n{2}: {3}".format(e, frappe.get_traceback(), __("Payment ID"), payment.id)
|
||||||
|
log = frappe.log_error(message, _("Error creating membership entry for {0}").format(member.name))
|
||||||
notify_failure(log)
|
notify_failure(log)
|
||||||
return { 'status': 'Failed', 'reason': e}
|
return { 'status': 'Failed', 'reason': e}
|
||||||
|
|
||||||
|
@ -730,3 +730,4 @@ erpnext.patches.v13_0.rename_issue_doctype_fields
|
|||||||
erpnext.patches.v13_0.change_default_pos_print_format
|
erpnext.patches.v13_0.change_default_pos_print_format
|
||||||
erpnext.patches.v13_0.set_youtube_video_id
|
erpnext.patches.v13_0.set_youtube_video_id
|
||||||
erpnext.patches.v13_0.set_app_name
|
erpnext.patches.v13_0.set_app_name
|
||||||
|
erpnext.patches.v13_0.print_uom_after_quantity_patch
|
||||||
|
10
erpnext/patches/v13_0/print_uom_after_quantity_patch.py
Normal file
10
erpnext/patches/v13_0/print_uom_after_quantity_patch.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Copyright (c) 2019, Frappe and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from erpnext.setup.install import create_print_uom_after_qty_custom_field
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
create_print_uom_after_qty_custom_field()
|
@ -217,7 +217,7 @@
|
|||||||
"fieldname": "help",
|
"fieldname": "help",
|
||||||
"fieldtype": "HTML",
|
"fieldtype": "HTML",
|
||||||
"label": "Help",
|
"label": "Help",
|
||||||
"options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base < 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS > 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
|
"options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condition. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base < 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS > 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@ -238,14 +238,13 @@
|
|||||||
"depends_on": "eval:doc.type == \"Deduction\"",
|
"depends_on": "eval:doc.type == \"Deduction\"",
|
||||||
"fieldname": "is_income_tax_component",
|
"fieldname": "is_income_tax_component",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Is Income Tax Component",
|
"label": "Is Income Tax Component"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-flag",
|
"icon": "fa fa-flag",
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-06-22 15:39:20.826565",
|
"modified": "2020-10-07 20:38:33.795853",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Payroll",
|
"module": "Payroll",
|
||||||
"name": "Salary Component",
|
"name": "Salary Component",
|
||||||
|
@ -117,7 +117,7 @@
|
|||||||
"depends_on": "eval:doc.is_flexible_benefit != 1",
|
"depends_on": "eval:doc.is_flexible_benefit != 1",
|
||||||
"fieldname": "section_break_2",
|
"fieldname": "section_break_2",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Condtion and formula"
|
"label": "Condition and formula"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
@ -206,38 +206,28 @@
|
|||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"fieldname": "section_break_5",
|
"fieldname": "section_break_5",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Component properties and references ",
|
"label": "Component properties and references "
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_11",
|
"fieldname": "column_break_11",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_19",
|
"fieldname": "section_break_19",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_18",
|
"fieldname": "column_break_18",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_24",
|
"fieldname": "column_break_24",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-07-01 12:13:41.956495",
|
"modified": "2020-10-07 20:39:41.619283",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Payroll",
|
"module": "Payroll",
|
||||||
"name": "Salary Detail",
|
"name": "Salary Detail",
|
||||||
|
@ -347,8 +347,7 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
|
|
||||||
# create additional salary of 150000
|
# create additional salary of 150000
|
||||||
frappe.db.sql("""delete from `tabSalary Slip` where employee=%s""", (employee))
|
frappe.db.sql("""delete from `tabSalary Slip` where employee=%s""", (employee))
|
||||||
data["additional-1"] = create_additional_salary(employee, payroll_period, 50000)
|
data["additional-1"] = create_additional_salary(employee, payroll_period, 150000)
|
||||||
data["additional-2"] = create_additional_salary(employee, payroll_period, 100000)
|
|
||||||
data["deducted_dates"] = create_salary_slips_for_payroll_period(employee,
|
data["deducted_dates"] = create_salary_slips_for_payroll_period(employee,
|
||||||
salary_structure.name, payroll_period)
|
salary_structure.name, payroll_period)
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ class Question {
|
|||||||
make_question() {
|
make_question() {
|
||||||
let question_wrapper = document.createElement('h5');
|
let question_wrapper = document.createElement('h5');
|
||||||
question_wrapper.classList.add('mt-3');
|
question_wrapper.classList.add('mt-3');
|
||||||
question_wrapper.innerText = this.question;
|
question_wrapper.innerHTML = this.question;
|
||||||
this.wrapper.appendChild(question_wrapper);
|
this.wrapper.appendChild(question_wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,6 +452,9 @@ erpnext.utils.update_child_items = function(opts) {
|
|||||||
const frm = opts.frm;
|
const frm = opts.frm;
|
||||||
const cannot_add_row = (typeof opts.cannot_add_row === 'undefined') ? true : opts.cannot_add_row;
|
const cannot_add_row = (typeof opts.cannot_add_row === 'undefined') ? true : opts.cannot_add_row;
|
||||||
const child_docname = (typeof opts.cannot_add_row === 'undefined') ? "items" : opts.child_docname;
|
const child_docname = (typeof opts.cannot_add_row === 'undefined') ? "items" : opts.child_docname;
|
||||||
|
const child_meta = frappe.get_meta(`${frm.doc.doctype} Item`);
|
||||||
|
const get_precision = (fieldname) => child_meta.fields.find(f => f.fieldname == fieldname).precision;
|
||||||
|
|
||||||
this.data = [];
|
this.data = [];
|
||||||
const fields = [{
|
const fields = [{
|
||||||
fieldtype:'Data',
|
fieldtype:'Data',
|
||||||
@ -499,14 +502,16 @@ erpnext.utils.update_child_items = function(opts) {
|
|||||||
default: 0,
|
default: 0,
|
||||||
read_only: 0,
|
read_only: 0,
|
||||||
in_list_view: 1,
|
in_list_view: 1,
|
||||||
label: __('Qty')
|
label: __('Qty'),
|
||||||
|
precision: get_precision("qty")
|
||||||
}, {
|
}, {
|
||||||
fieldtype:'Currency',
|
fieldtype:'Currency',
|
||||||
fieldname:"rate",
|
fieldname:"rate",
|
||||||
default: 0,
|
default: 0,
|
||||||
read_only: 0,
|
read_only: 0,
|
||||||
in_list_view: 1,
|
in_list_view: 1,
|
||||||
label: __('Rate')
|
label: __('Rate'),
|
||||||
|
precision: get_precision("rate")
|
||||||
}];
|
}];
|
||||||
|
|
||||||
if (frm.doc.doctype == 'Sales Order' || frm.doc.doctype == 'Purchase Order' ) {
|
if (frm.doc.doctype == 'Sales Order' || frm.doc.doctype == 'Purchase Order' ) {
|
||||||
@ -521,7 +526,8 @@ erpnext.utils.update_child_items = function(opts) {
|
|||||||
fieldtype: 'Float',
|
fieldtype: 'Float',
|
||||||
fieldname: "conversion_factor",
|
fieldname: "conversion_factor",
|
||||||
in_list_view: 1,
|
in_list_view: 1,
|
||||||
label: __("Conversion Factor")
|
label: __("Conversion Factor"),
|
||||||
|
precision: get_precision('conversion_factor')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -677,6 +683,7 @@ erpnext.utils.map_current_doc = function(opts) {
|
|||||||
date_field: opts.date_field || undefined,
|
date_field: opts.date_field || undefined,
|
||||||
setters: opts.setters,
|
setters: opts.setters,
|
||||||
get_query: opts.get_query,
|
get_query: opts.get_query,
|
||||||
|
add_filters_group: 1,
|
||||||
action: function(selections, args) {
|
action: function(selections, args) {
|
||||||
let values = selections;
|
let values = selections;
|
||||||
if(values.length === 0){
|
if(values.length === 0){
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
// MIT License. See license.txt
|
|
||||||
|
|
||||||
frappe.ui.form.on('Website Theme', {
|
|
||||||
validate(frm) {
|
|
||||||
let theme_scss = frm.doc.theme_scss;
|
|
||||||
if (theme_scss && (theme_scss.includes('frappe/public/scss/website')
|
|
||||||
&& !theme_scss.includes('erpnext/public/scss/website'))
|
|
||||||
) {
|
|
||||||
frm.set_value('theme_scss',
|
|
||||||
`${frm.doc.theme_scss}\n@import "erpnext/public/scss/website";`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
57
erpnext/regional/germany/accounts_controller.py
Normal file
57
erpnext/regional/germany/accounts_controller.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe import msgprint
|
||||||
|
|
||||||
|
|
||||||
|
REQUIRED_FIELDS = {
|
||||||
|
"Sales Invoice": [
|
||||||
|
{
|
||||||
|
"field_name": "company_address",
|
||||||
|
"regulation": "§ 14 Abs. 4 Nr. 1 UStG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field_name": "company_tax_id",
|
||||||
|
"regulation": "§ 14 Abs. 4 Nr. 2 UStG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field_name": "taxes",
|
||||||
|
"regulation": "§ 14 Abs. 4 Nr. 8 UStG",
|
||||||
|
"condition": "not exempt_from_sales_tax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field_name": "customer_address",
|
||||||
|
"regulation": "§ 14 Abs. 4 Nr. 1 UStG",
|
||||||
|
"condition": "base_grand_total > 250"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def validate_regional(doc):
|
||||||
|
"""Check if required fields for this document are present."""
|
||||||
|
required_fields = REQUIRED_FIELDS.get(doc.doctype)
|
||||||
|
if not required_fields:
|
||||||
|
return
|
||||||
|
|
||||||
|
meta = frappe.get_meta(doc.doctype)
|
||||||
|
field_map = {field.fieldname: field.label for field in meta.fields}
|
||||||
|
|
||||||
|
for field in required_fields:
|
||||||
|
condition = field.get("condition")
|
||||||
|
if condition and not frappe.safe_eval(condition, doc.as_dict()):
|
||||||
|
continue
|
||||||
|
|
||||||
|
field_name = field.get("field_name")
|
||||||
|
regulation = field.get("regulation")
|
||||||
|
if field_name and not doc.get(field_name):
|
||||||
|
missing(field_map.get(field_name), regulation)
|
||||||
|
|
||||||
|
|
||||||
|
def missing(field_label, regulation):
|
||||||
|
"""Notify the user that a required field is missing."""
|
||||||
|
context = 'Specific for Germany. Example: Remember to set Company Tax ID. It is required by § 14 Abs. 4 Nr. 2 UStG.'
|
||||||
|
msgprint(_('Remember to set {field_label}. It is required by {regulation}.', context=context).format(
|
||||||
|
field_label=frappe.bold(_(field_label)),
|
||||||
|
regulation=regulation
|
||||||
|
)
|
||||||
|
)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user