Merge branch 'develop' into datev_report_headers
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index cb88a11..cd1545c 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '11.1.39'
+__version__ = '12.1.2'
def get_default_company(user=None):
'''Get default company for user'''
diff --git a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
index 648cc68..bc07b6d 100644
--- a/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
+++ b/erpnext/accounts/dashboard_chart_source/account_balance_timeline/account_balance_timeline.py
@@ -12,11 +12,14 @@
@frappe.whitelist()
@cache_source
-def get(chart_name=None, from_date = None, to_date = None):
- chart = frappe.get_doc('Dashboard Chart', chart_name)
+def get(chart_name = None, chart = None, no_cache = None, from_date = None, to_date = None):
+ if chart_name:
+ chart = frappe.get_doc('Dashboard Chart', chart_name)
+ else:
+ chart = frappe._dict(frappe.parse_json(chart))
timespan = chart.timespan
timegrain = chart.time_interval
- filters = json.loads(chart.filters_json)
+ filters = frappe.parse_json(chart.filters_json)
account = filters.get("account")
company = filters.get("company")
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index 0e57b3f..1adc4c4 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -128,7 +128,8 @@
"account_currency": self.account_currency,
"parent_account": parent_acc_name_map[company]
})
- doc.save()
+ if not self.check_if_child_acc_exists(doc):
+ doc.save()
frappe.msgprint(_("Account {0} is added in the child company {1}")
.format(doc.name, company))
@@ -172,6 +173,24 @@
if frappe.db.get_value("GL Entry", {"account": self.name}):
frappe.throw(_("Currency can not be changed after making entries using some other currency"))
+ def check_if_child_acc_exists(self, doc):
+ ''' Checks if a account in parent company exists in the '''
+ info = frappe.db.get_value("Account", {
+ "account_name": doc.account_name,
+ "account_number": doc.account_number
+ }, ['company', 'account_currency', 'is_group', 'root_type', 'account_type', 'balance_must_be', 'account_name'], as_dict=1)
+
+ if not info:
+ return
+
+ doc = vars(doc)
+ dict_diff = [k for k in info if k in doc and info[k] != doc[k] and k != "company"]
+ if dict_diff:
+ frappe.throw(_("Account {0} already exists in child company {1}. The following fields have different values, they should be same:<ul><li>{2}</li></ul>")
+ .format(info.account_name, info.company, '</li><li>'.join(dict_diff)))
+ else:
+ return True
+
def convert_group_to_ledger(self):
if self.check_if_child_exists():
throw(_("Account with child nodes cannot be converted to ledger"))
diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js
index 6fdd797..efac1af 100644
--- a/erpnext/accounts/doctype/account/account_tree.js
+++ b/erpnext/accounts/doctype/account/account_tree.js
@@ -123,7 +123,8 @@
if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){
// show Dr if positive since balance is calculated as debit - credit else show Cr
- let dr_or_cr = node.data.balance_in_account_currency > 0 ? "Dr": "Cr";
+ let balance = node.data.balance_in_account_currency || node.data.balance;
+ let dr_or_cr = balance > 0 ? "Dr": "Cr";
if (node.data && node.data.balance!==undefined) {
$('<span class="balance-area pull-right text-muted small">'
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json
index b042bcc..adfa9f8 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json
@@ -406,7 +406,11 @@
"is_group": 1,
"Bewertungskorrektur zu Forderungen aus Lieferungen und Leistungen": {
"account_number": "9960"
- },
+ },
+ "Debitoren": {
+ "is_group": 1,
+ "account_number": "10000"
+ },
"Forderungen aus Lieferungen und Leistungen": {
"account_number": "1200",
"account_type": "Receivable"
@@ -1077,7 +1081,7 @@
}
}
},
- "C - Verb.": {
+ "C - Verbindlichkeiten": {
"account_type": "Payable",
"1 - Anleihen": {
"is_group": 1,
@@ -1193,7 +1197,15 @@
"is_group": 1,
"Bewertungskorrektur zu Verb. aus Lieferungen und Leistungen": {
"account_number": "9964"
- },
+ },
+ "Kreditoren": {
+ "account_number": "70000",
+ "is_group": 1,
+ "Wareneingangs-Verrechnungskonto" : {
+ "account_number": "70001",
+ "account_type": "Stock Received But Not Billed"
+ }
+ },
"Verb. aus Lieferungen und Leistungen": {
"account_number": "3300",
"account_type": "Payable"
@@ -1682,90 +1694,6 @@
"account_type": "Income Account"
}
},
- "Erl\u00f6sschm\u00e4lerungen (Gruppe)": {
- "is_group": 1,
- "Erl\u00f6sschm\u00e4lerungen": {
- "account_number": "4700"
- },
- "Erl\u00f6sschm\u00e4lerungen aus steuerfreien Ums\u00e4tzen \u00a7 4 Nr. 1a UStG": {
- "account_number": "4705"
- },
- "Erl\u00f6sschm\u00e4lerungen 7 % USt": {
- "account_number": "4710"
- },
- "Erl\u00f6sschm\u00e4lerungen 19 % USt": {
- "account_number": "4720"
- },
- "Erl\u00f6sschm\u00e4lerungen 16 % USt": {
- "account_number": "4723"
- },
- "Erl\u00f6sschm\u00e4lerungen aus steuerfreien innergem. Lieferungen": {
- "account_number": "4724"
- },
- "Erl\u00f6sschm\u00e4lerungen aus im Inland steuerpfl. EU-Lieferungen 7 % USt": {
- "account_number": "4725"
- },
- "Erl\u00f6sschm\u00e4lerungen aus im Inland steuerpfl. EU-Lieferungen 19 % USt": {
- "account_number": "4726"
- },
- "Erl\u00f6sschm\u00e4lerungen aus im anderen EU-Land steuerpfl. Lieferungen": {
- "account_number": "4727"
- },
- "Erl\u00f6sschm\u00e4lerungen aus im Inland steuerpfl. EU-Lieferungen 16 % USt": {
- "account_number": "4729"
- },
- "Gew\u00e4hrte Skonti (Gruppe)": {
- "is_group": 1,
- "Gew. Skonti": {
- "account_number": "4730"
- },
- "Gew. Skonti 7 % USt": {
- "account_number": "4731"
- },
- "Gew. Skonti 19 % USt": {
- "account_number": "4736"
- },
- "Gew. Skonti aus Lieferungen von Mobilfunkger./Schaltkr., f. die der Leistungsempf. die Ust. schuldet": {
- "account_number": "4738"
- },
- "Gew. Skonti aus Leistungen, f. die der Leistungsempf. die Umsatzsteuer nach \u00a7 13b UStG schuldet": {
- "account_number": "4741"
- },
- "Gew. Skonti aus Erl\u00f6sen aus im anderen EU-Land steuerpfl. Leistungen, f. die der Leistungsempf. die Ust. schuldet": {
- "account_number": "4742"
- },
- "Gew. Skonti aus steuerfreien innergem. Lieferungen \u00a7 4 Nr. 1b UStG": {
- "account_number": "4743"
- },
- "Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen": {
- "account_number": "4745"
- },
- "Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen 7% USt": {
- "account_number": "4746"
- },
- "Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen 19% USt": {
- "account_number": "4748"
- }
- },
- "Gew\u00e4hrte Boni 7 % USt": {
- "account_number": "4750"
- },
- "Gew\u00e4hrte Boni 19 % USt": {
- "account_number": "4760"
- },
- "Gew\u00e4hrte Boni": {
- "account_number": "4769"
- },
- "Gew\u00e4hrte Rabatte": {
- "account_number": "4770"
- },
- "Gew\u00e4hrte Rabatte 7 % USt": {
- "account_number": "4780"
- },
- "Gew\u00e4hrte Rabatte 19 % USt": {
- "account_number": "4790"
- }
- },
"Grundst\u00fccksertr\u00e4ge (Gruppe)": {
"is_group": 1,
"Grundst\u00fccksertr\u00e4ge": {
@@ -2049,48 +1977,6 @@
"Erh. Skonti aus Erwerb Waren als letzter Abnehmer innerh. Dreiecksgesch. 19% Vorst. u. 19% Ust.": {
"account_number": "5793"
}
- },
- "Erhaltene Boni (Gruppe)": {
- "is_group": 1,
- "Erhaltene Boni 7 % Vorsteuer": {
- "account_number": "5750"
- },
- "Erhaltene Boni aus Einkauf Roh-, Hilfs- und Betriebsstoffe": {
- "account_number": "5753"
- },
- "Erhaltene Boni aus Einkauf Roh-, Hilfs- und Betriebsstoffe 7% Vorsteuer": {
- "account_number": "5754"
- },
- "Erhaltene Boni aus Einkauf Roh-, Hilfs- und Betriebsstoffe 19% Vorsteuer": {
- "account_number": "5755"
- },
- "Erhaltene Boni 19 % Vorsteuer": {
- "account_number": "5760"
- },
- "Erhaltene Boni": {
- "account_number": "5769"
- }
- },
- "Erhaltene Rabatte (Gruppe)": {
- "is_group": 1,
- "Erhaltene Rabatte": {
- "account_number": "5770"
- },
- "Erhaltene Rabatte 7 % Vorsteuer": {
- "account_number": "5780"
- },
- "Erhaltene Rabatte aus Einkauf Roh-, Hilfs- und Betriebsstoffe": {
- "account_number": "5783"
- },
- "Erhaltene Rabatte aus Einkauf Roh-, Hilfs- und Betriebsstoffe 7% Vorsteuer": {
- "account_number": "5784"
- },
- "Erhaltene Rabatte aus Einkauf Roh-, Hilfs- und Betriebsstoffe 19% Vorsteuer": {
- "account_number": "5785"
- },
- "Erhaltene Rabatte 19 % Vorsteuer": {
- "account_number": "5790"
- }
}
},
"Bezugsnebenkosten (Gruppe)": {
@@ -2409,7 +2295,49 @@
},
"6 - sonstige betriebliche Ertr\u00e4ge": {
"root_type": "Income",
- "is_group": 1,
+ "is_group": 1,
+ "Erhaltene Boni (Gruppe)": {
+ "is_group": 1,
+ "Erhaltene Boni 7 % Vorsteuer": {
+ "account_number": "5750"
+ },
+ "Erhaltene Boni aus Einkauf Roh-, Hilfs- und Betriebsstoffe": {
+ "account_number": "5753"
+ },
+ "Erhaltene Boni aus Einkauf Roh-, Hilfs- und Betriebsstoffe 7% Vorsteuer": {
+ "account_number": "5754"
+ },
+ "Erhaltene Boni aus Einkauf Roh-, Hilfs- und Betriebsstoffe 19% Vorsteuer": {
+ "account_number": "5755"
+ },
+ "Erhaltene Boni 19 % Vorsteuer": {
+ "account_number": "5760"
+ },
+ "Erhaltene Boni": {
+ "account_number": "5769"
+ }
+ },
+ "Erhaltene Rabatte (Gruppe)": {
+ "is_group": 1,
+ "Erhaltene Rabatte": {
+ "account_number": "5770"
+ },
+ "Erhaltene Rabatte 7 % Vorsteuer": {
+ "account_number": "5780"
+ },
+ "Erhaltene Rabatte aus Einkauf Roh-, Hilfs- und Betriebsstoffe": {
+ "account_number": "5783"
+ },
+ "Erhaltene Rabatte aus Einkauf Roh-, Hilfs- und Betriebsstoffe 7% Vorsteuer": {
+ "account_number": "5784"
+ },
+ "Erhaltene Rabatte aus Einkauf Roh-, Hilfs- und Betriebsstoffe 19% Vorsteuer": {
+ "account_number": "5785"
+ },
+ "Erhaltene Rabatte 19 % Vorsteuer": {
+ "account_number": "5790"
+ }
+ },
"Andere aktivierte Eigenleistungen": {
"account_number": "4820"
},
@@ -2732,7 +2660,91 @@
},
"7 - sonstige betriebliche Aufwendungen": {
"root_type": "Expense",
- "is_group": 1,
+ "is_group": 1,
+ "Erl\u00f6sschm\u00e4lerungen (Gruppe)": {
+ "is_group": 1,
+ "Erl\u00f6sschm\u00e4lerungen": {
+ "account_number": "4700"
+ },
+ "Erl\u00f6sschm\u00e4lerungen aus steuerfreien Ums\u00e4tzen \u00a7 4 Nr. 1a UStG": {
+ "account_number": "4705"
+ },
+ "Erl\u00f6sschm\u00e4lerungen 7 % USt": {
+ "account_number": "4710"
+ },
+ "Erl\u00f6sschm\u00e4lerungen 19 % USt": {
+ "account_number": "4720"
+ },
+ "Erl\u00f6sschm\u00e4lerungen 16 % USt": {
+ "account_number": "4723"
+ },
+ "Erl\u00f6sschm\u00e4lerungen aus steuerfreien innergem. Lieferungen": {
+ "account_number": "4724"
+ },
+ "Erl\u00f6sschm\u00e4lerungen aus im Inland steuerpfl. EU-Lieferungen 7 % USt": {
+ "account_number": "4725"
+ },
+ "Erl\u00f6sschm\u00e4lerungen aus im Inland steuerpfl. EU-Lieferungen 19 % USt": {
+ "account_number": "4726"
+ },
+ "Erl\u00f6sschm\u00e4lerungen aus im anderen EU-Land steuerpfl. Lieferungen": {
+ "account_number": "4727"
+ },
+ "Erl\u00f6sschm\u00e4lerungen aus im Inland steuerpfl. EU-Lieferungen 16 % USt": {
+ "account_number": "4729"
+ },
+ "Gew\u00e4hrte Skonti (Gruppe)": {
+ "is_group": 1,
+ "Gew. Skonti": {
+ "account_number": "4730"
+ },
+ "Gew. Skonti 7 % USt": {
+ "account_number": "4731"
+ },
+ "Gew. Skonti 19 % USt": {
+ "account_number": "4736"
+ },
+ "Gew. Skonti aus Lieferungen von Mobilfunkger./Schaltkr., f. die der Leistungsempf. die Ust. schuldet": {
+ "account_number": "4738"
+ },
+ "Gew. Skonti aus Leistungen, f. die der Leistungsempf. die Umsatzsteuer nach \u00a7 13b UStG schuldet": {
+ "account_number": "4741"
+ },
+ "Gew. Skonti aus Erl\u00f6sen aus im anderen EU-Land steuerpfl. Leistungen, f. die der Leistungsempf. die Ust. schuldet": {
+ "account_number": "4742"
+ },
+ "Gew. Skonti aus steuerfreien innergem. Lieferungen \u00a7 4 Nr. 1b UStG": {
+ "account_number": "4743"
+ },
+ "Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen": {
+ "account_number": "4745"
+ },
+ "Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen 7% USt": {
+ "account_number": "4746"
+ },
+ "Gew. Skonti aus im Inland steuerpfl. EU-Lieferungen 19% USt": {
+ "account_number": "4748"
+ }
+ },
+ "Gew\u00e4hrte Boni 7 % USt": {
+ "account_number": "4750"
+ },
+ "Gew\u00e4hrte Boni 19 % USt": {
+ "account_number": "4760"
+ },
+ "Gew\u00e4hrte Boni": {
+ "account_number": "4769"
+ },
+ "Gew\u00e4hrte Rabatte": {
+ "account_number": "4770"
+ },
+ "Gew\u00e4hrte Rabatte 7 % USt": {
+ "account_number": "4780"
+ },
+ "Gew\u00e4hrte Rabatte 19 % USt": {
+ "account_number": "4790"
+ }
+ },
"Sonstige betriebliche Aufwendungen": {
"account_number": "6300"
},
@@ -3609,18 +3621,6 @@
"Ertr\u00e4ge aus der Aufl\u00f6sung von R\u00fcckstellungen f. sonstige Steuern": {
"account_number": "7694"
}
- },
- "Debitoren": {
- "root_type": "Asset",
- "is_group": 1
- },
- "Kreditoren": {
- "root_type": "Liability",
- "is_group": 1,
- "Wareneingangs-Verrechnungskonto" : {
- "account_number": "70001",
- "account_type": "Stock Received But Not Billed"
- }
}
}
}
diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json
index 1ccef6c..e9e1f43 100644
--- a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json
+++ b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json
@@ -17,8 +17,7 @@
"fieldtype": "Link",
"in_list_view": 1,
"label": "Company",
- "options": "Company",
- "reqd": 1
+ "options": "Company"
},
{
"fieldname": "reference_document",
@@ -34,8 +33,7 @@
"fieldtype": "Dynamic Link",
"in_list_view": 1,
"label": "Default Dimension",
- "options": "reference_document",
- "reqd": 1
+ "options": "reference_document"
},
{
"columns": 3,
@@ -55,7 +53,7 @@
}
],
"istable": 1,
- "modified": "2019-07-17 23:34:33.026883",
+ "modified": "2019-08-15 11:59:09.389891",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting Dimension Detail",
diff --git a/erpnext/accounts/doctype/bank/bank_dashboard.py b/erpnext/accounts/doctype/bank/bank_dashboard.py
index 4a1dad8..1e2383d 100644
--- a/erpnext/accounts/doctype/bank/bank_dashboard.py
+++ b/erpnext/accounts/doctype/bank/bank_dashboard.py
@@ -8,7 +8,7 @@
'fieldname': 'bank',
'transactions': [
{
- 'label': _('Bank Deatils'),
+ 'label': _('Bank Details'),
'items': ['Bank Account', 'Bank Guarantee']
}
]
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index f943b34..b8ebeba 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -45,12 +45,12 @@
def clear_linked_payment_entries(self):
for payment_entry in self.payment_entries:
allocated_amount = get_total_allocated_amount(payment_entry)
- paid_amount = get_paid_amount(payment_entry)
+ paid_amount = get_paid_amount(payment_entry, self.currency)
if paid_amount and allocated_amount:
if flt(allocated_amount[0]["allocated_amount"]) > flt(paid_amount):
frappe.throw(_("The total allocated amount ({0}) is greated than the paid amount ({1}).".format(flt(allocated_amount[0]["allocated_amount"]), flt(paid_amount))))
- elif flt(allocated_amount[0]["allocated_amount"]) == flt(paid_amount):
+ else:
if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
self.clear_simple_entry(payment_entry)
@@ -80,9 +80,17 @@
AND
bt.docstatus = 1""", (payment_entry.payment_document, payment_entry.payment_entry), as_dict=True)
-def get_paid_amount(payment_entry):
+def get_paid_amount(payment_entry, currency):
if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
- return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "paid_amount")
+
+ paid_amount_field = "paid_amount"
+ if payment_entry.payment_document == 'Payment Entry':
+ doc = frappe.get_doc("Payment Entry", payment_entry.payment_entry)
+ paid_amount_field = ("base_paid_amount"
+ if doc.paid_to_account_currency == currency else "paid_amount")
+
+ return frappe.db.get_value(payment_entry.payment_document,
+ payment_entry.payment_entry, paid_amount_field)
elif payment_entry.payment_document == "Journal Entry":
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "total_credit")
diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py
index b126b1f..33aefd6 100644
--- a/erpnext/accounts/doctype/budget/test_budget.py
+++ b/erpnext/accounts/doctype/budget/test_budget.py
@@ -11,32 +11,32 @@
from erpnext.accounts.doctype.budget.budget import get_actual_expense, BudgetError
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
-class TestBudget(unittest.TestCase):
+class TestBudget(unittest.TestCase):
def test_monthly_budget_crossed_ignore(self):
set_total_expense_zero("2013-02-28", "Cost Center")
budget = make_budget(budget_against="Cost Center")
-
+
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
self.assertTrue(frappe.db.get_value("GL Entry",
{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
-
+
budget.cancel()
def test_monthly_budget_crossed_stop1(self):
set_total_expense_zero("2013-02-28", "Cost Center")
budget = make_budget(budget_against="Cost Center")
-
+
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date="2013-02-28")
self.assertRaises(BudgetError, jv.submit)
-
+
budget.load_from_db()
budget.cancel()
@@ -46,7 +46,7 @@
budget = make_budget(budget_against="Cost Center")
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
-
+
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", posting_date="2013-03-02")
@@ -117,14 +117,14 @@
set_total_expense_zero("2013-02-28", "Project")
budget = make_budget(budget_against="Project")
-
+
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", project="_Test Project", posting_date="2013-02-28")
self.assertRaises(BudgetError, jv.submit)
-
+
budget.load_from_db()
budget.cancel()
@@ -132,31 +132,31 @@
set_total_expense_zero("2013-02-28", "Cost Center")
budget = make_budget(budget_against="Cost Center")
-
+
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", 150000, "_Test Cost Center - _TC", posting_date="2013-03-28")
self.assertRaises(BudgetError, jv.submit)
-
+
budget.cancel()
def test_yearly_budget_crossed_stop2(self):
set_total_expense_zero("2013-02-28", "Project")
budget = make_budget(budget_against="Project")
-
+
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", 150000, "_Test Cost Center - _TC", project="_Test Project", posting_date="2013-03-28")
self.assertRaises(BudgetError, jv.submit)
-
+
budget.cancel()
def test_monthly_budget_on_cancellation1(self):
set_total_expense_zero("2013-02-28", "Cost Center")
budget = make_budget(budget_against="Cost Center")
-
+
jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True)
@@ -170,9 +170,9 @@
{"voucher_type": "Journal Entry", "voucher_no": jv2.name}))
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
-
+
self.assertRaises(BudgetError, jv1.cancel)
-
+
budget.load_from_db()
budget.cancel()
@@ -180,7 +180,7 @@
set_total_expense_zero("2013-02-28", "Project")
budget = make_budget(budget_against="Project")
-
+
jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date="2013-02-28", submit=True, project="_Test Project")
@@ -194,16 +194,16 @@
{"voucher_type": "Journal Entry", "voucher_no": jv2.name}))
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
-
+
self.assertRaises(BudgetError, jv1.cancel)
-
+
budget.load_from_db()
budget.cancel()
def test_monthly_budget_against_group_cost_center(self):
set_total_expense_zero("2013-02-28", "Cost Center")
set_total_expense_zero("2013-02-28", "Cost Center", "_Test Cost Center 2 - _TC")
-
+
budget = make_budget(budget_against="Cost Center", cost_center="_Test Company - _TC")
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
@@ -211,7 +211,7 @@
"_Test Bank - _TC", 40000, "_Test Cost Center 2 - _TC", posting_date="2013-02-28")
self.assertRaises(BudgetError, jv.submit)
-
+
budget.load_from_db()
budget.cancel()
@@ -239,8 +239,6 @@
budget.cancel()
jv.cancel()
- frappe.delete_doc('Journal Entry', jv.name)
- frappe.delete_doc('Cost Center', cost_center)
def set_total_expense_zero(posting_date, budget_against_field=None, budget_against_CC=None):
if budget_against_field == "Project":
@@ -256,7 +254,7 @@
"budget_against_field": budget_against_field,
"budget_against": budget_against
}))
-
+
if existing_expense:
if budget_against_field == "Cost Center":
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
@@ -281,13 +279,13 @@
frappe.db.sql("delete from `tabBudget Account` where parent = %(name)s", d)
budget = frappe.new_doc("Budget")
-
+
if budget_against == "Project":
budget.project = "_Test Project"
else:
budget.cost_center =cost_center or "_Test Cost Center - _TC"
-
-
+
+
budget.fiscal_year = "_Test Fiscal Year 2013"
budget.monthly_distribution = "_Test Distribution"
budget.company = "_Test Company"
@@ -299,7 +297,7 @@
"account": "_Test Account Cost for Goods Sold - _TC",
"budget_amount": 100000
})
-
+
if args.applicable_on_material_request:
budget.applicable_on_material_request = 1
budget.action_if_annual_budget_exceeded_on_mr = args.action_if_annual_budget_exceeded_on_mr or 'Warn'
diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
index 4683c7a..9bf5887 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
@@ -150,7 +150,7 @@
accounts_dict = {}
for account in accounts:
accounts_dict.setdefault(account["account_name"], account)
- if account["parent_account"] and accounts_dict[account["parent_account"]]:
+ if account["parent_account"] and accounts_dict.get(account["parent_account"]):
accounts_dict[account["parent_account"]]["is_group"] = 1
message = validate_root(accounts_dict)
diff --git a/erpnext/accounts/doctype/cost_center/cost_center.json b/erpnext/accounts/doctype/cost_center/cost_center.json
index 4da21f1..ff55c21 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center.json
+++ b/erpnext/accounts/doctype/cost_center/cost_center.json
@@ -1,457 +1,171 @@
{
- "allow_copy": 1,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:cost_center_name",
- "beta": 0,
- "creation": "2013-01-23 19:57:17",
- "custom": 0,
- "description": "Track separate Income and Expense for product verticals or divisions.",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
+ "allow_copy": 1,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:cost_center_name",
+ "creation": "2013-01-23 19:57:17",
+ "description": "Track separate Income and Expense for product verticals or divisions.",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+ "sb0",
+ "cost_center_name",
+ "cost_center_number",
+ "parent_cost_center",
+ "company",
+ "cb0",
+ "is_group",
+ "enabled",
+ "lft",
+ "rgt",
+ "old_parent"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sb0",
- "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
- },
+ "fieldname": "sb0",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "cost_center_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Cost Center Name",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "cost_center_name",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "cost_center_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Cost Center Name",
+ "no_copy": 1,
+ "oldfieldname": "cost_center_name",
+ "oldfieldtype": "Data",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "cost_center_number",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Cost Center Number",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "cost_center_number",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Cost Center Number",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "parent_cost_center",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Parent Cost Center",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "parent_cost_center",
- "oldfieldtype": "Link",
- "options": "Cost Center",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "parent_cost_center",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_list_view": 1,
+ "label": "Parent Cost Center",
+ "oldfieldname": "parent_cost_center",
+ "oldfieldtype": "Link",
+ "options": "Cost Center",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "company_name",
- "oldfieldtype": "Link",
- "options": "Company",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 1,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Company",
+ "oldfieldname": "company_name",
+ "oldfieldtype": "Link",
+ "options": "Company",
+ "remember_last_selected_value": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "cb0",
- "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,
- "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,
+ "fieldname": "cb0",
+ "fieldtype": "Column Break",
"width": "50%"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "fieldname": "is_group",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Is Group",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "is_group",
+ "fieldtype": "Check",
+ "label": "Is Group"
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "lft",
- "fieldtype": "Int",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "lft",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "lft",
- "oldfieldtype": "Int",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "lft",
+ "fieldtype": "Int",
+ "hidden": 1,
+ "label": "lft",
+ "no_copy": 1,
+ "oldfieldname": "lft",
+ "oldfieldtype": "Int",
+ "print_hide": 1,
+ "report_hide": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "rgt",
- "fieldtype": "Int",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "rgt",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "rgt",
- "oldfieldtype": "Int",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "rgt",
+ "fieldtype": "Int",
+ "hidden": 1,
+ "label": "rgt",
+ "no_copy": 1,
+ "oldfieldname": "rgt",
+ "oldfieldtype": "Int",
+ "print_hide": 1,
+ "report_hide": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "old_parent",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "old_parent",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "old_parent",
- "oldfieldtype": "Data",
- "options": "Cost Center",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "old_parent",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "ignore_user_permissions": 1,
+ "label": "old_parent",
+ "no_copy": 1,
+ "oldfieldname": "old_parent",
+ "oldfieldtype": "Data",
+ "options": "Cost Center",
+ "print_hide": 1,
+ "report_hide": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "enabled",
+ "fieldtype": "Check",
+ "label": "Enabled"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-money",
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "menu_index": 0,
- "modified": "2018-04-26 15:26:25.325778",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Cost Center",
- "owner": "Administrator",
+ ],
+ "icon": "fa fa-money",
+ "idx": 1,
+ "modified": "2019-08-22 15:05:05.559862",
+ "modified_by": "sammish.thundiyil@gmail.com",
+ "module": "Accounts",
+ "name": "Cost Center",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 1,
- "role": "Auditor",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
+ "export": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Auditor"
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User"
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 0,
- "role": "Sales User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
+ "read": 1,
+ "role": "Sales User"
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 0,
- "role": "Purchase User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "read": 1,
+ "role": "Purchase User"
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "search_fields": "parent_cost_center, is_group",
- "show_name_in_global_search": 1,
- "sort_order": "ASC",
- "track_changes": 0,
- "track_seen": 0
-}
\ No newline at end of file
+ ],
+ "quick_entry": 1,
+ "search_fields": "parent_cost_center, is_group",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "ASC"
+}
diff --git a/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json b/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json
index 8d7ed74..04d6303 100644
--- a/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json
+++ b/erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json
@@ -8,7 +8,8 @@
"customer",
"column_break_3",
"posting_date",
- "outstanding_amount"
+ "outstanding_amount",
+ "debit_to"
],
"fields": [
{
@@ -48,10 +49,18 @@
{
"fieldname": "column_break_3",
"fieldtype": "Column Break"
+ },
+ {
+ "fetch_from": "sales_invoice.debit_to",
+ "fieldname": "debit_to",
+ "fieldtype": "Link",
+ "label": "Debit to",
+ "options": "Account",
+ "read_only": 1
}
],
"istable": 1,
- "modified": "2019-05-30 19:27:29.436153",
+ "modified": "2019-08-07 15:13:55.808349",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Discounted Invoice",
diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js
index 5563f03..f1f88a8 100644
--- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js
+++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js
@@ -13,41 +13,57 @@
};
});
- frm.events.filter_accounts("bank_account", frm, {"account_type": "Bank"});
- frm.events.filter_accounts("bank_charges_account", frm, {"root_type": "Expense"});
- frm.events.filter_accounts("short_term_loan", frm, {"root_type": "Liability"});
- frm.events.filter_accounts("accounts_receivable_credit", frm, {"account_type": "Receivable"});
- frm.events.filter_accounts("accounts_receivable_discounted", frm, {"account_type": "Receivable"});
- frm.events.filter_accounts("accounts_receivable_unpaid", frm, {"account_type": "Receivable"});
+
+ frm.events.filter_accounts("bank_account", frm, [["account_type", "=", "Bank"]]);
+ frm.events.filter_accounts("bank_charges_account", frm, [["root_type", "=", "Expense"]]);
+ frm.events.filter_accounts("short_term_loan", frm, [["root_type", "=", "Liability"]]);
+ frm.events.filter_accounts("accounts_receivable_discounted", frm, [["account_type", "=", "Receivable"]]);
+ frm.events.filter_accounts("accounts_receivable_credit", frm, [["account_type", "=", "Receivable"]]);
+ frm.events.filter_accounts("accounts_receivable_unpaid", frm, [["account_type", "=", "Receivable"]]);
},
filter_accounts: (fieldname, frm, addl_filters) => {
- let filters = {
- "company": frm.doc.company,
- "is_group": 0
- };
- if(addl_filters) Object.assign(filters, addl_filters);
+ let filters = [
+ ["company", "=", frm.doc.company],
+ ["is_group", "=", 0]
+ ];
+ if(addl_filters){
+ filters = $.merge(filters , addl_filters);
+ }
frm.set_query(fieldname, () => { return { "filters": filters }; });
},
+ refresh_filters: (frm) =>{
+ let invoice_accounts = Object.keys(frm.doc.invoices).map(function(key) {
+ return frm.doc.invoices[key].debit_to;
+ });
+ let filters = [
+ ["account_type", "=", "Receivable"],
+ ["name", "not in", invoice_accounts]
+ ];
+ frm.events.filter_accounts("accounts_receivable_credit", frm, filters);
+ frm.events.filter_accounts("accounts_receivable_discounted", frm, filters);
+ frm.events.filter_accounts("accounts_receivable_unpaid", frm, filters);
+ },
+
refresh: (frm) => {
frm.events.show_general_ledger(frm);
- if(frm.doc.docstatus === 0) {
+ if (frm.doc.docstatus === 0) {
frm.add_custom_button(__('Get Invoices'), function() {
frm.events.get_invoices(frm);
});
}
- if(frm.doc.docstatus === 1 && frm.doc.status !== "Settled") {
- if(frm.doc.status == "Sanctioned") {
+ if (frm.doc.docstatus === 1 && frm.doc.status !== "Settled") {
+ if (frm.doc.status == "Sanctioned") {
frm.add_custom_button(__('Disburse Loan'), function() {
frm.events.create_disbursement_entry(frm);
}).addClass("btn-primary");
}
- if(frm.doc.status == "Disbursed") {
+ if (frm.doc.status == "Disbursed") {
frm.add_custom_button(__('Close Loan'), function() {
frm.events.close_loan(frm);
}).addClass("btn-primary");
@@ -64,7 +80,7 @@
},
set_end_date: (frm) => {
- if(frm.doc.loan_start_date && frm.doc.loan_period) {
+ if (frm.doc.loan_start_date && frm.doc.loan_period) {
let end_date = frappe.datetime.add_days(frm.doc.loan_start_date, frm.doc.loan_period);
frm.set_value("loan_end_date", end_date);
}
@@ -132,6 +148,7 @@
frm.doc.invoices = frm.doc.invoices.filter(row => row.sales_invoice);
let row = frm.add_child("invoices");
$.extend(row, v);
+ frm.events.refresh_filters(frm);
});
refresh_field("invoices");
}
@@ -190,8 +207,10 @@
frappe.ui.form.on('Discounted Invoice', {
sales_invoice: (frm) => {
frm.events.calculate_total_amount(frm);
+ frm.events.refresh_filters(frm);
},
invoices_remove: (frm) => {
frm.events.calculate_total_amount(frm);
+ frm.events.refresh_filters(frm);
}
-});
\ No newline at end of file
+});
diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
index 29475d5..36c2911 100644
--- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
+++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
@@ -12,6 +12,7 @@
class InvoiceDiscounting(AccountsController):
def validate(self):
self.validate_mandatory()
+ self.validate_invoices()
self.calculate_total_amount()
self.set_status()
self.set_end_date()
@@ -24,6 +25,15 @@
if self.docstatus == 1 and not (self.loan_start_date and self.loan_period):
frappe.throw(_("Loan Start Date and Loan Period are mandatory to save the Invoice Discounting"))
+ def validate_invoices(self):
+ discounted_invoices = [record.sales_invoice for record in
+ frappe.get_all("Discounted Invoice",fields = ["sales_invoice"], filters= {"docstatus":1})]
+
+ for record in self.invoices:
+ if record.sales_invoice in discounted_invoices:
+ frappe.throw("Row({0}): {1} is already discounted in {2}"
+ .format(record.idx, frappe.bold(record.sales_invoice), frappe.bold(record.parent)))
+
def calculate_total_amount(self):
self.total_amount = sum([flt(d.outstanding_amount) for d in self.invoices])
@@ -212,7 +222,8 @@
name as sales_invoice,
customer,
posting_date,
- outstanding_amount
+ outstanding_amount,
+ debit_to
from `tabSales Invoice` si
where
docstatus = 1
diff --git a/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py b/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py
index 56a0d2f..4a7406e 100644
--- a/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py
+++ b/erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py
@@ -49,7 +49,6 @@
# cancel and delete
for d in [si_redeem, si_original]:
d.cancel()
- frappe.delete_doc('Sales Invoice', d.name)
def test_loyalty_points_earned_multiple_tier(self):
frappe.db.set_value("Customer", "Test Loyalty Customer", "loyalty_program", "Test Multiple Loyalty")
@@ -91,7 +90,6 @@
# cancel and delete
for d in [si_redeem, si_original]:
d.cancel()
- frappe.delete_doc('Sales Invoice', d.name)
def test_cancel_sales_invoice(self):
''' cancelling the sales invoice should cancel the earned points'''
@@ -143,7 +141,6 @@
d.cancel()
except frappe.TimestampMismatchError:
frappe.get_doc('Sales Invoice', d.name).cancel()
- frappe.delete_doc('Sales Invoice', d.name)
def test_loyalty_points_for_dashboard(self):
doc = frappe.get_doc('Customer', 'Test Loyalty Customer')
diff --git a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.json b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.json
index 9609e3d..f3df1f0 100644
--- a/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.json
+++ b/erpnext/accounts/doctype/mode_of_payment/mode_of_payment.json
@@ -1,171 +1,74 @@
{
- "allow_copy": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "field:mode_of_payment",
- "beta": 0,
- "creation": "2012-12-04 17:49:20",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
- "engine": "InnoDB",
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "field:mode_of_payment",
+ "creation": "2012-12-04 17:49:20",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+ "mode_of_payment",
+ "enabled",
+ "type",
+ "accounts"
+ ],
"fields": [
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "mode_of_payment",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Mode of Payment",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "mode_of_payment",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "mode_of_payment",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Mode of Payment",
+ "oldfieldname": "mode_of_payment",
+ "oldfieldtype": "Data",
+ "reqd": 1,
+ "unique": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "type",
- "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,
- "label": "Type",
- "length": 0,
- "no_copy": 0,
- "options": "Cash\nBank\nGeneral",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "type",
+ "fieldtype": "Select",
+ "in_standard_filter": 1,
+ "label": "Type",
+ "options": "Cash\nBank\nGeneral"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "accounts",
- "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": "Accounts",
- "length": 0,
- "no_copy": 0,
- "options": "Mode of Payment Account",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
+ "fieldname": "accounts",
+ "fieldtype": "Table",
+ "label": "Accounts",
+ "options": "Mode of Payment Account"
+ },
+ {
+ "default": "1",
+ "fieldname": "enabled",
+ "fieldtype": "Check",
+ "label": "Enabled"
}
- ],
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-credit-card",
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
-
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2017-02-17 16:31:34.207683",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Mode of Payment",
- "owner": "harshada@webnotestech.com",
+ ],
+ "icon": "fa fa-credit-card",
+ "idx": 1,
+ "modified": "2019-08-14 14:58:42.079115",
+ "modified_by": "sammish.thundiyil@gmail.com",
+ "module": "Accounts",
+ "name": "Mode of Payment",
+ "owner": "harshada@webnotestech.com",
"permissions": [
{
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 1,
- "role": "Accounts User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User"
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 1,
- "sort_order": "ASC",
- "track_changes": 0,
- "track_seen": 0
+ ],
+ "quick_entry": 1,
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "ASC"
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index f17b2cb..172d537 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -720,7 +720,7 @@
$.each(frm.doc.references || [], function(i, row) {
row.allocated_amount = 0 //If allocate payment amount checkbox is unchecked, set zero to allocate amount
- if(frappe.flags.allocate_payment_amount){
+ if(frappe.flags.allocate_payment_amount != 0){
if(row.outstanding_amount > 0 && allocated_positive_outstanding > 0) {
if(row.outstanding_amount >= allocated_positive_outstanding) {
row.allocated_amount = allocated_positive_outstanding;
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index e0d3e7a..3529900 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -126,7 +126,7 @@
if not self.party:
frappe.throw(_("Party is mandatory"))
- _party_name = "title" if self.party_type == "Student" else self.party_type.lower() + "_name"
+ _party_name = "title" if self.party_type in ("Student", "Shareholder") else self.party_type.lower() + "_name"
self.party_name = frappe.db.get_value(self.party_type, self.party, _party_name)
if self.party:
@@ -624,8 +624,8 @@
data = negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed
if not data:
- frappe.msgprint(_("No outstanding invoices found for the {0} <b>{1}</b> which qualify the filters you have specified.")
- .format(args.get("party_type").lower(), args.get("party")))
+ frappe.msgprint(_("No outstanding invoices found for the {0} {1} which qualify the filters you have specified.")
+ .format(args.get("party_type").lower(), frappe.bold(args.get("party"))))
return data
@@ -683,8 +683,8 @@
order_list = []
for d in orders:
- if not (d.outstanding_amount >= filters.get("outstanding_amt_greater_than")
- and d.outstanding_amount <= filters.get("outstanding_amt_less_than")):
+ if not (flt(d.outstanding_amount) >= flt(filters.get("outstanding_amt_greater_than"))
+ and flt(d.outstanding_amount) <= flt(filters.get("outstanding_amt_less_than"))):
continue
d["voucher_type"] = voucher_type
@@ -947,10 +947,15 @@
paid_amount = abs(outstanding_amount)
if bank_amount:
received_amount = bank_amount
+ else:
+ received_amount = paid_amount * doc.conversion_rate
else:
received_amount = abs(outstanding_amount)
if bank_amount:
paid_amount = bank_amount
+ else:
+ # if party account currency and bank currency is different then populate paid amount as well
+ paid_amount = received_amount * doc.conversion_rate
pe = frappe.new_doc("Payment Entry")
pe.payment_type = payment_type
diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js
index f2f00ce..ce9cfe5 100644
--- a/erpnext/accounts/doctype/payment_order/payment_order.js
+++ b/erpnext/accounts/doctype/payment_order/payment_order.js
@@ -66,6 +66,7 @@
get_query_filters: {
bank: frm.doc.bank,
docstatus: 1,
+ payment_type: ("!=", "Receive"),
bank_account: frm.doc.company_bank_account,
paid_from: frm.doc.account,
payment_order_status: ["=", "Initiated"],
diff --git a/erpnext/accounts/doctype/payment_order/regional/india.js b/erpnext/accounts/doctype/payment_order/regional/india.js
deleted file mode 100644
index 66d0f60..0000000
--- a/erpnext/accounts/doctype/payment_order/regional/india.js
+++ /dev/null
@@ -1,29 +0,0 @@
-frappe.ui.form.on('Payment Order', {
- refresh: function(frm) {
- if (frm.doc.docstatus==1 && frm.doc.payment_order_type==='Payment Entry') {
- frm.add_custom_button(__('Generate Text File'), function() {
- frm.trigger("generate_text_and_download_file");
- });
- }
- },
- generate_text_and_download_file: (frm) => {
- return frappe.call({
- method: "erpnext.regional.india.bank_remittance.generate_report",
- args: {
- name: frm.doc.name
- },
- freeze: true,
- callback: function(r) {
- {
- frm.reload_doc();
- const a = document.createElement('a');
- let file_obj = r.message;
- a.href = file_obj.file_url;
- a.target = '_blank';
- a.download = file_obj.file_name;
- a.click();
- }
- }
- });
- }
-});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index b74eed5..4665d75 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -93,7 +93,7 @@
and `tab{doc}`.is_return = 1 and `tabGL Entry`.against_voucher_type = %(voucher_type)s
and `tab{doc}`.docstatus = 1 and `tabGL Entry`.party = %(party)s
and `tabGL Entry`.party_type = %(party_type)s and `tabGL Entry`.account = %(account)s
- GROUP BY `tabSales Invoice`.name
+ GROUP BY `tab{doc}`.name
Having
amount > 0
""".format(doc=voucher_type, dr_or_cr=dr_or_cr, reconciled_dr_or_cr=reconciled_dr_or_cr), {
@@ -257,11 +257,8 @@
voucher_type = ('Credit Note'
if d.voucher_type == 'Sales Invoice' else 'Debit Note')
- dr_or_cr = ('credit_in_account_currency'
- if d.reference_type == 'Sales Invoice' else 'debit_in_account_currency')
-
reconcile_dr_or_cr = ('debit_in_account_currency'
- if dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency')
+ if d.dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency')
jv = frappe.get_doc({
"doctype": "Journal Entry",
@@ -272,8 +269,7 @@
'account': d.account,
'party': d.party,
'party_type': d.party_type,
- reconcile_dr_or_cr: (abs(d.allocated_amount)
- if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)),
+ d.dr_or_cr: abs(d.allocated_amount),
'reference_type': d.against_voucher_type,
'reference_name': d.against_voucher
},
@@ -281,7 +277,8 @@
'account': d.account,
'party': d.party,
'party_type': d.party_type,
- dr_or_cr: abs(d.allocated_amount),
+ reconcile_dr_or_cr: (abs(d.allocated_amount)
+ if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)),
'reference_type': d.voucher_type,
'reference_name': d.voucher_no
}
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.js b/erpnext/accounts/doctype/payment_request/payment_request.js
index a455e74..e2510f6 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.js
+++ b/erpnext/accounts/doctype/payment_request/payment_request.js
@@ -1,7 +1,6 @@
-cur_frm.add_fetch("payment_gateway", "payment_account", "payment_account")
-cur_frm.add_fetch("payment_gateway", "payment_gateway", "payment_gateway")
-cur_frm.add_fetch("payment_gateway", "message", "message")
-cur_frm.add_fetch("payment_gateway", "payment_url_message", "payment_url_message")
+cur_frm.add_fetch("payment_gateway_account", "payment_account", "payment_account")
+cur_frm.add_fetch("payment_gateway_account", "payment_gateway", "payment_gateway")
+cur_frm.add_fetch("payment_gateway_account", "message", "message")
frappe.ui.form.on("Payment Request", "onload", function(frm, dt, dn){
if (frm.doc.reference_doctype) {
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 73758be..eda59ab 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -20,7 +20,7 @@
if self.get("__islocal"):
self.status = 'Draft'
self.validate_reference_document()
- self.validate_payment_request()
+ self.validate_payment_request_amount()
self.validate_currency()
self.validate_subscription_details()
@@ -28,10 +28,19 @@
if not self.reference_doctype or not self.reference_name:
frappe.throw(_("To create a Payment Request reference document is required"))
- def validate_payment_request(self):
- if frappe.db.get_value("Payment Request", {"reference_name": self.reference_name,
- "name": ("!=", self.name), "status": ("not in", ["Initiated", "Paid"]), "docstatus": 1}, "name"):
- frappe.throw(_("Payment Request already exists {0}".format(self.reference_name)))
+ def validate_payment_request_amount(self):
+ existing_payment_request_amount = \
+ get_existing_payment_request_amount(self.reference_doctype, self.reference_name)
+
+ if existing_payment_request_amount:
+ ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
+ if (hasattr(ref_doc, "order_type") \
+ and getattr(ref_doc, "order_type") != "Shopping Cart"):
+ ref_amount = get_amount(ref_doc)
+
+ if existing_payment_request_amount + flt(self.grand_total)> ref_amount:
+ frappe.throw(_("Total Payment Request amount cannot be greater than {0} amount"
+ .format(self.reference_doctype)))
def validate_currency(self):
ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
@@ -271,7 +280,7 @@
args = frappe._dict(args)
ref_doc = frappe.get_doc(args.dt, args.dn)
- grand_total = get_amount(ref_doc, args.dt)
+ grand_total = get_amount(ref_doc)
if args.loyalty_points and args.dt == "Sales Order":
from erpnext.accounts.doctype.loyalty_program.loyalty_program import validate_loyalty_points
loyalty_amount = validate_loyalty_points(ref_doc, int(args.loyalty_points))
@@ -281,17 +290,25 @@
gateway_account = get_gateway_details(args) or frappe._dict()
- existing_payment_request = frappe.db.get_value("Payment Request",
- {"reference_doctype": args.dt, "reference_name": args.dn, "docstatus": ["!=", 2]})
-
bank_account = (get_party_bank_account(args.get('party_type'), args.get('party'))
if args.get('party_type') else '')
+ existing_payment_request = None
+ if args.order_type == "Shopping Cart":
+ existing_payment_request = frappe.db.get_value("Payment Request",
+ {"reference_doctype": args.dt, "reference_name": args.dn, "docstatus": ("!=", 2)})
+
if existing_payment_request:
frappe.db.set_value("Payment Request", existing_payment_request, "grand_total", grand_total, update_modified=False)
pr = frappe.get_doc("Payment Request", existing_payment_request)
-
else:
+ if args.order_type != "Shopping Cart":
+ existing_payment_request_amount = \
+ get_existing_payment_request_amount(args.dt, args.dn)
+
+ if existing_payment_request_amount:
+ grand_total -= existing_payment_request_amount
+
pr = frappe.new_doc("Payment Request")
pr.update({
"payment_gateway_account": gateway_account.get("name"),
@@ -327,8 +344,9 @@
return pr.as_dict()
-def get_amount(ref_doc, dt):
+def get_amount(ref_doc):
"""get amount based on doctype"""
+ dt = ref_doc.doctype
if dt in ["Sales Order", "Purchase Order"]:
grand_total = flt(ref_doc.grand_total) - flt(ref_doc.advance_paid)
@@ -347,6 +365,17 @@
else:
frappe.throw(_("Payment Entry is already created"))
+def get_existing_payment_request_amount(ref_dt, ref_dn):
+ existing_payment_request_amount = frappe.db.sql("""
+ select sum(grand_total)
+ from `tabPayment Request`
+ where
+ reference_doctype = %s
+ and reference_name = %s
+ and docstatus = 1
+ """, (ref_dt, ref_dn))
+ return flt(existing_payment_request_amount[0][0]) if existing_payment_request_amount else 0
+
def get_gateway_details(args):
"""return gateway and payment account of default payment gateway"""
if args.get("payment_gateway"):
diff --git a/erpnext/accounts/doctype/payment_request/test_payment_request.py b/erpnext/accounts/doctype/payment_request/test_payment_request.py
index bfd6d54..188ab0a 100644
--- a/erpnext/accounts/doctype/payment_request/test_payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/test_payment_request.py
@@ -37,12 +37,12 @@
def setUp(self):
if not frappe.db.get_value("Payment Gateway", payment_gateway["gateway"], "name"):
frappe.get_doc(payment_gateway).insert(ignore_permissions=True)
-
+
for method in payment_method:
- if not frappe.db.get_value("Payment Gateway Account", {"payment_gateway": method["payment_gateway"],
+ if not frappe.db.get_value("Payment Gateway Account", {"payment_gateway": method["payment_gateway"],
"currency": method["currency"]}, "name"):
frappe.get_doc(method).insert(ignore_permissions=True)
-
+
def test_payment_request_linkings(self):
so_inr = make_sales_order(currency="INR")
pr = make_payment_request(dt="Sales Order", dn=so_inr.name, recipient_id="saurabh@erpnext.com")
@@ -100,3 +100,23 @@
self.assertEqual(expected_gle[gle.account][1], gle.debit)
self.assertEqual(expected_gle[gle.account][2], gle.credit)
self.assertEqual(expected_gle[gle.account][3], gle.against_voucher)
+
+ def test_multiple_payment_entries_against_sales_order(self):
+ # Make Sales Order, grand_total = 1000
+ so = make_sales_order()
+
+ # Payment Request amount = 200
+ pr1 = make_payment_request(dt="Sales Order", dn=so.name,
+ recipient_id="nabin@erpnext.com", return_doc=1)
+ pr1.grand_total = 200
+ pr1.submit()
+
+ # Make a 2nd Payment Request
+ pr2 = make_payment_request(dt="Sales Order", dn=so.name,
+ recipient_id="nabin@erpnext.com", return_doc=1)
+
+ self.assertEqual(pr2.grand_total, 800)
+
+ # Try to make Payment Request more than SO amount, should give validation
+ pr2.grand_total = 900
+ self.assertRaises(frappe.ValidationError, pr2.save)
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index e2f99d6..7e23793 100755
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -227,8 +227,8 @@
customers = [frappe._dict({'name': customers})]
for data in customers:
- contact = frappe.db.sql(""" select email_id, phone, mobile_no from `tabContact`
- where is_primary_contact =1 and name in
+ contact = frappe.db.sql(""" select email_id, phone from `tabContact`
+ where is_primary_contact=1 and name in
(select parent from `tabDynamic Link` where link_doctype = 'Customer' and link_name = %s
and parenttype = 'Contact')""", data.name, as_dict=1)
if contact:
@@ -307,7 +307,7 @@
# example: {'Consulting Services': {'Excise 12 - TS': '12.000'}}
itemwise_tax = {}
- taxes = frappe.db.sql(""" select parent, tax_type, tax_rate from `tabItem Tax`""", as_dict=1)
+ taxes = frappe.db.sql(""" select parent, tax_type, tax_rate from `tabItem Tax Template Detail`""", as_dict=1)
for tax in taxes:
if tax.parent not in itemwise_tax:
@@ -432,7 +432,6 @@
return cust_id
-
def make_customer_and_address(customers):
customers_list = []
for customer, data in iteritems(customers):
@@ -449,7 +448,6 @@
frappe.db.commit()
return customers_list
-
def add_customer(data):
customer = data.get('full_name') or data.get('customer')
if frappe.db.exists("Customer", customer.strip()):
@@ -466,21 +464,18 @@
frappe.db.commit()
return customer_doc.name
-
def get_territory(data):
if data.get('territory'):
return data.get('territory')
return frappe.db.get_single_value('Selling Settings','territory') or _('All Territories')
-
def get_customer_group(data):
if data.get('customer_group'):
return data.get('customer_group')
return frappe.db.get_single_value('Selling Settings', 'customer_group') or frappe.db.get_value('Customer Group', {'is_group': 0}, 'name')
-
def make_contact(args, customer):
if args.get('email_id') or args.get('phone'):
name = frappe.db.get_value('Dynamic Link',
@@ -506,7 +501,6 @@
doc.flags.ignore_mandatory = True
doc.save(ignore_permissions=True)
-
def make_address(args, customer):
if not args.get('address_line1'):
return
@@ -521,7 +515,10 @@
address = frappe.get_doc('Address', name)
else:
address = frappe.new_doc('Address')
- address.country = frappe.get_cached_value('Company', args.get('company'), 'country')
+ if args.get('company'):
+ address.country = frappe.get_cached_value('Company',
+ args.get('company'), 'country')
+
address.append('links', {
'link_doctype': 'Customer',
'link_name': customer
@@ -533,7 +530,6 @@
address.flags.ignore_mandatory = True
address.save(ignore_permissions=True)
-
def make_email_queue(email_queue):
name_list = []
for key, data in iteritems(email_queue):
@@ -550,7 +546,6 @@
return name_list
-
def validate_item(doc):
for item in doc.get('items'):
if not frappe.db.exists('Item', item.get('item_code')):
@@ -569,7 +564,6 @@
item_doc.save(ignore_permissions=True)
frappe.db.commit()
-
def submit_invoice(si_doc, name, doc, name_list):
try:
si_doc.insert()
@@ -585,7 +579,6 @@
return name_list
-
def save_invoice(doc, name, name_list):
try:
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 74e9186..3c85210 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -158,7 +158,7 @@
cur_frm.meta._default_print_format = cur_frm.meta.default_print_format;
cur_frm.meta.default_print_format = cur_frm.pos_print_format;
}
- } else if(cur_frm.doc.is_return) {
+ } else if(cur_frm.doc.is_return && !cur_frm.meta.default_print_format) {
if(cur_frm.return_print_format) {
cur_frm.meta._default_print_format = cur_frm.meta.default_print_format;
cur_frm.meta.default_print_format = cur_frm.return_print_format;
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 8742300..abbac77 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -78,6 +78,7 @@
self.so_dn_required()
self.validate_proj_cust()
+ self.validate_pos_return()
self.validate_with_previous_doc()
self.validate_uom_is_integer("stock_uom", "stock_qty")
self.validate_uom_is_integer("uom", "qty")
@@ -199,6 +200,16 @@
if "Healthcare" in active_domains:
manage_invoice_submit_cancel(self, "on_submit")
+ def validate_pos_return(self):
+
+ if self.is_pos and self.is_return:
+ total_amount_in_payments = 0
+ for payment in self.payments:
+ total_amount_in_payments += payment.amount
+ invoice_total = self.rounded_total or self.grand_total
+ if total_amount_in_payments < invoice_total:
+ frappe.throw(_("Total payments amount can't be greater than {}".format(-invoice_total)))
+
def validate_pos_paid_amount(self):
if len(self.payments) == 0 and self.is_pos:
frappe.throw(_("At least one mode of payment is required for POS invoice."))
@@ -293,8 +304,10 @@
from erpnext.selling.doctype.customer.customer import check_credit_limit
validate_against_credit_limit = False
- bypass_credit_limit_check_at_sales_order = cint(frappe.get_cached_value("Customer", self.customer,
- "bypass_credit_limit_check_at_sales_order"))
+ bypass_credit_limit_check_at_sales_order = frappe.db.get_value("Customer Credit Limit",
+ filters={'parent': self.customer, 'parenttype': 'Customer', 'company': self.company},
+ fieldname=["bypass_credit_limit_check"])
+
if bypass_credit_limit_check_at_sales_order:
validate_against_credit_limit = True
@@ -1499,4 +1512,4 @@
"outstanding_amount": invoice.outstanding_amount
})
- return invoice_discounting
\ No newline at end of file
+ return invoice_discounting
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index dff5594..4f253b6 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -818,7 +818,6 @@
self.assertEqual(expected_gl_entries[i][2], gle.credit)
si.cancel()
- frappe.delete_doc('Sales Invoice', si.name)
gle = frappe.db.sql("""select * from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
diff --git a/erpnext/accounts/doctype/share_transfer/share_transfer.py b/erpnext/accounts/doctype/share_transfer/share_transfer.py
index 1a1f036..e95c694 100644
--- a/erpnext/accounts/doctype/share_transfer/share_transfer.py
+++ b/erpnext/accounts/doctype/share_transfer/share_transfer.py
@@ -86,17 +86,23 @@
frappe.throw(_('The field From Shareholder cannot be blank'))
if self.from_folio_no is None or self.from_folio_no is '':
self.to_folio_no = self.autoname_folio(self.to_shareholder)
+ if self.asset_account is None:
+ frappe.throw(_('The field Asset Account cannot be blank'))
elif (self.transfer_type == 'Issue'):
self.from_shareholder = ''
if self.to_shareholder is None or self.to_shareholder == '':
frappe.throw(_('The field To Shareholder cannot be blank'))
if self.to_folio_no is None or self.to_folio_no is '':
self.to_folio_no = self.autoname_folio(self.to_shareholder)
+ if self.asset_account is None:
+ frappe.throw(_('The field Asset Account cannot be blank'))
else:
if self.from_shareholder is None or self.to_shareholder is None:
frappe.throw(_('The fields From Shareholder and To Shareholder cannot be blank'))
if self.to_folio_no is None or self.to_folio_no is '':
self.to_folio_no = self.autoname_folio(self.to_shareholder)
+ if self.equity_or_liability_account is None:
+ frappe.throw(_('The field Equity/Liability Account cannot be blank'))
if self.from_shareholder == self.to_shareholder:
frappe.throw(_('The seller and the buyer cannot be the same'))
if self.no_of_shares != self.to_no - self.from_no + 1:
diff --git a/erpnext/accounts/doctype/share_transfer/test_share_transfer.py b/erpnext/accounts/doctype/share_transfer/test_share_transfer.py
index f1cf31b..910dfd0 100644
--- a/erpnext/accounts/doctype/share_transfer/test_share_transfer.py
+++ b/erpnext/accounts/doctype/share_transfer/test_share_transfer.py
@@ -15,67 +15,74 @@
frappe.db.sql("delete from `tabShare Balance`")
share_transfers = [
{
- "doctype" : "Share Transfer",
- "transfer_type" : "Issue",
- "date" : "2018-01-01",
- "to_shareholder" : "SH-00001",
- "share_type" : "Equity",
- "from_no" : 1,
- "to_no" : 500,
- "no_of_shares" : 500,
- "rate" : 10,
- "company" : "_Test Company"
+ "doctype" : "Share Transfer",
+ "transfer_type" : "Issue",
+ "date" : "2018-01-01",
+ "to_shareholder" : "SH-00001",
+ "share_type" : "Equity",
+ "from_no" : 1,
+ "to_no" : 500,
+ "no_of_shares" : 500,
+ "rate" : 10,
+ "company" : "_Test Company",
+ "asset_account" : "Cash - _TC",
+ "equity_or_liability_account": "Creditors - _TC"
},
{
- "doctype" : "Share Transfer",
- "transfer_type" : "Transfer",
- "date" : "2018-01-02",
- "from_shareholder" : "SH-00001",
- "to_shareholder" : "SH-00002",
- "share_type" : "Equity",
- "from_no" : 101,
- "to_no" : 200,
- "no_of_shares" : 100,
- "rate" : 15,
- "company" : "_Test Company"
+ "doctype" : "Share Transfer",
+ "transfer_type" : "Transfer",
+ "date" : "2018-01-02",
+ "from_shareholder" : "SH-00001",
+ "to_shareholder" : "SH-00002",
+ "share_type" : "Equity",
+ "from_no" : 101,
+ "to_no" : 200,
+ "no_of_shares" : 100,
+ "rate" : 15,
+ "company" : "_Test Company",
+ "equity_or_liability_account": "Creditors - _TC"
},
{
- "doctype" : "Share Transfer",
- "transfer_type" : "Transfer",
- "date" : "2018-01-03",
- "from_shareholder" : "SH-00001",
- "to_shareholder" : "SH-00003",
- "share_type" : "Equity",
- "from_no" : 201,
- "to_no" : 500,
- "no_of_shares" : 300,
- "rate" : 20,
- "company" : "_Test Company"
+ "doctype" : "Share Transfer",
+ "transfer_type" : "Transfer",
+ "date" : "2018-01-03",
+ "from_shareholder" : "SH-00001",
+ "to_shareholder" : "SH-00003",
+ "share_type" : "Equity",
+ "from_no" : 201,
+ "to_no" : 500,
+ "no_of_shares" : 300,
+ "rate" : 20,
+ "company" : "_Test Company",
+ "equity_or_liability_account": "Creditors - _TC"
},
{
- "doctype" : "Share Transfer",
- "transfer_type" : "Transfer",
- "date" : "2018-01-04",
- "from_shareholder" : "SH-00003",
- "to_shareholder" : "SH-00002",
- "share_type" : "Equity",
- "from_no" : 201,
- "to_no" : 400,
- "no_of_shares" : 200,
- "rate" : 15,
- "company" : "_Test Company"
+ "doctype" : "Share Transfer",
+ "transfer_type" : "Transfer",
+ "date" : "2018-01-04",
+ "from_shareholder" : "SH-00003",
+ "to_shareholder" : "SH-00002",
+ "share_type" : "Equity",
+ "from_no" : 201,
+ "to_no" : 400,
+ "no_of_shares" : 200,
+ "rate" : 15,
+ "company" : "_Test Company",
+ "equity_or_liability_account": "Creditors - _TC"
},
{
- "doctype" : "Share Transfer",
- "transfer_type" : "Purchase",
- "date" : "2018-01-05",
- "from_shareholder" : "SH-00003",
- "share_type" : "Equity",
- "from_no" : 401,
- "to_no" : 500,
- "no_of_shares" : 100,
- "rate" : 25,
- "company" : "_Test Company"
+ "doctype" : "Share Transfer",
+ "transfer_type" : "Purchase",
+ "date" : "2018-01-05",
+ "from_shareholder" : "SH-00003",
+ "share_type" : "Equity",
+ "from_no" : 401,
+ "to_no" : 500,
+ "no_of_shares" : 100,
+ "rate" : 25,
+ "company" : "_Test Company",
+ "asset_account" : "Cash - _TC",
+ "equity_or_liability_account": "Creditors - _TC"
}
]
for d in share_transfers:
@@ -84,30 +91,33 @@
def test_invalid_share_transfer(self):
doc = frappe.get_doc({
- "doctype" : "Share Transfer",
- "transfer_type" : "Transfer",
- "date" : "2018-01-05",
- "from_shareholder" : "SH-00003",
- "to_shareholder" : "SH-00002",
- "share_type" : "Equity",
- "from_no" : 1,
- "to_no" : 100,
- "no_of_shares" : 100,
- "rate" : 15,
- "company" : "_Test Company"
+ "doctype" : "Share Transfer",
+ "transfer_type" : "Transfer",
+ "date" : "2018-01-05",
+ "from_shareholder" : "SH-00003",
+ "to_shareholder" : "SH-00002",
+ "share_type" : "Equity",
+ "from_no" : 1,
+ "to_no" : 100,
+ "no_of_shares" : 100,
+ "rate" : 15,
+ "company" : "_Test Company",
+ "equity_or_liability_account": "Creditors - _TC"
})
self.assertRaises(ShareDontExists, doc.insert)
doc = frappe.get_doc({
- "doctype" : "Share Transfer",
- "transfer_type" : "Purchase",
- "date" : "2018-01-02",
- "from_shareholder" : "SH-00001",
- "share_type" : "Equity",
- "from_no" : 1,
- "to_no" : 200,
- "no_of_shares" : 200,
- "rate" : 15,
- "company" : "_Test Company"
+ "doctype" : "Share Transfer",
+ "transfer_type" : "Purchase",
+ "date" : "2018-01-02",
+ "from_shareholder" : "SH-00001",
+ "share_type" : "Equity",
+ "from_no" : 1,
+ "to_no" : 200,
+ "no_of_shares" : 200,
+ "rate" : 15,
+ "company" : "_Test Company",
+ "asset_account" : "Cash - _TC",
+ "equity_or_liability_account": "Creditors - _TC"
})
self.assertRaises(ShareDontExists, doc.insert)
diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
index 638e57e..b146899 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
@@ -48,7 +48,6 @@
#delete invoices to avoid clashing
for d in invoices:
d.cancel()
- frappe.delete_doc("Purchase Invoice", d.name)
def test_single_threshold_tds(self):
invoices = []
@@ -83,7 +82,6 @@
# delete invoices to avoid clashing
for d in invoices:
d.cancel()
- frappe.delete_doc("Purchase Invoice", d.name)
def test_single_threshold_tds_with_previous_vouchers(self):
invoices = []
@@ -102,7 +100,6 @@
# delete invoices to avoid clashing
for d in invoices:
d.cancel()
- frappe.delete_doc("Purchase Invoice", d.name)
def create_purchase_invoice(**args):
# return sales invoice doc object
diff --git a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
index 36c9399..bd4b4d7 100644
--- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
+++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py
@@ -124,8 +124,6 @@
'txt': '%%%s%%' % amount
}, as_dict=True)
- frappe.errprint(journal_entries)
-
if transaction.credit > 0:
sales_invoices = frappe.db.sql("""
SELECT
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index 3834c96..0cd8bfe 100755
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -816,7 +816,6 @@
contact = me.contacts[data.name];
if(reg.test(data.name.toLowerCase())
|| reg.test(data.customer_name.toLowerCase())
- || (contact && reg.test(contact["mobile_no"]))
|| (contact && reg.test(contact["phone"]))
|| (data.customer_group && reg.test(data.customer_group.toLowerCase()))){
return data;
@@ -834,7 +833,6 @@
if(contact && !c['phone']) {
c["phone"] = contact["phone"];
c["email_id"] = contact["email_id"];
- c["mobile_no"] = contact["mobile_no"];
}
me.customers_mapper.push({
@@ -844,10 +842,9 @@
customer_group: c.customer_group,
territory: c.territory,
phone: contact ? contact["phone"] : '',
- mobile_no: contact ? contact["mobile_no"] : '',
email_id: contact ? contact["email_id"] : '',
searchtext: ['customer_name', 'customer_group', 'name', 'value',
- 'label', 'email_id', 'phone', 'mobile_no']
+ 'label', 'email_id', 'phone']
.map(key => c[key]).join(' ')
.toLowerCase()
});
@@ -1121,7 +1118,8 @@
if (key) {
return $.grep(this.items_list, function (item) {
if (search_status) {
- if (in_list(me.batch_no_data[item.item_code], me.search_item.$input.val())) {
+ if (me.batch_no_data[item.item_code] &&
+ in_list(me.batch_no_data[item.item_code], me.search_item.$input.val())) {
search_status = false;
return me.item_batch_no[item.item_code] = me.search_item.$input.val()
} else if (me.serial_no_data[item.item_code]
@@ -1129,7 +1127,8 @@
search_status = false;
me.item_serial_no[item.item_code] = [me.search_item.$input.val(), me.serial_no_data[item.item_code][me.search_item.$input.val()]]
return true
- } else if (in_list(me.barcode_data[item.item_code], me.search_item.$input.val())) {
+ } else if (me.barcode_data[item.item_code] &&
+ in_list(me.barcode_data[item.item_code], me.search_item.$input.val())) {
search_status = false;
return true;
} else if (reg.test(item.item_code.toLowerCase()) || (item.description && reg.test(item.description.toLowerCase())) ||
@@ -1692,20 +1691,13 @@
if(this.si_docs) {
this.si_docs.forEach((row) => {
- existing_pos_list.push(Object.keys(row));
+ existing_pos_list.push(Object.keys(row)[0]);
});
}
if (this.frm.doc.offline_pos_name
- && in_list(existing_pos_list, this.frm.doc.offline_pos_name)) {
+ && in_list(existing_pos_list, cstr(this.frm.doc.offline_pos_name))) {
this.update_invoice()
- //to retrieve and set the default payment
- invoice_data[this.frm.doc.offline_pos_name] = this.frm.doc;
- invoice_data[this.frm.doc.offline_pos_name].payments[0].amount = this.frm.doc.net_total
- invoice_data[this.frm.doc.offline_pos_name].payments[0].base_amount = this.frm.doc.net_total
-
- this.frm.doc.paid_amount = this.frm.doc.net_total
- this.frm.doc.outstanding_amount = 0
} else if(!this.frm.doc.offline_pos_name) {
this.frm.doc.offline_pos_name = frappe.datetime.now_datetime();
this.frm.doc.posting_date = frappe.datetime.get_today();
@@ -1762,18 +1754,11 @@
this.si_docs = this.get_submitted_invoice() || [];
this.email_queue_list = this.get_email_queue() || {};
this.customers_list = this.get_customers_details() || {};
- if(this.customer_doc) {
- this.freeze = this.customer_doc.display
- }
- freeze_screen = this.freeze_screen || false;
-
- if ((this.si_docs.length || this.email_queue_list || this.customers_list) && !this.freeze) {
- this.freeze = true;
-
+ if (this.si_docs.length || this.email_queue_list || this.customers_list) {
frappe.call({
method: "erpnext.accounts.doctype.sales_invoice.pos.make_invoice",
- freeze: freeze_screen,
+ freeze: true,
args: {
doc_list: me.si_docs,
email_queue_list: me.email_queue_list,
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index cb94722..59936d5 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -292,8 +292,11 @@
party_account_currency = frappe.db.get_value("Account", account.account, "account_currency", cache=True)
existing_gle_currency = get_party_gle_currency(doc.doctype, doc.name, account.company)
- company_default_currency = frappe.get_cached_value('Company',
- frappe.db.get_default("Company"), "default_currency")
+ if frappe.db.get_default("Company"):
+ company_default_currency = frappe.get_cached_value('Company',
+ frappe.db.get_default("Company"), "default_currency")
+ else:
+ company_default_currency = frappe.db.get_value('Company', account.company, "default_currency")
if existing_gle_currency and party_account_currency != existing_gle_currency:
frappe.throw(_("Accounting entries have already been made in currency {0} for company {1}. Please select a receivable or payable account with currency {0}.").format(existing_gle_currency, account.company))
@@ -365,7 +368,7 @@
.format(formatdate(default_due_date)))
@frappe.whitelist()
-def get_address_tax_category(tax_category, billing_address=None, shipping_address=None):
+def get_address_tax_category(tax_category=None, billing_address=None, shipping_address=None):
addr_tax_category_from = frappe.db.get_single_value("Accounts Settings", "determine_address_tax_category_from")
if addr_tax_category_from == "Shipping Address":
if shipping_address:
@@ -469,7 +472,9 @@
# fetch and append data from Activity Log
data += frappe.db.sql("""select {fields}
from `tabActivity Log`
- where reference_doctype={doctype} and reference_name={name}
+ where (reference_doctype="{doctype}" and reference_name="{name}")
+ or (timeline_doctype in ("{doctype}") and timeline_name="{name}")
+ or (reference_doctype in ("Quotation", "Opportunity") and timeline_name="{name}")
and status!='Success' and creation > {after}
{group_by} order by creation desc
""".format(doctype=frappe.db.escape(doctype), name=frappe.db.escape(name), fields=fields,
@@ -605,4 +610,4 @@
.format(("credit") if party_type == "Customer" else "debit", cond) , party_type)
if data:
- return frappe._dict(data)
\ No newline at end of file
+ return frappe._dict(data)
diff --git a/erpnext/accounts/print_format/point_of_sale/point_of_sale.json b/erpnext/accounts/print_format/point_of_sale/point_of_sale.json
index a8bedc2..c0c50cb 100644
--- a/erpnext/accounts/print_format/point_of_sale/point_of_sale.json
+++ b/erpnext/accounts/print_format/point_of_sale/point_of_sale.json
@@ -1,22 +1,23 @@
{
- "align_labels_right": 0,
- "creation": "2016-05-05 17:16:18.564460",
- "custom_format": 1,
- "disabled": 0,
- "doc_type": "Sales Invoice",
- "docstatus": 0,
- "doctype": "Print Format",
- "font": "Default",
- "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ company }}<br>\n\t{{ __(\"POS No : \") }} {{ offline_pos_name }}<br>\n</p>\n<p>\n\t<b>{{ __(\"Customer\") }}:</b> {{ customer }}<br>\n</p>\n\n<p>\n\t<b>{{ __(\"Date\") }}:</b> {{ dateutil.global_date_format(posting_date) }}<br>\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ __(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{% for item in items %}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_name }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ format_number(item.qty, null,precision(\"difference\")) }}<br>@ {{ format_currency(item.rate, currency) }}</td>\n\t\t\t<td class=\"text-right\">{{ format_currency(item.amount, currency) }}</td>\n\t\t</tr>\n\t\t{% endfor %}\n\t</tbody>\n</table>\n\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% for row in taxes %}\n\t\t{% if not row.included_in_print_rate %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if discount_amount %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Qty Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ qty_total }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n\n\n<hr>\n<p>{{ terms }}</p>\n<p class=\"text-center\">{{ __(\"Thank you, please visit again.\") }}</p>",
- "idx": 0,
- "line_breaks": 0,
- "modified": "2018-03-21 09:10:16.693732",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Point of Sale",
- "owner": "Administrator",
- "print_format_builder": 0,
- "print_format_type": "Js",
- "show_section_headings": 0,
+ "align_labels_right": 0,
+ "creation": "2016-05-05 17:16:18.564460",
+ "custom_format": 1,
+ "disabled": 0,
+ "doc_type": "Sales Invoice",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ company }}<br>\n\t{{ __(\"POS No : \") }} {{ offline_pos_name }}<br>\n</p>\n<p>\n\t<b>{{ __(\"Customer\") }}:</b> {{ customer }}<br>\n</p>\n\n<p>\n\t<b>{{ __(\"Date\") }}:</b> {{ dateutil.global_date_format(posting_date) }}<br>\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ __(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{% for item in items %}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_name }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ format_number(item.qty, null,precision(\"difference\")) }}<br>@ {{ format_currency(item.rate, currency) }}</td>\n\t\t\t<td class=\"text-right\">{{ format_currency(item.amount, currency) }}</td>\n\t\t</tr>\n\t\t{% endfor %}\n\t</tbody>\n</table>\n\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% for row in taxes %}\n\t\t{% if not row.included_in_print_rate %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if discount_amount %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Qty Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ qty_total }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n\n\n<hr>\n<p>{{ terms }}</p>\n<p class=\"text-center\">{{ __(\"Thank you, please visit again.\") }}</p>",
+ "idx": 0,
+ "line_breaks": 0,
+ "modified": "2019-09-05 17:20:30.726659",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Point of Sale",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "JS",
+ "raw_printing": 0,
+ "show_section_headings": 0,
"standard": "Yes"
}
\ No newline at end of file
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html
index 192b6d7..791f3f8 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html
@@ -1,275 +1,269 @@
<style>
-.print-format {
- padding: 4mm;
- font-size: 8.0pt !important;
-}
-.print-format td {
- vertical-align:middle !important;
-}
-</style>
+ .print-format {
+ padding: 4mm;
+ font-size: 8.0pt !important;
+ }
+ .print-format td {
+ vertical-align:middle !important;
+ }
+ </style>
-<h2 class="text-center" style="margin-top:0">{%= __(report.report_name) %}</h2>
-<h4 class="text-center">
- {% if (filters.customer_name) { %}
- {%= filters.customer_name %}
- {% } else { %}
- {%= filters.customer || filters.supplier %}
- {% } %}
-</h4>
-<h6 class="text-center">
- {% if (filters.tax_id) { %}
- {%= __("Tax Id: ")%} {%= filters.tax_id %}
+ <h2 class="text-center" style="margin-top:0">{%= __(report.report_name) %}</h2>
+ <h4 class="text-center">
+ {% if (filters.customer_name) { %}
+ {%= filters.customer_name %}
+ {% } else { %}
+ {%= filters.customer || filters.supplier %}
{% } %}
-</h6>
-<h5 class="text-center">
- {%= __(filters.ageing_based_on) %}
- {%= __("Until") %}
- {%= frappe.datetime.str_to_user(filters.report_date) %}
-</h5>
+ </h4>
+ <h6 class="text-center">
+ {% if (filters.tax_id) { %}
+ {%= __("Tax Id: ")%} {%= filters.tax_id %}
+ {% } %}
+ </h6>
+ <h5 class="text-center">
+ {%= __(filters.ageing_based_on) %}
+ {%= __("Until") %}
+ {%= frappe.datetime.str_to_user(filters.report_date) %}
+ </h5>
-<div class="clearfix">
- <div class="pull-left">
- {% if(filters.payment_terms) { %}
- <strong>{%= __("Payment Terms") %}:</strong> {%= filters.payment_terms %}
- {% } %}
+ <div class="clearfix">
+ <div class="pull-left">
+ {% if(filters.payment_terms) { %}
+ <strong>{%= __("Payment Terms") %}:</strong> {%= filters.payment_terms %}
+ {% } %}
+ </div>
+ <div class="pull-right">
+ {% if(filters.credit_limit) { %}
+ <strong>{%= __("Credit Limit") %}:</strong> {%= format_currency(filters.credit_limit) %}
+ {% } %}
+ </div>
</div>
- <div class="pull-right">
- {% if(filters.credit_limit) { %}
- <strong>{%= __("Credit Limit") %}:</strong> {%= format_currency(filters.credit_limit) %}
+
+ {% if(filters.show_future_payments) { %}
+ {% var balance_row = data.slice(-1).pop();
+ var range1 = report.columns[11].label;
+ var range2 = report.columns[12].label;
+ var range3 = report.columns[13].label;
+ var range4 = report.columns[14].label;
+ var range5 = report.columns[15].label;
+ %}
+ {% if(balance_row) { %}
+ <table class="table table-bordered table-condensed">
+ <caption class="text-right">(Amount in {%= data[0]["currency"] || "" %})</caption>
+ <colgroup>
+ <col style="width: 30mm;">
+ <col style="width: 18mm;">
+ <col style="width: 18mm;">
+ <col style="width: 18mm;">
+ <col style="width: 18mm;">
+ <col style="width: 18mm;">
+ <col style="width: 18mm;">
+ <col style="width: 18mm;">
+ </colgroup>
+
+ <thead>
+ <tr>
+ <th>{%= __(" ") %}</th>
+ <th>{%= __(range1) %}</th>
+ <th>{%= __(range2) %}</th>
+ <th>{%= __(range3) %}</th>
+ <th>{%= __(range4) %}</th>
+ <th>{%= __(range5) %}</th>
+ <th>{%= __("Total") %}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>{%= __("Total Outstanding") %}</td>
+ <td class="text-right">{%= format_number(balance_row["range1"], null, 2) %}</td>
+ <td class="text-right">{%= format_currency(balance_row["range2"]) %}</td>
+ <td class="text-right">{%= format_currency(balance_row["range3"]) %}</td>
+ <td class="text-right">{%= format_currency(balance_row["range4"]) %}</td>
+ <td class="text-right">{%= format_currency(balance_row["range5"]) %}</td>
+ <td class="text-right">
+ {%= format_currency(flt(balance_row["outstanding"]), data[data.length-1]["currency"]) %}
+ </td>
+ </tr>
+ <td>{%= __("Future Payments") %}</td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ <td class="text-right">
+ {%= format_currency(flt(balance_row[("future_amount")]), data[data.length-1]["currency"]) %}
+ </td>
+ <tr class="cvs-footer">
+ <th class="text-left">{%= __("Cheques Required") %}</th>
+ <th></th>
+ <th></th>
+ <th></th>
+ <th></th>
+ <th></th>
+ <th class="text-right">
+ {%= format_currency(flt(balance_row["outstanding"] - balance_row[("future_amount")]), data[data.length-1]["currency"]) %}</th>
+ </tr>
+ </tbody>
+
+ </table>
+ {% } %}
{% } %}
- </div>
-</div>
-
-{% if(filters.show_pdc_in_print) { %}
- {% var balance_row = data.slice(-1).pop();
- var range1 = report.columns[11].label;
- var range2 = report.columns[12].label;
- var range3 = report.columns[13].label;
- var range4 = report.columns[14].label;
- var range5 = report.columns[15].label;
- var range6 = report.columns[16].label;
- %}
- {% if(balance_row) { %}
- <table class="table table-bordered table-condensed">
- <caption class="text-right">(Amount in {%= data[0][__("currency")] || "" %})</caption>
- <colgroup>
- <col style="width: 30mm;">
- <col style="width: 18mm;">
- <col style="width: 18mm;">
- <col style="width: 18mm;">
- <col style="width: 18mm;">
- <col style="width: 18mm;">
- <col style="width: 18mm;">
- <col style="width: 18mm;">
- <col style="width: 18mm;">
- </colgroup>
-
+ <table class="table table-bordered">
<thead>
<tr>
- <th>{%= __(" ") %}</th>
- <th>{%= __(range1) %}</th>
- <th>{%= __(range2) %}</th>
- <th>{%= __(range3) %}</th>
- <th>{%= __(range4) %}</th>
- <th>{%= __(range5) %}</th>
- <th>{%= __(range6) %}</th>
- <th>{%= __("Total") %}</th>
+ {% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
+ <th style="width: 10%">{%= __("Date") %}</th>
+ <th style="width: 4%">{%= __("Age (Days)") %}</th>
+
+ {% if(report.report_name === "Accounts Receivable" && filters.show_sales_person) { %}
+ <th style="width: 14%">{%= __("Reference") %}</th>
+ <th style="width: 10%">{%= __("Sales Person") %}</th>
+ {% } else { %}
+ <th style="width: 24%">{%= __("Reference") %}</th>
+ {% } %}
+ {% if(!filters.show_future_payments) { %}
+ <th style="width: 20%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
+ {% } %}
+ <th style="width: 10%; text-align: right">{%= __("Invoiced Amount") %}</th>
+ {% if(!filters.show_future_payments) { %}
+ <th style="width: 10%; text-align: right">{%= __("Paid Amount") %}</th>
+ <th style="width: 10%; text-align: right">{%= report.report_name === "Accounts Receivable" ? __('Credit Note') : __('Debit Note') %}</th>
+ {% } %}
+ <th style="width: 10%; text-align: right">{%= __("Outstanding Amount") %}</th>
+ {% if(filters.show_future_payments) { %}
+ {% if(report.report_name === "Accounts Receivable") { %}
+ <th style="width: 12%">{%= __("Customer LPO No.") %}</th>
+ {% } %}
+ <th style="width: 10%">{%= __("Future Payment Ref") %}</th>
+ <th style="width: 10%">{%= __("Future Payment Amount") %}</th>
+ <th style="width: 10%">{%= __("Remaining Balance") %}</th>
+ {% } %}
+ {% } else { %}
+ <th style="width: 40%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
+ <th style="width: 15%">{%= __("Total Invoiced Amount") %}</th>
+ <th style="width: 15%">{%= __("Total Paid Amount") %}</th>
+ <th style="width: 15%">{%= report.report_name === "Accounts Receivable Summary" ? __('Credit Note Amount') : __('Debit Note Amount') %}</th>
+ <th style="width: 15%">{%= __("Total Outstanding Amount") %}</th>
+ {% } %}
</tr>
</thead>
<tbody>
- <tr>
- <td>{%= __("Total Outstanding") %}</td>
- <td class="text-right">{%= format_number(balance_row[range1], null, 2) %}</td>
- <td class="text-right">{%= format_currency(balance_row[range2]) %}</td>
- <td class="text-right">{%= format_currency(balance_row[range3]) %}</td>
- <td class="text-right">{%= format_currency(balance_row[range4]) %}</td>
- <td class="text-right">{%= format_currency(balance_row[range5]) %}</td>
- <td class="text-right">{%= format_currency(balance_row[range6]) %}</td>
- <td class="text-right">
- {%= format_currency(flt(balance_row[("outstanding_amount")]), data[data.length-1]["currency"]) %}
- </td>
- </tr>
- <td>{%= __("PDC/LC") %}</td>
- <td></td>
- <td></td>
- <td></td>
- <td></td>
- <td></td>
- <td></td>
- <td class="text-right">
- {%= format_currency(flt(balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %}
- </td>
- <tr class="cvs-footer">
- <th class="text-left">{%= __("Cheques Required") %}</th>
- <th></th>
- <th></th>
- <th></th>
- <th></th>
- <th></th>
- <th></th>
- <th class="text-right">
- {%= format_currency(flt(balance_row[("outstanding_amount")]-balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %}</th>
- </tr>
- </tbody>
-
- </table>
- {% } %}
-{% } %}
-<table class="table table-bordered">
- <thead>
- <tr>
- {% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
- <th style="width: 10%">{%= __("Date") %}</th>
- <th style="width: 4%">{%= __("Age (Days)") %}</th>
-
- {% if(report.report_name === "Accounts Receivable" && filters.show_sales_person_in_print) { %}
- <th style="width: 14%">{%= __("Reference") %}</th>
- <th style="width: 10%">{%= __("Sales Person") %}</th>
- {% } else { %}
- <th style="width: 24%">{%= __("Reference") %}</th>
- {% } %}
- {% if(!filters.show_pdc_in_print) { %}
- <th style="width: 20%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
- {% } %}
- <th style="width: 10%; text-align: right">{%= __("Invoiced Amount") %}</th>
- {% if(!filters.show_pdc_in_print) { %}
- <th style="width: 10%; text-align: right">{%= __("Paid Amount") %}</th>
- <th style="width: 10%; text-align: right">{%= report.report_name === "Accounts Receivable" ? __('Credit Note') : __('Debit Note') %}</th>
- {% } %}
- <th style="width: 10%; text-align: right">{%= __("Outstanding Amount") %}</th>
- {% if(filters.show_pdc_in_print) { %}
- {% if(report.report_name === "Accounts Receivable") { %}
- <th style="width: 12%">{%= __("Customer LPO No.") %}</th>
- {% } %}
- <th style="width: 10%">{%= __("PDC/LC Ref") %}</th>
- <th style="width: 10%">{%= __("PDC/LC Amount") %}</th>
- <th style="width: 10%">{%= __("Remaining Balance") %}</th>
- {% } %}
- {% } else { %}
- <th style="width: 40%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
- <th style="width: 15%">{%= __("Total Invoiced Amount") %}</th>
- <th style="width: 15%">{%= __("Total Paid Amount") %}</th>
- <th style="width: 15%">{%= report.report_name === "Accounts Receivable Summary" ? __('Credit Note Amount') : __('Debit Note Amount') %}</th>
- <th style="width: 15%">{%= __("Total Outstanding Amount") %}</th>
- {% } %}
- </tr>
- </thead>
- <tbody>
- {% for(var i=0, l=data.length; i<l; i++) { %}
- <tr>
- {% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
- {% if(data[i][__("Customer")] || data[i][__("Supplier")]) { %}
- <td>{%= frappe.datetime.str_to_user(data[i]["posting_date"]) %}</td>
- <td style="text-align: right">{%= data[i][__("Age (Days)")] %}</td>
- <td>
- {% if(!filters.show_pdc_in_print) { %}
- {%= data[i]["voucher_type"] %}
- <br>
- {% } %}
- {%= data[i]["voucher_no"] %}
- </td>
-
- {% if(report.report_name === "Accounts Receivable" && filters.show_sales_person_in_print) { %}
- <td>{%= data[i]["sales_person"] %}</td>
- {% } %}
-
- {% if(!filters.show_pdc_in_print) { %}
- <td>
- {% if(!(filters.customer || filters.supplier)) { %}
- {%= data[i][__("Customer")] || data[i][__("Supplier")] %}
- {% if(data[i][__("Customer Name")] && data[i][__("Customer Name")] != data[i][__("Customer")]) { %}
- <br> {%= data[i][__("Customer Name")] %}
- {% } else if(data[i][__("Supplier Name")] != data[i][__("Supplier")]) { %}
- <br> {%= data[i][__("Supplier Name")] %}
+ {% for(var i=0, l=data.length; i<l; i++) { %}
+ <tr>
+ {% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
+ {% if(data[i]["party"]) { %}
+ <td>{%= frappe.datetime.str_to_user(data[i]["posting_date"]) %}</td>
+ <td style="text-align: right">{%= data[i]["age"] %}</td>
+ <td>
+ {% if(!filters.show_future_payments) { %}
+ {%= data[i]["voucher_type"] %}
+ <br>
{% } %}
+ {%= data[i]["voucher_no"] %}
+ </td>
+
+ {% if(report.report_name === "Accounts Receivable" && filters.show_sales_person) { %}
+ <td>{%= data[i]["sales_person"] %}</td>
{% } %}
- <div>
- {% if data[i][__("Remarks")] %}
- {%= __("Remarks") %}:
- {%= data[i][__("Remarks")] %}
- {% } %}
- </div>
- </td>
- {% } %}
- <td style="text-align: right">
- {%= format_currency(data[i]["invoiced_amount"], data[i]["currency"]) %}</td>
-
- {% if(!filters.show_pdc_in_print) { %}
- <td style="text-align: right">
- {%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %}</td>
- <td style="text-align: right">
- {%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["debit_note"], data[i]["currency"]) %}</td>
- {% } %}
- <td style="text-align: right">
- {%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %}</td>
-
- {% if(filters.show_pdc_in_print) { %}
- {% if(report.report_name === "Accounts Receivable") { %}
- <td style="text-align: right">
- {%= data[i]["po_no"] %}</td>
- {% } %}
- <td style="text-align: right">{%= data[i][("pdc/lc_ref")] %}</td>
- <td style="text-align: right">{%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %}</td>
- <td style="text-align: right">{%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %}</td>
- {% } %}
- {% } else { %}
- <td></td>
- {% if(!filters.show_pdc_in_print) { %}
- <td></td>
- {% } %}
- {% if(report.report_name === "Accounts Receivable" && filters.show_sales_person_in_print) { %}
- <td></td>
- {% } %}
- <td></td>
- <td style="text-align: right"><b>{%= __("Total") %}</b></td>
- <td style="text-align: right">
- {%= format_currency(data[i]["invoiced_amount"], data[i]["currency"] ) %}</td>
-
- {% if(!filters.show_pdc_in_print) { %}
- <td style="text-align: right">
- {%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %}</td>
- <td style="text-align: right">{%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["debit_note"], data[i]["currency"]) %} </td>
- {% } %}
- <td style="text-align: right">
- {%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %}</td>
-
- {% if(filters.show_pdc_in_print) { %}
- {% if(report.report_name === "Accounts Receivable") { %}
- <td style="text-align: right">
- {%= data[i][__("Customer LPO")] %}</td>
- {% } %}
- <td style="text-align: right">{%= data[i][("pdc/lc_ref")] %}</td>
- <td style="text-align: right">{%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %}</td>
- <td style="text-align: right">{%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %}</td>
- {% } %}
- {% } %}
- {% } else { %}
- {% if(data[i][__("Customer")] || data[i][__("Supplier")]|| " ") { %}
- {% if((data[i][__("Customer")] || data[i][__("Supplier")]) != __("'Total'")) { %}
+ {% if(!filters.show_future_payments) { %}
<td>
{% if(!(filters.customer || filters.supplier)) { %}
- {%= data[i][__("Customer")] || data[i][__("Supplier")] %}
- {% if(data[i][__("Customer Name")] && data[i][__("Customer Name")] != data[i][__("Customer")]) { %}
- <br> {%= data[i][__("Customer Name")] %}
- {% } else if(data[i][__("Supplier Name")] != data[i][__("Supplier")]) { %}
- <br> {%= data[i][__("Supplier Name")] %}
+ {%= data[i]["party"] %}
+ {% if(data[i]["customer_name"] && data[i]["customer_name"] != data[i]["party"]) { %}
+ <br> {%= data[i]["customer_name"] %}
+ {% } else if(data[i]["supplier_name"] != data[i]["party"]) { %}
+ <br> {%= data[i]["supplier_name"] %}
{% } %}
{% } %}
- <br>{%= __("Remarks") %}:
- {%= data[i][__("Remarks")] %}
+ <div>
+ {% if data[i]["remarks"] %}
+ {%= __("Remarks") %}:
+ {%= data[i]["remarks"] %}
+ {% } %}
+ </div>
</td>
+ {% } %}
+
+ <td style="text-align: right">
+ {%= format_currency(data[i]["invoiced"], data[i]["currency"]) %}</td>
+
+ {% if(!filters.show_future_payments) { %}
+ <td style="text-align: right">
+ {%= format_currency(data[i]["paid"], data[i]["currency"]) %}</td>
+ <td style="text-align: right">
+ {%= format_currency(data[i]["credit_note"], data[i]["currency"]) %}</td>
+ {% } %}
+ <td style="text-align: right">
+ {%= format_currency(data[i]["outstanding"], data[i]["currency"]) %}</td>
+
+ {% if(filters.show_future_payments) { %}
+ {% if(report.report_name === "Accounts Receivable") { %}
+ <td style="text-align: right">
+ {%= data[i]["po_no"] %}</td>
+ {% } %}
+ <td style="text-align: right">{%= data[i]["future_ref"] %}</td>
+ <td style="text-align: right">{%= format_currency(data[i]["future_amount"], data[i]["currency"]) %}</td>
+ <td style="text-align: right">{%= format_currency(data[i]["remaining_balance"], data[i]["currency"]) %}</td>
+ {% } %}
{% } else { %}
- <td><b>{%= __("Total") %}</b></td>
+ <td></td>
+ {% if(!filters.show_future_payments) { %}
+ <td></td>
+ {% } %}
+ {% if(report.report_name === "Accounts Receivable" && filters.show_sales_person) { %}
+ <td></td>
+ {% } %}
+ <td></td>
+ <td style="text-align: right"><b>{%= __("Total") %}</b></td>
+ <td style="text-align: right">
+ {%= format_currency(data[i]["invoiced"], data[i]["currency"] ) %}</td>
+
+ {% if(!filters.show_future_payments) { %}
+ <td style="text-align: right">
+ {%= format_currency(data[i]["paid"], data[i]["currency"]) %}</td>
+ <td style="text-align: right">{%= format_currency(data[i]["credit_note"], data[i]["currency"]) %} </td>
+ {% } %}
+ <td style="text-align: right">
+ {%= format_currency(data[i]["outstanding"], data[i]["currency"]) %}</td>
+
+ {% if(filters.show_future_payments) { %}
+ {% if(report.report_name === "Accounts Receivable") { %}
+ <td style="text-align: right">
+ {%= data[i]["po_no"] %}</td>
+ {% } %}
+ <td style="text-align: right">{%= data[i]["future_ref"] %}</td>
+ <td style="text-align: right">{%= format_currency(data[i]["future_amount"], data[i]["currency"]) %}</td>
+ <td style="text-align: right">{%= format_currency(data[i]["remaining_balance"], data[i]["currency"]) %}</td>
+ {% } %}
{% } %}
- <td style="text-align: right">{%= format_currency(data[i][("total_invoiced_amt")], data[i]["currency"]) %}</td>
- <td style="text-align: right">{%= format_currency(data[i][("total_paid_amt")], data[i]["currency"]) %}</td>
- <td style="text-align: right">{%= report.report_name === "Accounts Receivable Summary" ? format_currency(data[i][__("credit_note_amt")], data[i]["currency"]) : format_currency(data[i][__("debit_note_amt")], data[i]["currency"]) %}</td>
- <td style="text-align: right">{%= format_currency(data[i][("total_outstanding_amt")], data[i]["currency"]) %}</td>
+ {% } else { %}
+ {% if(data[i]["party"]|| " ") { %}
+ {% if((data[i]["party"]) != __("'Total'")) { %}
+ <td>
+ {% if(!(filters.customer || filters.supplier)) { %}
+ {%= data[i]["party"] %}
+ {% if(data[i]["customer_name"] && data[i]["customer_name"] != data[i]["party"]) { %}
+ <br> {%= data[i]["customer_name"] %}
+ {% } else if(data[i]["supplier_name"] != data[i]["party"]) { %}
+ <br> {%= data[i]["supplier_name"] %}
+ {% } %}
+ {% } %}
+ <br>{%= __("Remarks") %}:
+ {%= data[i]["remarks"] %}
+ </td>
+ {% } else { %}
+ <td><b>{%= __("Total") %}</b></td>
+ {% } %}
+ <td style="text-align: right">{%= format_currency(data[i]["invoiced"], data[i]["currency"]) %}</td>
+ <td style="text-align: right">{%= format_currency(data[i]["paid"], data[i]["currency"]) %}</td>
+ <td style="text-align: right">{%= format_currency(data[i]["credit_note"], data[i]["currency"]) %}</td>
+ <td style="text-align: right">{%= format_currency(data[i]["outstanding"], data[i]["currency"]) %}</td>
+ {% } %}
{% } %}
+ </tr>
{% } %}
- </tr>
- {% } %}
- </tbody>
-</table>
-<p class="text-right text-muted">{{ __("Printed On ") }}{%= frappe.datetime.str_to_user(frappe.datetime.get_datetime_as_string()) %}</p>
+ </tbody>
+ </table>
+ <p class="text-right text-muted">{{ __("Printed On ") }}{%= frappe.datetime.str_to_user(frappe.datetime.get_datetime_as_string()) %}</p>
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
index 4551973..228be18 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
@@ -130,13 +130,18 @@
"fieldtype": "Check",
},
{
- "fieldname":"show_pdc_in_print",
- "label": __("Show PDC in Print"),
+ "fieldname":"show_future_payments",
+ "label": __("Show Future Payments"),
"fieldtype": "Check",
},
{
- "fieldname":"show_sales_person_in_print",
- "label": __("Show Sales Person in Print"),
+ "fieldname":"show_delivery_notes",
+ "label": __("Show Delivery Notes"),
+ "fieldtype": "Check",
+ },
+ {
+ "fieldname":"show_sales_person",
+ "label": __("Show Sales Person"),
"fieldtype": "Check",
},
{
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index ecf149b..a7279f7 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -4,9 +4,33 @@
from __future__ import unicode_literals
import frappe, erpnext
from frappe import _, scrub
-from frappe.utils import getdate, nowdate, flt, cint, formatdate, cstr
+from frappe.utils import getdate, nowdate, flt, cint, formatdate, cstr, now, time_diff_in_seconds
+from collections import OrderedDict
+from erpnext.accounts.utils import get_currency_precision
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
+# This report gives a summary of all Outstanding Invoices considering the following
+
+# 1. Invoice can be booked via Sales/Purchase Invoice or Journal Entry
+# 2. Report handles both receivable and payable
+# 3. Key balances for each row are "Invoiced Amount", "Paid Amount", "Credit/Debit Note Amount", "Oustanding Amount"
+# 4. For explicit payment terms in invoice (example: 30% advance, 30% on delivery, 40% post delivery),
+# the invoice will be broken up into multiple rows, one for each payment term
+# 5. If there are payments after the report date (post dated), these will be updated in additional columns
+# for future amount
+# 6. Configurable Ageing Groups (0-30, 30-60 etc) can be set via filters
+# 7. For overpayment against an invoice with payment terms, there will be an additional row
+# 8. Invoice details like Sales Persons, Delivery Notes are also fetched comma separated
+# 9. Report amounts are in "Party Currency" if party is selected, or company currency for multi-party
+# 10. This reports is based on all GL Entries that are made against account_type "Receivable" or "Payable"
+
+def execute(filters=None):
+ args = {
+ "party_type": "Customer",
+ "naming_by": ["Selling Settings", "cust_master_name"],
+ }
+ return ReceivablePayableReport(filters).run(args)
+
class ReceivablePayableReport(object):
def __init__(self, filters=None):
self.filters = frappe._dict(filters or {})
@@ -16,455 +40,429 @@
else self.filters.report_date
def run(self, args):
- party_naming_by = frappe.db.get_value(args.get("naming_by")[0], None, args.get("naming_by")[1])
- columns = self.get_columns(party_naming_by, args)
- data = self.get_data(party_naming_by, args)
- chart = self.get_chart_data(columns, data)
- return columns, data, None, chart
+ self.filters.update(args)
+ self.set_defaults()
+ self.party_naming_by = frappe.db.get_value(args.get("naming_by")[0], None, args.get("naming_by")[1])
+ self.get_columns()
+ self.get_data()
+ self.get_chart_data()
+ return self.columns, self.data, None, self.chart
- def get_columns(self, party_naming_by, args):
- columns = []
- columns.append({
- "label": _("Posting Date"),
- "fieldtype": "Date",
- "fieldname": "posting_date",
- "width": 90
- })
-
- columns += [_(args.get("party_type")) + ":Link/" + args.get("party_type") + ":200"]
-
- if args.get("party_type") == 'Customer':
- columns.append({
- "label": _("Customer Contact"),
- "fieldtype": "Link",
- "fieldname": "contact",
- "options":"Contact",
- "width": 100
- })
-
- if party_naming_by == "Naming Series":
- columns += [args.get("party_type") + " Name::110"]
-
- columns.append({
- "label": _("Voucher Type"),
- "fieldtype": "Data",
- "fieldname": "voucher_type",
- "width": 110
- })
-
- columns.append({
- "label": _("Voucher No"),
- "fieldtype": "Dynamic Link",
- "fieldname": "voucher_no",
- "width": 110,
- "options": "voucher_type",
- })
-
- columns += [_("Due Date") + ":Date:80"]
-
- if args.get("party_type") == "Supplier":
- columns += [_("Bill No") + "::80", _("Bill Date") + ":Date:80"]
-
- credit_or_debit_note = "Credit Note" if args.get("party_type") == "Customer" else "Debit Note"
-
- if self.filters.based_on_payment_terms:
- columns.append({
- "label": _("Payment Term"),
- "fieldname": "payment_term",
- "fieldtype": "Data",
- "width": 120
- })
- columns.append({
- "label": _("Invoice Grand Total"),
- "fieldname": "invoice_grand_total",
- "fieldtype": "Currency",
- "options": "currency",
- "width": 120
- })
-
- for label in ("Invoiced Amount", "Paid Amount", credit_or_debit_note, "Outstanding Amount"):
- columns.append({
- "label": _(label),
- "fieldname": frappe.scrub(label),
- "fieldtype": "Currency",
- "options": "currency",
- "width": 120
- })
-
- columns += [_("Age (Days)") + ":Int:80"]
-
- self.ageing_col_idx_start = len(columns)
-
- if not "range1" in self.filters:
- self.filters["range1"] = "30"
- if not "range2" in self.filters:
- self.filters["range2"] = "60"
- if not "range3" in self.filters:
- self.filters["range3"] = "90"
- if not "range4" in self.filters:
- self.filters["range4"] = "120"
-
- for label in ("0-{range1}".format(range1=self.filters["range1"]),
- "{range1}-{range2}".format(range1=cint(self.filters["range1"])+ 1, range2=self.filters["range2"]),
- "{range2}-{range3}".format(range2=cint(self.filters["range2"])+ 1, range3=self.filters["range3"]),
- "{range3}-{range4}".format(range3=cint(self.filters["range3"])+ 1, range4=self.filters["range4"]),
- "{range4}-{above}".format(range4=cint(self.filters["range4"])+ 1, above=_("Above"))):
- columns.append({
- "label": label,
- "fieldname":label,
- "fieldtype": "Currency",
- "options": "currency",
- "width": 120
- })
-
- columns += [
- {
- "fieldname": "currency",
- "label": _("Currency"),
- "fieldtype": "Link",
- "options": "Currency",
- "width": 100
- },
- {
- "fieldname": "pdc/lc_ref",
- "label": _("PDC/LC Ref"),
- "fieldtype": "Data",
- "width": 110
- },
- {
- "fieldname": "pdc/lc_amount",
- "label": _("PDC/LC Amount"),
- "fieldtype": "Currency",
- "options": "currency",
- "width": 130
- },
- {
- "fieldname": "remaining_balance",
- "label": _("Remaining Balance"),
- "fieldtype": "Currency",
- "options": "currency",
- "width": 130
- }]
-
- if args.get('party_type') == 'Customer':
- columns += [
- {
- "label": _("Customer LPO"),
- "fieldtype": "Data",
- "fieldname": "po_no",
- "width": 100,
- },
- _("Delivery Note") + ":Data:100",
- _("Territory") + ":Link/Territory:80",
- _("Customer Group") + ":Link/Customer Group:120",
- {
- "label": _("Sales Person"),
- "fieldtype": "Data",
- "fieldname": "sales_person",
- "width": 120,
- }
- ]
- if args.get("party_type") == "Supplier":
- columns += [_("Supplier Group") + ":Link/Supplier Group:80"]
-
- columns.append(_("Remarks") + "::200")
-
- return columns
-
- def get_data(self, party_naming_by, args):
- from erpnext.accounts.utils import get_currency_precision
- self.currency_precision = get_currency_precision() or 2
- self.dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"
-
- future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
-
+ def set_defaults(self):
if not self.filters.get("company"):
- self.filters["company"] = frappe.db.get_single_value('Global Defaults', 'default_company')
-
+ self.filters.company = frappe.db.get_single_value('Global Defaults', 'default_company')
self.company_currency = frappe.get_cached_value('Company', self.filters.get("company"), "default_currency")
+ self.currency_precision = get_currency_precision() or 2
+ self.dr_or_cr = "debit" if self.filters.party_type == "Customer" else "credit"
+ self.party_type = self.filters.party_type
+ self.party_details = {}
+ self.invoices = set()
- return_entries = self.get_return_entries(args.get("party_type"))
+ def get_data(self):
+ t1 = now()
+ self.get_gl_entries()
+ self.voucher_balance = OrderedDict()
+ self.init_voucher_balance() # invoiced, paid, credit_note, outstanding
- data = []
- self.pdc_details = get_pdc_details(args.get("party_type"), self.filters.report_date)
- gl_entries_data = self.get_entries_till(self.filters.report_date, args.get("party_type"))
+ # Build delivery note map against all sales invoices
+ self.build_delivery_note_map()
- if gl_entries_data:
- voucher_nos = [d.voucher_no for d in gl_entries_data] or []
- dn_details = get_dn_details(args.get("party_type"), voucher_nos)
- self.voucher_details = get_voucher_details(args.get("party_type"), voucher_nos, dn_details)
+ # Get invoice details like bill_no, due_date etc for all invoices
+ self.get_invoice_details()
- if self.filters.based_on_payment_terms and gl_entries_data:
- self.payment_term_map = self.get_payment_term_detail(voucher_nos)
+ # fetch future payments against invoices
+ self.get_future_payments()
- for gle in gl_entries_data:
- if self.is_receivable_or_payable(gle, self.dr_or_cr, future_vouchers, return_entries):
- outstanding_amount, credit_note_amount, payment_amount = self.get_outstanding_amount(
- gle,self.filters.report_date, self.dr_or_cr, return_entries)
- temp_outstanding_amt = outstanding_amount
- temp_credit_note_amt = credit_note_amount
+ self.data = []
+ for gle in self.gl_entries:
+ self.update_voucher_balance(gle)
- if abs(outstanding_amount) > 0.1/10**self.currency_precision:
- if self.filters.based_on_payment_terms and self.payment_term_map.get(gle.voucher_no):
- for d in self.payment_term_map.get(gle.voucher_no):
- # Allocate payment amount based on payment terms(FIFO order)
- payment_amount, d.payment_amount = self.allocate_based_on_fifo(payment_amount, d.payment_term_amount)
+ self.build_data()
- term_outstanding_amount = d.payment_term_amount - d.payment_amount
+ def init_voucher_balance(self):
+ # build all keys, since we want to exclude vouchers beyond the report date
+ for gle in self.gl_entries:
+ # get the balance object for voucher_type
+ key = (gle.voucher_type, gle.voucher_no, gle.party)
+ if not key in self.voucher_balance:
+ self.voucher_balance[key] = frappe._dict(
+ voucher_type = gle.voucher_type,
+ voucher_no = gle.voucher_no,
+ party = gle.party,
+ posting_date = gle.posting_date,
+ remarks = gle.remarks,
+ invoiced = 0.0,
+ paid = 0.0,
+ credit_note = 0.0,
+ outstanding = 0.0
+ )
+ self.get_invoices(gle)
- # Allocate credit note based on payment terms(FIFO order)
- credit_note_amount, d.credit_note_amount = self.allocate_based_on_fifo(credit_note_amount, term_outstanding_amount)
+ def get_invoices(self, gle):
+ if gle.voucher_type in ('Sales Invoice', 'Purchase Invoice'):
+ self.invoices.add(gle.voucher_no)
- term_outstanding_amount -= d.credit_note_amount
+ def update_voucher_balance(self, gle):
+ # get the row where this balance needs to be updated
+ # if its a payment, it will return the linked invoice or will be considered as advance
+ row = self.get_voucher_balance(gle)
- row_outstanding = term_outstanding_amount
- # Allocate PDC based on payment terms(FIFO order)
- d.pdc_details, d.pdc_amount = self.allocate_pdc_amount_in_fifo(gle, row_outstanding)
-
- if term_outstanding_amount > 0:
- row = self.prepare_row(party_naming_by, args, gle, term_outstanding_amount,
- d.credit_note_amount, d.due_date, d.payment_amount , d.payment_term_amount,
- d.description, d.pdc_amount, d.pdc_details)
- data.append(row)
-
- if credit_note_amount:
- row = self.prepare_row_without_payment_terms(party_naming_by, args, gle, temp_outstanding_amt,
- temp_credit_note_amt)
- data.append(row)
-
- else:
- row = self.prepare_row_without_payment_terms(party_naming_by, args, gle, outstanding_amount,
- credit_note_amount)
- data.append(row)
- return data
-
- def allocate_pdc_amount_in_fifo(self, gle, row_outstanding):
- pdc_list = self.pdc_details.get((gle.voucher_no, gle.party), [])
-
- pdc_details = []
- pdc_amount = 0
- for pdc in pdc_list:
- if row_outstanding <= pdc.pdc_amount:
- pdc_amount += row_outstanding
- pdc.pdc_amount -= row_outstanding
- if row_outstanding and pdc.pdc_ref and pdc.pdc_date:
- pdc_details.append(cstr(pdc.pdc_ref) + "/" + formatdate(pdc.pdc_date))
- row_outstanding = 0
-
+ # gle_balance will be the total "debit - credit" for receivable type reports and
+ # and vice-versa for payable type reports
+ gle_balance = self.get_gle_balance(gle)
+ if gle_balance > 0:
+ if gle.voucher_type in ('Journal Entry', 'Payment Entry') and gle.against_voucher:
+ # debit against sales / purchase invoice
+ row.paid -= gle_balance
else:
- pdc_amount = pdc.pdc_amount
- if pdc.pdc_amount and pdc.pdc_ref and pdc.pdc_date:
- pdc_details.append(cstr(pdc.pdc_ref) + "/" + formatdate(pdc.pdc_date))
- pdc.pdc_amount = 0
- row_outstanding -= pdc_amount
-
- return pdc_details, pdc_amount
-
- def prepare_row_without_payment_terms(self, party_naming_by, args, gle, outstanding_amount, credit_note_amount):
- pdc_list = self.pdc_details.get((gle.voucher_no, gle.party), [])
- pdc_amount = 0
- pdc_details = []
- for d in pdc_list:
- pdc_amount += flt(d.pdc_amount)
- if pdc_amount and d.pdc_ref and d.pdc_date:
- pdc_details.append(cstr(d.pdc_ref) + "/" + formatdate(d.pdc_date))
-
- row = self.prepare_row(party_naming_by, args, gle, outstanding_amount,
- credit_note_amount, pdc_amount=pdc_amount, pdc_details=pdc_details)
-
- return row
-
-
- def allocate_based_on_fifo(self, total_amount, row_amount):
- allocated_amount = 0
- if row_amount <= total_amount:
- allocated_amount = row_amount
- total_amount -= row_amount
+ # invoice
+ row.invoiced += gle_balance
else:
- allocated_amount = total_amount
- total_amount = 0
+ # payment or credit note for receivables
+ if self.is_invoice(gle):
+ # stand alone debit / credit note
+ row.credit_note -= gle_balance
+ else:
+ # advance / unlinked payment or other adjustment
+ row.paid -= gle_balance
- return total_amount, allocated_amount
+ def get_voucher_balance(self, gle):
+ voucher_balance = None
- def prepare_row(self, party_naming_by, args, gle, outstanding_amount, credit_note_amount,
- due_date=None, paid_amt=None, payment_term_amount=None, payment_term=None, pdc_amount=None, pdc_details=None):
- row = [gle.posting_date, gle.party]
+ if gle.against_voucher:
+ # find invoice
+ voucher_balance = self.voucher_balance.get((gle.against_voucher_type, gle.against_voucher, gle.party))
- # customer / supplier name
- if party_naming_by == "Naming Series":
- row += [self.get_party_name(gle.party_type, gle.party)]
+ if not voucher_balance:
+ # no invoice, this is an invoice / stand-alone payment / credit note
+ voucher_balance = self.voucher_balance.get((gle.voucher_type, gle.voucher_no, gle.party))
- if args.get("party_type") == 'Customer':
- row += [self.get_customer_contact(gle.party_type, gle.party)]
+ return voucher_balance
- # get due date
- if not due_date:
- due_date = self.voucher_details.get(gle.voucher_no, {}).get("due_date", "")
- bill_date = self.voucher_details.get(gle.voucher_no, {}).get("bill_date", "")
+ def build_data(self):
+ # set outstanding for all the accumulated balances
+ # as we can use this to filter out invoices without outstanding
+ for key, row in self.voucher_balance.items():
+ row.outstanding = flt(row.invoiced - row.paid - row.credit_note, self.currency_precision)
+ row.invoice_grand_total = row.invoiced
- row += [gle.voucher_type, gle.voucher_no, due_date]
+ if abs(row.outstanding) > 0.1/10 ** self.currency_precision:
+ # non-zero oustanding, we must consider this row
- # get supplier bill details
- if args.get("party_type") == "Supplier":
- row += [
- self.voucher_details.get(gle.voucher_no, {}).get("bill_no", ""),
- self.voucher_details.get(gle.voucher_no, {}).get("bill_date", "")
- ]
+ if self.is_invoice(row) and self.filters.based_on_payment_terms:
+ # is an invoice, allocate based on fifo
+ # adds a list `payment_terms` which contains new rows for each term
+ self.allocate_outstanding_based_on_payment_terms(row)
- # invoiced and paid amounts
- invoiced_amount = gle.get(self.dr_or_cr) if (gle.get(self.dr_or_cr) > 0) else 0
+ if row.payment_terms:
+ # make separate rows for each payment term
+ for d in row.payment_terms:
+ if d.outstanding > 0:
+ self.append_row(d)
- if self.filters.based_on_payment_terms:
- row+=[payment_term, invoiced_amount]
- if payment_term_amount:
- invoiced_amount = payment_term_amount
-
- if not payment_term_amount:
- paid_amt = invoiced_amount - outstanding_amount - credit_note_amount
- row += [invoiced_amount, paid_amt, credit_note_amount, outstanding_amount]
-
- # ageing data
- if self.filters.ageing_based_on == "Due Date":
- entry_date = due_date
- elif self.filters.ageing_based_on == "Supplier Invoice Date":
- entry_date = bill_date
- else:
- entry_date = gle.posting_date
-
- row += get_ageing_data(cint(self.filters.range1), cint(self.filters.range2),
- cint(self.filters.range3), cint(self.filters.range4), self.age_as_on, entry_date, outstanding_amount)
-
- # issue 6371-Ageing buckets should not have amounts if due date is not reached
- if self.filters.ageing_based_on == "Due Date" \
- and getdate(due_date) > getdate(self.filters.report_date):
- row[-1]=row[-2]=row[-3]=row[-4]=row[-5]=0
-
- if self.filters.ageing_based_on == "Supplier Invoice Date" \
- and getdate(bill_date) > getdate(self.filters.report_date):
-
- row[-1]=row[-2]=row[-3]=row[-4]=row[-5]=0
-
- if self.filters.get(scrub(args.get("party_type"))):
- row.append(gle.account_currency)
- else:
- row.append(self.company_currency)
-
- remaining_balance = outstanding_amount - flt(pdc_amount)
- pdc_details = ", ".join(pdc_details)
- row += [pdc_details, pdc_amount, remaining_balance]
-
- if args.get('party_type') == 'Customer':
- # customer LPO
- row += [self.voucher_details.get(gle.voucher_no, {}).get("po_no")]
-
- # Delivery Note
- row += [self.voucher_details.get(gle.voucher_no, {}).get("delivery_note")]
-
- # customer territory / supplier group
- if args.get("party_type") == "Customer":
- row += [self.get_territory(gle.party), self.get_customer_group(gle.party),
- self.voucher_details.get(gle.voucher_no, {}).get("sales_person")]
- if args.get("party_type") == "Supplier":
- row += [self.get_supplier_group(gle.party)]
-
- row.append(gle.remarks)
-
- return row
-
- def get_entries_after(self, report_date, party_type):
- # returns a distinct list
- return list(set([(e.voucher_type, e.voucher_no) for e in self.get_gl_entries(party_type, report_date, for_future=True)]))
-
- def get_entries_till(self, report_date, party_type):
- # returns a generator
- return self.get_gl_entries(party_type, report_date)
-
- def is_receivable_or_payable(self, gle, dr_or_cr, future_vouchers, return_entries):
- return (
- # advance
- (not gle.against_voucher) or
-
- # against sales order/purchase order
- (gle.against_voucher_type in ["Sales Order", "Purchase Order"]) or
-
- # sales invoice/purchase invoice
- (gle.against_voucher==gle.voucher_no and gle.get(dr_or_cr) > 0) or
-
- # standalone credit notes
- (gle.against_voucher==gle.voucher_no and gle.voucher_no in return_entries and not return_entries.get(gle.voucher_no)) or
-
- # entries adjusted with future vouchers
- ((gle.against_voucher_type, gle.against_voucher) in future_vouchers)
- )
-
- def get_return_entries(self, party_type):
- doctype = "Sales Invoice" if party_type=="Customer" else "Purchase Invoice"
- return_entries = frappe._dict(frappe.get_all(doctype,
- filters={"is_return": 1, "docstatus": 1}, fields=["name", "return_against"], as_list=1))
- return return_entries
-
- def get_outstanding_amount(self, gle, report_date, dr_or_cr, return_entries):
- payment_amount, credit_note_amount = 0.0, 0.0
- reverse_dr_or_cr = "credit" if dr_or_cr=="debit" else "debit"
- for e in self.get_gl_entries_for(gle.party, gle.party_type, gle.voucher_type, gle.voucher_no):
- if getdate(e.posting_date) <= report_date \
- and (e.name!=gle.name or (e.voucher_no in return_entries and not return_entries.get(e.voucher_no))):
-
- amount = flt(e.get(reverse_dr_or_cr), self.currency_precision) - flt(e.get(dr_or_cr), self.currency_precision)
- if e.voucher_no not in return_entries:
- payment_amount += amount
+ # if there is overpayment, add another row
+ self.allocate_extra_payments_or_credits(row)
+ else:
+ self.append_row(row)
else:
- credit_note_amount += amount
+ self.append_row(row)
- voucher_amount = flt(gle.get(dr_or_cr), self.currency_precision) - flt(gle.get(reverse_dr_or_cr), self.currency_precision)
- if gle.voucher_no in return_entries and not return_entries.get(gle.voucher_no):
- voucher_amount = 0
+ def append_row(self, row):
+ self.allocate_future_payments(row)
+ self.set_invoice_details(row)
+ self.set_party_details(row)
+ self.set_ageing(row)
+ self.data.append(row)
- outstanding_amount = flt((voucher_amount - payment_amount - credit_note_amount), self.currency_precision)
- credit_note_amount = flt(credit_note_amount, self.currency_precision)
+ def set_invoice_details(self, row):
+ row.update(self.invoice_details.get(row.voucher_no, {}))
+ if row.voucher_type == 'Sales Invoice':
+ if self.filters.show_delivery_notes:
+ self.set_delivery_notes(row)
- return outstanding_amount, credit_note_amount, payment_amount
+ if self.filters.show_sales_person and row.sales_team:
+ row.sales_person = ", ".join(row.sales_team)
+ del row['sales_team']
- def get_party_name(self, party_type, party_name):
- return self.get_party_map(party_type).get(party_name, {}).get("customer_name" if party_type == "Customer" else "supplier_name") or ""
+ def set_delivery_notes(self, row):
+ delivery_notes = self.delivery_notes.get(row.voucher_no, [])
+ if delivery_notes:
+ row.delivery_notes = ', '.join(delivery_notes)
- def get_customer_contact(self, party_type, party_name):
- return self.get_party_map(party_type).get(party_name, {}).get("customer_primary_contact")
+ def build_delivery_note_map(self):
+ if self.invoices and self.filters.show_delivery_notes:
+ self.delivery_notes = frappe._dict()
- def get_territory(self, party_name):
- return self.get_party_map("Customer").get(party_name, {}).get("territory") or ""
+ # delivery note link inside sales invoice
+ si_against_dn = frappe.db.sql("""
+ select parent, delivery_note
+ from `tabSales Invoice Item`
+ where docstatus=1 and parent in (%s)
+ """ % (','.join(['%s'] * len(self.invoices))), tuple(self.invoices), as_dict=1)
- def get_customer_group(self, party_name):
- return self.get_party_map("Customer").get(party_name, {}).get("customer_group") or ""
+ for d in si_against_dn:
+ if d.delivery_note:
+ self.delivery_notes.setdefault(d.parent, set()).add(d.delivery_note)
- def get_supplier_group(self, party_name):
- return self.get_party_map("Supplier").get(party_name, {}).get("supplier_group") or ""
+ dn_against_si = frappe.db.sql("""
+ select distinct parent, against_sales_invoice
+ from `tabDelivery Note Item`
+ where against_sales_invoice in (%s)
+ """ % (','.join(['%s'] * len(self.invoices))), tuple(self.invoices) , as_dict=1)
- def get_party_map(self, party_type):
- if not hasattr(self, "party_map"):
- if party_type == "Customer":
- select_fields = "name, customer_name, territory, customer_group, customer_primary_contact"
- elif party_type == "Supplier":
- select_fields = "name, supplier_name, supplier_group"
+ for d in dn_against_si:
+ self.delivery_notes.setdefault(d.against_sales_invoice, set()).add(d.parent)
- self.party_map = dict(((r.name, r) for r in frappe.db.sql("select {0} from `tab{1}`"
- .format(select_fields, party_type), as_dict=True)))
+ def get_invoice_details(self):
+ self.invoice_details = frappe._dict()
+ if self.party_type == "Customer":
+ si_list = frappe.db.sql("""
+ select name, due_date, po_no
+ from `tabSales Invoice`
+ where posting_date <= %s
+ """,self.filters.report_date, as_dict=1)
+ for d in si_list:
+ self.invoice_details.setdefault(d.name, d)
- return self.party_map
+ # Get Sales Team
+ if self.filters.show_sales_person:
+ sales_team = frappe.db.sql("""
+ select parent, sales_person
+ from `tabSales Team`
+ where parenttype = 'Sales Invoice'
+ """, as_dict=1)
+ for d in sales_team:
+ self.invoice_details.setdefault(d.parent, {})\
+ .setdefault('sales_team', []).append(d.sales_person)
- def get_gl_entries(self, party_type, date=None, for_future=False):
- conditions, values = self.prepare_conditions(party_type)
+ if self.party_type == "Supplier":
+ for pi in frappe.db.sql("""
+ select name, due_date, bill_no, bill_date
+ from `tabPurchase Invoice`
+ where posting_date <= %s
+ """, self.filters.report_date, as_dict=1):
+ self.invoice_details.setdefault(pi.name, pi)
- if self.filters.get(scrub(party_type)):
- select_fields = "sum(debit_in_account_currency) as debit, sum(credit_in_account_currency) as credit"
+ # Invoices booked via Journal Entries
+ journal_entries = frappe.db.sql("""
+ select name, due_date, bill_no, bill_date
+ from `tabJournal Entry`
+ where posting_date <= %s
+ """, self.filters.report_date, as_dict=1)
+
+ for je in journal_entries:
+ if je.bill_no:
+ self.invoice_details.setdefault(je.name, je)
+
+ def set_party_details(self, row):
+ # customer / supplier name
+ party_details = self.get_party_details(row.party)
+ row.update(party_details)
+
+ if self.filters.get(scrub(self.filters.party_type)):
+ row.currency = row.account_currency
else:
- select_fields = "sum(debit) as debit, sum(credit) as credit"
+ row.currency = self.company_currency
- if date and not for_future:
- conditions += " and posting_date <= '%s'" % date
+ def allocate_outstanding_based_on_payment_terms(self, row):
+ self.get_payment_terms(row)
+ for term in row.payment_terms:
+ term.outstanding = term.invoiced
- if date and for_future:
- conditions += " and posting_date > '%s'" % date
+ # update "paid" and "oustanding" for this term
+ self.allocate_closing_to_term(row, term, 'paid')
+
+ # update "credit_note" and "oustanding" for this term
+ if term.outstanding:
+ self.allocate_closing_to_term(row, term, 'credit_note')
+
+ def get_payment_terms(self, row):
+ # build payment_terms for row
+ payment_terms_details = frappe.db.sql("""
+ select
+ si.name, si.party_account_currency, si.currency, si.conversion_rate,
+ ps.due_date, ps.payment_amount, ps.description
+ from `tab{0}` si, `tabPayment Schedule` ps
+ where
+ si.name = ps.parent and
+ si.name = %s
+ order by ps.due_date
+ """.format(row.voucher_type), row.voucher_no, as_dict = 1)
+
+
+ original_row = frappe._dict(row)
+ row.payment_terms = []
+
+ # If no or single payment terms, no need to split the row
+ if len(payment_terms_details) <= 1:
+ return
+
+ for d in payment_terms_details:
+ term = frappe._dict(original_row)
+ self.append_payment_term(row, d, term)
+
+ def append_payment_term(self, row, d, term):
+ if self.filters.get("customer") and d.currency == d.party_account_currency:
+ invoiced = d.payment_amount
+ else:
+ invoiced = flt(flt(d.payment_amount) * flt(d.conversion_rate), self.currency_precision)
+
+ row.payment_terms.append(term.update({
+ "due_date": d.due_date,
+ "invoiced": invoiced,
+ "invoice_grand_total": row.invoiced,
+ "payment_term": d.description,
+ "paid": 0.0,
+ "credit_note": 0.0,
+ "outstanding": 0.0
+ }))
+
+ def allocate_closing_to_term(self, row, term, key):
+ if row[key]:
+ if row[key] > term.outstanding:
+ term[key] = term.outstanding
+ row[key] -= term.outstanding
+ else:
+ term[key] = row[key]
+ row[key] = 0
+ term.outstanding -= term[key]
+
+ def allocate_extra_payments_or_credits(self, row):
+ # allocate extra payments / credits
+ additional_row = None
+ for key in ('paid', 'credit_note'):
+ if row[key] > 0:
+ if not additional_row:
+ additional_row = frappe._dict(row)
+ additional_row.invoiced = 0.0
+ additional_row[key] = row[key]
+
+ if additional_row:
+ additional_row.outstanding = additional_row.invoiced - additional_row.paid - additional_row.credit_note
+ self.append_row(additional_row)
+
+ def get_future_payments(self):
+ if self.filters.show_future_payments:
+ self.future_payments = frappe._dict()
+ future_payments = list(self.get_future_payments_from_payment_entry())
+ future_payments += list(self.get_future_payments_from_journal_entry())
+ if future_payments:
+ for d in future_payments:
+ if d.future_amount and d.invoice_no:
+ self.future_payments.setdefault((d.invoice_no, d.party), []).append(d)
+
+ def get_future_payments_from_payment_entry(self):
+ return frappe.db.sql("""
+ select
+ ref.reference_name as invoice_no,
+ payment_entry.party,
+ payment_entry.party_type,
+ payment_entry.posting_date as future_date,
+ ref.allocated_amount as future_amount,
+ payment_entry.reference_no as future_ref
+ from
+ `tabPayment Entry` as payment_entry inner join `tabPayment Entry Reference` as ref
+ on
+ (ref.parent = payment_entry.name)
+ where
+ payment_entry.docstatus < 2
+ and payment_entry.posting_date > %s
+ and payment_entry.party_type = %s
+ """, (self.filters.report_date, self.party_type), as_dict=1)
+
+ def get_future_payments_from_journal_entry(self):
+ if self.filters.get('party'):
+ amount_field = ("jea.debit_in_account_currency - jea.credit_in_account_currency"
+ if self.party_type == 'Supplier' else "jea.credit_in_account_currency - jea.debit_in_account_currency")
+ else:
+ amount_field = ("jea.debit - " if self.party_type == 'Supplier' else "jea.credit")
+
+ return frappe.db.sql("""
+ select
+ jea.reference_name as invoice_no,
+ jea.party,
+ jea.party_type,
+ je.posting_date as future_date,
+ sum({0}) as future_amount,
+ je.cheque_no as future_ref
+ from
+ `tabJournal Entry` as je inner join `tabJournal Entry Account` as jea
+ on
+ (jea.parent = je.name)
+ where
+ je.docstatus < 2
+ and je.posting_date > %s
+ and jea.party_type = %s
+ and jea.reference_name is not null and jea.reference_name != ''
+ group by je.name, jea.reference_name
+ having future_amount > 0
+ """.format(amount_field), (self.filters.report_date, self.party_type), as_dict=1)
+
+ def allocate_future_payments(self, row):
+ # future payments are captured in additional columns
+ # this method allocates pending future payments against a voucher to
+ # the current row (which could be generated from payment terms)
+ if not self.filters.show_future_payments:
+ return
+
+ row.remaining_balance = row.outstanding
+ row.future_amount = 0.0
+ for future in self.future_payments.get((row.voucher_no, row.party), []):
+ if row.remaining_balance > 0 and future.future_amount:
+ if future.future_amount > row.outstanding:
+ row.future_amount = row.outstanding
+ future.future_amount = future.future_amount - row.outstanding
+ row.remaining_balance = 0
+ else:
+ row.future_amount += future.future_amount
+ future.future_amount = 0
+ row.remaining_balance = row.outstanding - row.future_amount
+
+ row.setdefault('future_ref', []).append(cstr(future.future_ref) + '/' + cstr(future.future_date))
+
+ if row.future_ref:
+ row.future_ref = ', '.join(row.future_ref)
+
+ def set_ageing(self, row):
+ if self.filters.ageing_based_on == "Due Date":
+ entry_date = row.due_date
+ elif self.filters.ageing_based_on == "Supplier Invoice Date":
+ entry_date = row.bill_date
+ else:
+ entry_date = row.posting_date
+
+ self.get_ageing_data(entry_date, row)
+
+ # ageing buckets should not have amounts if due date is not reached
+ if getdate(entry_date) > getdate(self.filters.report_date):
+ row.range1 = row.range2 = row.range3 = row.range4 = row.range5 = 0.0
+
+ def get_ageing_data(self, entry_date, row):
+ # [0-30, 30-60, 60-90, 90-120, 120-above]
+ row.range1 = row.range2 = row.range3 = row.range4 = range5 = 0.0
+
+ if not (self.age_as_on and entry_date):
+ return
+
+ row.age = (getdate(self.age_as_on) - getdate(entry_date)).days or 0
+ index = None
+ for i, days in enumerate([self.filters.range1, self.filters.range2, self.filters.range3, self.filters.range4]):
+ if row.age <= days:
+ index = i
+ break
+
+ if index is None: index = 4
+ row['range' + str(index+1)] = row.outstanding
+
+ def get_gl_entries(self):
+ # get all the GL entries filtered by the given filters
+
+ conditions, values = self.prepare_conditions()
+
+ if self.filters.get(scrub(self.party_type)):
+ select_fields = "debit_in_account_currency as debit, credit_in_account_currency as credit"
+ else:
+ select_fields = "debit, credit"
self.gl_entries = frappe.db.sql("""
select
@@ -473,91 +471,95 @@
from
`tabGL Entry`
where
- docstatus < 2 and party_type=%s and (party is not null and party != '') {1}
- group by voucher_type, voucher_no, against_voucher_type, against_voucher, party
- order by posting_date, party"""
+ docstatus < 2
+ and party_type=%s
+ and (party is not null and party != '')
+ and posting_date <= %s
+ {1}
+ order by posting_date, party"""
.format(select_fields, conditions), values, as_dict=True)
- return self.gl_entries
-
- def prepare_conditions(self, party_type):
+ def prepare_conditions(self):
conditions = [""]
- values = [party_type]
+ values = [self.party_type, self.filters.report_date]
+ party_type_field = scrub(self.party_type)
- party_type_field = scrub(party_type)
+ self.add_common_filters(conditions, values, party_type_field)
+ if party_type_field=="customer":
+ self.add_customer_filters(conditions, values)
+
+ elif party_type_field=="supplier":
+ self.add_supplier_filters(conditions, values)
+
+ self.add_accounting_dimensions_filters(conditions, values)
+
+ return " and ".join(conditions), values
+
+ def add_common_filters(self, conditions, values, party_type_field):
if self.filters.company:
conditions.append("company=%s")
values.append(self.filters.company)
if self.filters.finance_book:
- conditions.append("ifnull(finance_book,'') in (%s, '')")
+ conditions.append("ifnull(finance_book, '') in (%s, '')")
values.append(self.filters.finance_book)
if self.filters.get(party_type_field):
conditions.append("party=%s")
values.append(self.filters.get(party_type_field))
- if party_type_field=="customer":
- account_type = "Receivable"
- if self.filters.get("customer_group"):
- lft, rgt = frappe.db.get_value("Customer Group",
- self.filters.get("customer_group"), ["lft", "rgt"])
+ # get GL with "receivable" or "payable" account_type
+ account_type = "Receivable" if self.party_type == "Customer" else "Payable"
+ accounts = [d.name for d in frappe.get_all("Account",
+ filters={"account_type": account_type, "company": self.filters.company})]
+ conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts)))
+ values += accounts
- conditions.append("""party in (select name from tabCustomer
- where exists(select name from `tabCustomer Group` where lft >= {0} and rgt <= {1}
- and name=tabCustomer.customer_group))""".format(lft, rgt))
+ def add_customer_filters(self, conditions, values):
+ if self.filters.get("customer_group"):
+ conditions.append(self.get_hierarchical_filters('Customer Group', 'customer_group'))
- if self.filters.get("territory"):
- lft, rgt = frappe.db.get_value("Territory",
- self.filters.get("territory"), ["lft", "rgt"])
+ if self.filters.get("territory"):
+ conditions.append(self.get_hierarchical_filters('Territory', 'territory'))
- conditions.append("""party in (select name from tabCustomer
- where exists(select name from `tabTerritory` where lft >= {0} and rgt <= {1}
- and name=tabCustomer.territory))""".format(lft, rgt))
+ if self.filters.get("payment_terms_template"):
+ conditions.append("party in (select name from tabCustomer where payment_terms=%s)")
+ values.append(self.filters.get("payment_terms_template"))
- if self.filters.get("payment_terms_template"):
- conditions.append("party in (select name from tabCustomer where payment_terms=%s)")
- values.append(self.filters.get("payment_terms_template"))
+ if self.filters.get("sales_partner"):
+ conditions.append("party in (select name from tabCustomer where default_sales_partner=%s)")
+ values.append(self.filters.get("sales_partner"))
- if self.filters.get("sales_partner"):
- conditions.append("party in (select name from tabCustomer where default_sales_partner=%s)")
- values.append(self.filters.get("sales_partner"))
+ if self.filters.get("sales_person"):
+ lft, rgt = frappe.db.get_value("Sales Person",
+ self.filters.get("sales_person"), ["lft", "rgt"])
- if self.filters.get("sales_person"):
- lft, rgt = frappe.db.get_value("Sales Person",
- self.filters.get("sales_person"), ["lft", "rgt"])
+ conditions.append("""exists(select name from `tabSales Team` steam where
+ steam.sales_person in (select name from `tabSales Person` where lft >= {0} and rgt <= {1})
+ and ((steam.parent = voucher_no and steam.parenttype = voucher_type)
+ or (steam.parent = against_voucher and steam.parenttype = against_voucher_type)
+ or (steam.parent = party and steam.parenttype = 'Customer')))""".format(lft, rgt))
- conditions.append("""exists(select name from `tabSales Team` steam where
- steam.sales_person in (select name from `tabSales Person` where lft >= {0} and rgt <= {1})
- and ((steam.parent = voucher_no and steam.parenttype = voucher_type)
- or (steam.parent = against_voucher and steam.parenttype = against_voucher_type)
- or (steam.parent = party and steam.parenttype = 'Customer')))""".format(lft, rgt))
+ def add_supplier_filters(self, conditions, values):
+ if self.filters.get("supplier_group"):
+ conditions.append("""party in (select name from tabSupplier
+ where supplier_group=%s)""")
+ values.append(self.filters.get("supplier_group"))
- elif party_type_field=="supplier":
- account_type = "Payable"
- if self.filters.get("supplier_group"):
- conditions.append("""party in (select name from tabSupplier
- where supplier_group=%s)""")
- values.append(self.filters.get("supplier_group"))
+ if self.filters.get("payment_terms_template"):
+ conditions.append("party in (select name from tabSupplier where payment_terms=%s)")
+ values.append(self.filters.get("payment_terms_template"))
- if self.filters.get("payment_terms_template"):
- conditions.append("party in (select name from tabSupplier where payment_terms=%s)")
- values.append(self.filters.get("payment_terms_template"))
+ def get_hierarchical_filters(self, doctype, key):
+ lft, rgt = frappe.db.get_value(doctype, self.filters.get(key), ["lft", "rgt"])
- if self.filters.get("cost_center"):
- lft, rgt = frappe.get_cached_value("Cost Center",
- self.filters.get("cost_center"), ['lft', 'rgt'])
+ return """party in (select name from tabCustomer
+ where exists(select name from `tab{doctype}` where lft >= {lft} and rgt <= {rgt}
+ and name=tabCustomer.{key}))""".format(
+ doctype=doctype, lft=lft, rgt=rgt, key=key)
- conditions.append("""cost_center in (select name from `tabCost Center` where
- lft >= {0} and rgt <= {1})""".format(lft, rgt))
-
- if self.filters.company:
- accounts = [d.name for d in frappe.get_all("Account",
- filters={"account_type": account_type, "company": self.filters.company})]
- conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts)))
- values += accounts
-
+ def add_accounting_dimensions_filters(self, conditions, values):
accounting_dimensions = get_accounting_dimensions()
if accounting_dimensions:
@@ -566,195 +568,133 @@
conditions.append("{0} = %s".format(dimension))
values.append(self.filters.get(dimension))
- return " and ".join(conditions), values
+ def get_gle_balance(self, gle):
+ # get the balance of the GL (debit - credit) or reverse balance based on report type
+ return gle.get(self.dr_or_cr) - self.get_reverse_balance(gle)
- def get_gl_entries_for(self, party, party_type, against_voucher_type, against_voucher):
- if not hasattr(self, "gl_entries_map"):
- self.gl_entries_map = {}
- for gle in self.get_gl_entries(party_type):
- if gle.against_voucher_type and gle.against_voucher:
- self.gl_entries_map.setdefault(gle.party, {})\
- .setdefault(gle.against_voucher_type, {})\
- .setdefault(gle.against_voucher, [])\
- .append(gle)
+ def get_reverse_balance(self, gle):
+ # get "credit" balance if report type is "debit" and vice versa
+ return gle.get('debit' if self.dr_or_cr=='credit' else 'credit')
- return self.gl_entries_map.get(party, {})\
- .get(against_voucher_type, {})\
- .get(against_voucher, [])
+ def is_invoice(self, gle):
+ if gle.voucher_type in ('Sales Invoice', 'Purchase Invoice'):
+ return True
- def get_payment_term_detail(self, voucher_nos):
- payment_term_map = frappe._dict()
- payment_terms_details = frappe.db.sql(""" select si.name,
- party_account_currency, currency, si.conversion_rate,
- ps.due_date, ps.payment_amount, ps.description
- from `tabSales Invoice` si, `tabPayment Schedule` ps
- where si.name = ps.parent and
- si.docstatus = 1 and si.company = %s and
- si.name in (%s) order by ps.due_date
- """ % (frappe.db.escape(self.filters.company), ','.join(['%s'] *len(voucher_nos))),
- (tuple(voucher_nos)), as_dict = 1)
-
- for d in payment_terms_details:
- if self.filters.get("customer") and d.currency == d.party_account_currency:
- payment_term_amount = d.payment_amount
+ def get_party_details(self, party):
+ if not party in self.party_details:
+ if self.party_type == 'Customer':
+ self.party_details[party] = frappe.db.get_value('Customer', party, ['customer_name',
+ 'territory', 'customer_group', 'customer_primary_contact'], as_dict=True)
else:
- payment_term_amount = flt(flt(d.payment_amount) * flt(d.conversion_rate), self.currency_precision)
+ self.party_details[party] = frappe.db.get_value('Supplier', party, ['supplier_name',
+ 'supplier_group'], as_dict=True)
- payment_term_map.setdefault(d.name, []).append(frappe._dict({
- "due_date": d.due_date,
- "payment_term_amount": payment_term_amount,
- "description": d.description
- }))
- return payment_term_map
+ return self.party_details[party]
- def get_chart_data(self, columns, data):
- ageing_columns = columns[self.ageing_col_idx_start : self.ageing_col_idx_start+5]
+ def get_columns(self):
+ self.columns = []
+ self.add_column('Posting Date', fieldtype='Date')
+ self.add_column(label=_(self.party_type), fieldname='party',
+ fieldtype='Link', options=self.party_type, width=180)
+
+ if self.party_naming_by == "Naming Series":
+ self.add_column(_('{0} Name').format(self.party_type),
+ fieldname = scrub(self.party_type) + '_name', fieldtype='Data')
+
+ if self.party_type == 'Customer':
+ self.add_column(_("Customer Contact"), fieldname='customer_primary_contact',
+ fieldtype='Link', options='Contact')
+
+ self.add_column(label=_('Voucher Type'), fieldname='voucher_type', fieldtype='Data')
+ self.add_column(label=_('Voucher No'), fieldname='voucher_no', fieldtype='Dynamic Link',
+ options='voucher_type', width=180)
+ self.add_column(label='Due Date', fieldtype='Date')
+
+ if self.party_type == "Supplier":
+ self.add_column(label=_('Bill No'), fieldname='bill_no', fieldtype='Data')
+ self.add_column(label=_('Bill Date'), fieldname='bill_date', fieldtype='Date')
+
+ if self.filters.based_on_payment_terms:
+ self.add_column(label=_('Payment Term'), fieldname='payment_term', fieldtype='Data')
+ self.add_column(label=_('Invoice Grand Total'), fieldname='invoice_grand_total')
+
+ self.add_column(_('Invoiced Amount'), fieldname='invoiced')
+ self.add_column(_('Paid Amount'), fieldname='paid')
+ if self.party_type == "Customer":
+ self.add_column(_('Credit Note'), fieldname='credit_note')
+ else:
+ # note: fieldname is still `credit_note`
+ self.add_column(_('Debit Note'), fieldname='credit_note')
+ self.add_column(_('Outstanding Amount'), fieldname='outstanding')
+
+ self.setup_ageing_columns()
+
+ self.add_column(label=_('Currency'), fieldname='currency', fieldtype='Link', options='Currency', width=80)
+
+ if self.filters.show_future_payments:
+ self.add_column(label=_('Future Payment Ref'), fieldname='future_ref', fieldtype='Data')
+ self.add_column(label=_('Future Payment Amount'), fieldname='future_amount')
+ self.add_column(label=_('Remaining Balance'), fieldname='remaining_balance')
+
+ if self.filters.party_type == 'Customer':
+ self.add_column(label=_('Customer LPO'), fieldname='po_no', fieldtype='Data')
+
+ # comma separated list of linked delivery notes
+ if self.filters.show_delivery_notes:
+ self.add_column(label=_('Delivery Notes'), fieldname='delivery_notes', fieldtype='Data')
+ self.add_column(label=_('Territory'), fieldname='territory', fieldtype='Link',
+ options='Territory')
+ self.add_column(label=_('Customer Group'), fieldname='customer_group', fieldtype='Link',
+ options='Customer Group')
+ if self.filters.show_sales_person:
+ self.add_column(label=_('Sales Person'), fieldname='sales_person', fieldtype='Data')
+
+ if self.filters.party_type == "Supplier":
+ self.add_column(label=_('Supplier Group'), fieldname='supplier_group', fieldtype='Link',
+ options='Supplier Group')
+
+ self.add_column(label=_('Remarks'), fieldname='remarks', fieldtype='Text', width=200)
+
+ def add_column(self, label, fieldname=None, fieldtype='Currency', options=None, width=120):
+ if not fieldname: fieldname = scrub(label)
+ if fieldtype=='Currency': options='currency'
+ if fieldtype=='Date': width = 90
+
+ self.columns.append(dict(
+ label=label,
+ fieldname=fieldname,
+ fieldtype=fieldtype,
+ options=options,
+ width=width
+ ))
+
+ def setup_ageing_columns(self):
+ # for charts
+ self.ageing_column_labels = []
+ self.add_column(label=_('Age (Days)'), fieldname='age', fieldtype='Int', width=80)
+
+ for i, label in enumerate(["0-{range1}".format(range1=self.filters["range1"]),
+ "{range1}-{range2}".format(range1=cint(self.filters["range1"])+ 1, range2=self.filters["range2"]),
+ "{range2}-{range3}".format(range2=cint(self.filters["range2"])+ 1, range3=self.filters["range3"]),
+ "{range3}-{range4}".format(range3=cint(self.filters["range3"])+ 1, range4=self.filters["range4"]),
+ "{range4}-{above}".format(range4=cint(self.filters["range4"])+ 1, above=_("Above"))]):
+ self.add_column(label=label, fieldname='range' + str(i+1))
+ self.ageing_column_labels.append(label)
+
+ def get_chart_data(self):
rows = []
- for d in data:
- values = d[self.ageing_col_idx_start : self.ageing_col_idx_start+5]
- precision = cint(frappe.db.get_default("float_precision")) or 2
- formatted_values = [frappe.utils.rounded(val, precision) for val in values]
+ for row in self.data:
rows.append(
{
- 'values': formatted_values
+ 'values': [row.range1, row.range2, row.range3, row.range4, row.range5]
}
)
- return {
+ self.chart = {
"data": {
- 'labels': [d.get("label") for d in ageing_columns],
+ 'labels': self.ageing_column_labels,
'datasets': rows
},
"type": 'percentage'
}
-
-def execute(filters=None):
- args = {
- "party_type": "Customer",
- "naming_by": ["Selling Settings", "cust_master_name"],
- }
- return ReceivablePayableReport(filters).run(args)
-
-def get_ageing_data(first_range, second_range, third_range,
- fourth_range, age_as_on, entry_date, outstanding_amount):
- # [0-30, 30-60, 60-90, 90-120, 120-above]
- outstanding_range = [0.0, 0.0, 0.0, 0.0, 0.0]
-
- if not (age_as_on and entry_date):
- return [0] + outstanding_range
-
- age = (getdate(age_as_on) - getdate(entry_date)).days or 0
- index = None
- for i, days in enumerate([first_range, second_range, third_range, fourth_range]):
- if age <= days:
- index = i
- break
-
- if index is None: index = 4
- outstanding_range[index] = outstanding_amount
-
- return [age] + outstanding_range
-
-def get_pdc_details(party_type, report_date):
- pdc_details = frappe._dict()
- pdc_via_pe = frappe.db.sql("""
- select
- pref.reference_name as invoice_no, pent.party, pent.party_type,
- pent.posting_date as pdc_date, ifnull(pref.allocated_amount,0) as pdc_amount,
- pent.reference_no as pdc_ref
- from
- `tabPayment Entry` as pent inner join `tabPayment Entry Reference` as pref
- on
- (pref.parent = pent.name)
- where
- pent.docstatus < 2 and pent.posting_date > %s
- and pent.party_type = %s
- """, (report_date, party_type), as_dict=1)
-
- for pdc in pdc_via_pe:
- pdc_details.setdefault((pdc.invoice_no, pdc.party), []).append(pdc)
-
- if scrub(party_type):
- amount_field = ("jea.debit_in_account_currency"
- if party_type == 'Supplier' else "jea.credit_in_account_currency")
- else:
- amount_field = "jea.debit + jea.credit"
-
- pdc_via_je = frappe.db.sql("""
- select
- jea.reference_name as invoice_no, jea.party, jea.party_type,
- je.posting_date as pdc_date, ifnull({0},0) as pdc_amount,
- je.cheque_no as pdc_ref
- from
- `tabJournal Entry` as je inner join `tabJournal Entry Account` as jea
- on
- (jea.parent = je.name)
- where
- je.docstatus < 2 and je.posting_date > %s
- and jea.party_type = %s
- """.format(amount_field), (report_date, party_type), as_dict=1)
-
- for pdc in pdc_via_je:
- pdc_details.setdefault((pdc.invoice_no, pdc.party), []).append(pdc)
-
- return pdc_details
-
-def get_dn_details(party_type, voucher_nos):
- dn_details = frappe._dict()
-
- if party_type == "Customer":
- for si in frappe.db.sql("""
- select
- parent, GROUP_CONCAT(delivery_note SEPARATOR ', ') as dn
- from
- `tabSales Invoice Item`
- where
- docstatus=1 and delivery_note is not null and delivery_note != ''
- and parent in (%s) group by parent
- """ %(','.join(['%s'] * len(voucher_nos))), tuple(voucher_nos) , as_dict=1):
- dn_details.setdefault(si.parent, si.dn)
-
- for si in frappe.db.sql("""
- select
- against_sales_invoice as parent, GROUP_CONCAT(parent SEPARATOR ', ') as dn
- from
- `tabDelivery Note Item`
- where
- docstatus=1 and against_sales_invoice is not null and against_sales_invoice != ''
- and against_sales_invoice in (%s)
- group by against_sales_invoice
- """ %(','.join(['%s'] * len(voucher_nos))), tuple(voucher_nos) , as_dict=1):
- if si.parent in dn_details:
- dn_details[si.parent] += ', %s' %(si.dn)
- else:
- dn_details.setdefault(si.parent, si.dn)
-
- return dn_details
-
-def get_voucher_details(party_type, voucher_nos, dn_details):
- voucher_details = frappe._dict()
-
- if party_type == "Customer":
- for si in frappe.db.sql("""
- select inv.name, inv.due_date, inv.po_no, GROUP_CONCAT(steam.sales_person SEPARATOR ', ') as sales_person
- from `tabSales Invoice` inv
- left join `tabSales Team` steam on steam.parent = inv.name and steam.parenttype = 'Sales Invoice'
- where inv.docstatus=1 and inv.name in (%s)
- group by inv.name
- """ %(','.join(['%s'] *len(voucher_nos))), (tuple(voucher_nos)), as_dict=1):
- si['delivery_note'] = dn_details.get(si.name)
- voucher_details.setdefault(si.name, si)
-
- if party_type == "Supplier":
- for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
- from `tabPurchase Invoice` where docstatus = 1 and name in (%s)
- """ %(','.join(['%s'] *len(voucher_nos))), (tuple(voucher_nos)), as_dict=1):
- voucher_details.setdefault(pi.name, pi)
-
- for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date from
- `tabJournal Entry` where docstatus = 1 and bill_no is not NULL and name in (%s)
- """ %(','.join(['%s'] *len(voucher_nos))), (tuple(voucher_nos)), as_dict=1):
- voucher_details.setdefault(pi.name, pi)
-
- return voucher_details
diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
index 43786a4..f0274b4 100644
--- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
@@ -14,33 +14,44 @@
filters = {
'company': '_Test Company 2',
- 'based_on_payment_terms': 1
+ 'based_on_payment_terms': 1,
+ 'report_date': today(),
+ 'range1': 30,
+ 'range2': 60,
+ 'range3': 90,
+ 'range4': 120
}
+ # check invoice grand total and invoiced column's value for 3 payment terms
name = make_sales_invoice()
report = execute(filters)
- expected_data = [[100,30], [100,50], [100,20]]
+ expected_data = [[100, 30], [100, 50], [100, 20]]
- self.assertEqual(expected_data[0], report[1][0][7:9])
- self.assertEqual(expected_data[1], report[1][1][7:9])
- self.assertEqual(expected_data[2], report[1][2][7:9])
+ for i in range(3):
+ row = report[1][i-1]
+ self.assertEqual(expected_data[i-1], [row.invoice_grand_total, row.invoiced])
+ # check invoice grand total, invoiced, paid and outstanding column's value after payment
make_payment(name)
report = execute(filters)
- expected_data_after_payment = [[100,50], [100,20]]
+ expected_data_after_payment = [[100, 50, 10, 40], [100, 20, 0, 20]]
- self.assertEqual(expected_data_after_payment[0], report[1][0][7:9])
- self.assertEqual(expected_data_after_payment[1], report[1][1][7:9])
+ for i in range(2):
+ row = report[1][i-1]
+ self.assertEqual(expected_data_after_payment[i-1],
+ [row.invoice_grand_total, row.invoiced, row.paid, row.outstanding])
+ # check invoice grand total, invoiced, paid and outstanding column's value after credit note
make_credit_note(name)
report = execute(filters)
- expected_data_after_credit_note = [[100,100,30,100,-30]]
+ expected_data_after_credit_note = [100, 0, 0, 40, -40]
- self.assertEqual(expected_data_after_credit_note[0], report[1][0][7:12])
-
+ row = report[1][0]
+ self.assertEqual(expected_data_after_credit_note,
+ [row.invoice_grand_total, row.invoiced, row.paid, row.credit_note, row.outstanding])
def make_sales_invoice():
frappe.set_user("Administrator")
@@ -64,7 +75,7 @@
return si.name
def make_payment(docname):
- pe = get_payment_entry("Sales Invoice", docname, bank_account="Cash - _TC2", party_amount=30)
+ pe = get_payment_entry("Sales Invoice", docname, bank_account="Cash - _TC2", party_amount=40)
pe.paid_from = "Debtors - _TC2"
pe.insert()
pe.submit()
diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
index ec24aec..350e081 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
@@ -3,236 +3,11 @@
from __future__ import unicode_literals
import frappe
-from frappe import _, scrub
-from frappe.utils import flt
+from frappe import _
+from frappe.utils import flt, cint
from erpnext.accounts.party import get_partywise_advanced_payment_amount
from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport
-
from six import iteritems
-from six.moves import zip
-
-class AccountsReceivableSummary(ReceivablePayableReport):
- def run(self, args):
- party_naming_by = frappe.db.get_value(args.get("naming_by")[0], None, args.get("naming_by")[1])
- return self.get_columns(party_naming_by, args), self.get_data(party_naming_by, args)
-
- def get_columns(self, party_naming_by, args):
- columns = [_(args.get("party_type")) + ":Link/" + args.get("party_type") + ":200"]
-
- if party_naming_by == "Naming Series":
- columns += [ args.get("party_type") + " Name::140"]
-
- credit_debit_label = "Credit Note Amt" if args.get('party_type') == 'Customer' else "Debit Note Amt"
-
- columns += [{
- "label": _("Advance Amount"),
- "fieldname": "advance_amount",
- "fieldtype": "Currency",
- "options": "currency",
- "width": 100
- },{
- "label": _("Total Invoiced Amt"),
- "fieldname": "total_invoiced_amt",
- "fieldtype": "Currency",
- "options": "currency",
- "width": 100
- },
- {
- "label": _("Total Paid Amt"),
- "fieldname": "total_paid_amt",
- "fieldtype": "Currency",
- "options": "currency",
- "width": 100
- }]
-
- columns += [
- {
- "label": _(credit_debit_label),
- "fieldname": scrub(credit_debit_label),
- "fieldtype": "Currency",
- "options": "currency",
- "width": 140
- },
- {
- "label": _("Total Outstanding Amt"),
- "fieldname": "total_outstanding_amt",
- "fieldtype": "Currency",
- "options": "currency",
- "width": 160
- },
- {
- "label": _("0-" + str(self.filters.range1)),
- "fieldname": scrub("0-" + str(self.filters.range1)),
- "fieldtype": "Currency",
- "options": "currency",
- "width": 160
- },
- {
- "label": _(str(self.filters.range1) + "-" + str(self.filters.range2)),
- "fieldname": scrub(str(self.filters.range1) + "-" + str(self.filters.range2)),
- "fieldtype": "Currency",
- "options": "currency",
- "width": 160
- },
- {
- "label": _(str(self.filters.range2) + "-" + str(self.filters.range3)),
- "fieldname": scrub(str(self.filters.range2) + "-" + str(self.filters.range3)),
- "fieldtype": "Currency",
- "options": "currency",
- "width": 160
- },
- {
- "label": _(str(self.filters.range3) + "-" + str(self.filters.range4)),
- "fieldname": scrub(str(self.filters.range3) + "-" + str(self.filters.range4)),
- "fieldtype": "Currency",
- "options": "currency",
- "width": 160
- },
- {
- "label": _(str(self.filters.range4) + _("-Above")),
- "fieldname": scrub(str(self.filters.range4) + _("-Above")),
- "fieldtype": "Currency",
- "options": "currency",
- "width": 160
- }
- ]
-
- if args.get("party_type") == "Customer":
- columns += [{
- "label": _("Territory"),
- "fieldname": "territory",
- "fieldtype": "Link",
- "options": "Territory",
- "width": 80
- },
- {
- "label": _("Customer Group"),
- "fieldname": "customer_group",
- "fieldtype": "Link",
- "options": "Customer Group",
- "width": 80
- },
- {
- "label": _("Sales Person"),
- "fieldtype": "Data",
- "fieldname": "sales_person",
- "width": 120,
- }]
-
- if args.get("party_type") == "Supplier":
- columns += [{
- "label": _("Supplier Group"),
- "fieldname": "supplier_group",
- "fieldtype": "Link",
- "options": "Supplier Group",
- "width": 80
- }]
-
- columns.append({
- "fieldname": "currency",
- "label": _("Currency"),
- "fieldtype": "Link",
- "options": "Currency",
- "width": 80
- })
-
- return columns
-
- def get_data(self, party_naming_by, args):
- data = []
-
- partywise_total = self.get_partywise_total(party_naming_by, args)
-
- partywise_advance_amount = get_partywise_advanced_payment_amount(args.get("party_type"),
- self.filters.get("report_date")) or {}
- for party, party_dict in iteritems(partywise_total):
- row = [party]
-
- if party_naming_by == "Naming Series":
- row += [self.get_party_name(args.get("party_type"), party)]
-
- row += [partywise_advance_amount.get(party, 0)]
-
- paid_amt = 0
- if party_dict.paid_amt > 0:
- paid_amt = flt(party_dict.paid_amt - partywise_advance_amount.get(party, 0))
-
- row += [
- party_dict.invoiced_amt, paid_amt, party_dict.credit_amt, party_dict.outstanding_amt,
- party_dict.range1, party_dict.range2, party_dict.range3, party_dict.range4, party_dict.range5
- ]
-
- if args.get("party_type") == "Customer":
- row += [self.get_territory(party), self.get_customer_group(party), ", ".join(set(party_dict.sales_person))]
- if args.get("party_type") == "Supplier":
- row += [self.get_supplier_group(party)]
-
- row.append(party_dict.currency)
- data.append(row)
-
- return data
-
- def get_partywise_total(self, party_naming_by, args):
- party_total = frappe._dict()
- for d in self.get_voucherwise_data(party_naming_by, args):
- party_total.setdefault(d.party,
- frappe._dict({
- "invoiced_amt": 0,
- "paid_amt": 0,
- "credit_amt": 0,
- "outstanding_amt": 0,
- "range1": 0,
- "range2": 0,
- "range3": 0,
- "range4": 0,
- "range5": 0,
- "sales_person": []
- })
- )
- for k in list(party_total[d.party]):
- if k not in ["currency", "sales_person"]:
- party_total[d.party][k] += flt(d.get(k, 0))
-
- party_total[d.party].currency = d.currency
-
- if d.sales_person:
- party_total[d.party].sales_person.append(d.sales_person)
-
- return party_total
-
- def get_voucherwise_data(self, party_naming_by, args):
- voucherwise_data = ReceivablePayableReport(self.filters).run(args)[1]
-
- cols = ["posting_date", "party"]
-
- if party_naming_by == "Naming Series":
- cols += ["party_name"]
-
- if args.get("party_type") == 'Customer':
- cols += ["contact"]
-
- cols += ["voucher_type", "voucher_no", "due_date"]
-
- if args.get("party_type") == "Supplier":
- cols += ["bill_no", "bill_date"]
-
- cols += ["invoiced_amt", "paid_amt", "credit_amt",
- "outstanding_amt", "age", "range1", "range2", "range3", "range4", "range5", "currency", "pdc/lc_date", "pdc/lc_ref",
- "pdc/lc_amount"]
-
- if args.get("party_type") == "Supplier":
- cols += ["supplier_group", "remarks"]
- if args.get("party_type") == "Customer":
- cols += ["po_no", "do_no", "territory", "customer_group", "sales_person", "remarks"]
-
- return self.make_data_dict(cols, voucherwise_data)
-
- def make_data_dict(self, cols, data):
- data_dict = []
- for d in data:
- data_dict.append(frappe._dict(zip(cols, d)))
-
- return data_dict
def execute(filters=None):
args = {
@@ -241,3 +16,119 @@
}
return AccountsReceivableSummary(filters).run(args)
+
+class AccountsReceivableSummary(ReceivablePayableReport):
+ def run(self, args):
+ self.party_type = args.get('party_type')
+ self.party_naming_by = frappe.db.get_value(args.get("naming_by")[0], None, args.get("naming_by")[1])
+ self.get_columns()
+ self.get_data(args)
+ return self.columns, self.data
+
+ def get_data(self, args):
+ self.data = []
+
+ self.receivables = ReceivablePayableReport(self.filters).run(args)[1]
+
+ self.get_party_total(args)
+
+ party_advance_amount = get_partywise_advanced_payment_amount(self.party_type,
+ self.filters.report_date) or {}
+
+ for party, party_dict in iteritems(self.party_total):
+ row = frappe._dict()
+
+ row.party = party
+ if self.party_naming_by == "Naming Series":
+ row.party_name = frappe.get_cached_value(self.party_type, party, [self.party_type + "_name"])
+
+ row.update(party_dict)
+
+ # Advance against party
+ row.advance = party_advance_amount.get(party, 0)
+
+ # In AR/AP, advance shown in paid columns,
+ # but in summary report advance shown in separate column
+ row.paid -= row.advance
+
+ self.data.append(row)
+
+ def get_party_total(self, args):
+ self.party_total = frappe._dict()
+
+ for d in self.receivables:
+ self.init_party_total(d)
+
+ # Add all amount columns
+ for k in list(self.party_total[d.party]):
+ if k not in ["currency", "sales_person"]:
+
+ self.party_total[d.party][k] += d.get(k, 0.0)
+
+ # set territory, customer_group, sales person etc
+ self.set_party_details(d)
+
+ def init_party_total(self, row):
+ self.party_total.setdefault(row.party, frappe._dict({
+ "invoiced": 0.0,
+ "paid": 0.0,
+ "credit_note": 0.0,
+ "outstanding": 0.0,
+ "range1": 0.0,
+ "range2": 0.0,
+ "range3": 0.0,
+ "range4": 0.0,
+ "range5": 0.0,
+ "sales_person": []
+ }))
+
+ def set_party_details(self, row):
+ self.party_total[row.party].currency = row.currency
+
+ for key in ('territory', 'customer_group', 'supplier_group'):
+ if row.get(key):
+ self.party_total[row.party][key] = row.get(key)
+
+ if row.sales_person:
+ self.party_total[row.party].sales_person.append(row.sales_person)
+
+ def get_columns(self):
+ self.columns = []
+ self.add_column(label=_(self.party_type), fieldname='party',
+ fieldtype='Link', options=self.party_type, width=180)
+
+ if self.party_naming_by == "Naming Series":
+ self.add_column(_('{0} Name').format(self.party_type),
+ fieldname = 'party_name', fieldtype='Data')
+
+ credit_debit_label = "Credit Note" if self.party_type == 'Customer' else "Debit Note"
+
+ self.add_column(_('Advance Amount'), fieldname='advance')
+ self.add_column(_('Invoiced Amount'), fieldname='invoiced')
+ self.add_column(_('Paid Amount'), fieldname='paid')
+ self.add_column(_(credit_debit_label), fieldname='credit_note')
+ self.add_column(_('Outstanding Amount'), fieldname='outstanding')
+
+ self.setup_ageing_columns()
+
+ if self.party_type == "Customer":
+ self.add_column(label=_('Territory'), fieldname='territory', fieldtype='Link',
+ options='Territory')
+ self.add_column(label=_('Customer Group'), fieldname='customer_group', fieldtype='Link',
+ options='Customer Group')
+ if self.filters.show_sales_person:
+ self.add_column(label=_('Sales Person'), fieldname='sales_person', fieldtype='Data')
+ else:
+ self.add_column(label=_('Supplier Group'), fieldname='supplier_group', fieldtype='Link',
+ options='Supplier Group')
+
+ self.add_column(label=_('Currency'), fieldname='currency', fieldtype='Link',
+ options='Currency', width=80)
+
+ def setup_ageing_columns(self):
+ for i, label in enumerate(["0-{range1}".format(range1=self.filters["range1"]),
+ "{range1}-{range2}".format(range1=cint(self.filters["range1"])+ 1, range2=self.filters["range2"]),
+ "{range2}-{range3}".format(range2=cint(self.filters["range2"])+ 1, range3=self.filters["range3"]),
+ "{range3}-{range4}".format(range3=cint(self.filters["range3"])+ 1, range4=self.filters["range4"]),
+ "{range4}-{above}".format(range4=cint(self.filters["range4"])+ 1, above=_("Above"))]):
+ self.add_column(label=label, fieldname='range' + str(i+1))
\ No newline at end of file
diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py
index 7d9acf2..97ce4f2 100644
--- a/erpnext/accounts/report/balance_sheet/balance_sheet.py
+++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py
@@ -135,11 +135,11 @@
datasets = []
if asset_data:
- datasets.append({'name':'Assets', 'values': asset_data})
+ datasets.append({'name': _('Assets'), 'values': asset_data})
if liability_data:
- datasets.append({'name':'Liabilities', 'values': liability_data})
+ datasets.append({'name': _('Liabilities'), 'values': liability_data})
if equity_data:
- datasets.append({'name':'Equity', 'values': equity_data})
+ datasets.append({'name': _('Equity'), 'values': equity_data})
chart = {
"data": {
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index 7b9c939..3c8de60 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -425,9 +425,12 @@
all_cost_centers = []
for d in cost_centers:
- lft, rgt = frappe.db.get_value("Cost Center", d, ["lft", "rgt"])
- children = frappe.get_all("Cost Center", filters={"lft": [">=", lft], "rgt": ["<=", rgt]})
- all_cost_centers += [c.name for c in children]
+ if frappe.db.exists("Cost Center", d):
+ lft, rgt = frappe.db.get_value("Cost Center", d, ["lft", "rgt"])
+ children = frappe.get_all("Cost Center", filters={"lft": [">=", lft], "rgt": ["<=", rgt]})
+ all_cost_centers += [c.name for c in children]
+ else:
+ frappe.throw(_("Cost Center: {0} does not exist".format(d)))
return list(set(all_cost_centers))
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 86fd108..ec3fb1f 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -119,19 +119,11 @@
select_fields = """, debit, credit, debit_in_account_currency,
credit_in_account_currency """
- group_by_statement = ''
order_by_statement = "order by posting_date, account"
if filters.get("group_by") == _("Group by Voucher"):
order_by_statement = "order by posting_date, voucher_type, voucher_no"
- if filters.get("group_by") == _("Group by Voucher (Consolidated)"):
- group_by_statement = "group by voucher_type, voucher_no, account, cost_center"
-
- select_fields = """, sum(debit) as debit, sum(credit) as credit,
- sum(debit_in_account_currency) as debit_in_account_currency,
- sum(credit_in_account_currency) as credit_in_account_currency"""
-
if filters.get("include_default_book_entries"):
filters['company_fb'] = frappe.db.get_value("Company",
filters.get("company"), 'default_finance_book')
@@ -144,11 +136,10 @@
against_voucher_type, against_voucher, account_currency,
remarks, against, is_opening {select_fields}
from `tabGL Entry`
- where company=%(company)s {conditions} {group_by_statement}
+ where company=%(company)s {conditions}
{order_by_statement}
""".format(
select_fields=select_fields, conditions=get_conditions(filters),
- group_by_statement=group_by_statement,
order_by_statement=order_by_statement
),
filters, as_dict=1)
@@ -185,7 +176,8 @@
if not (filters.get("account") or filters.get("party") or
filters.get("group_by") in ["Group by Account", "Group by Party"]):
conditions.append("posting_date >=%(from_date)s")
- conditions.append("posting_date <=%(to_date)s")
+
+ conditions.append("(posting_date <=%(to_date)s or is_opening = 'Yes')")
if filters.get("project"):
conditions.append("project in %(project)s")
@@ -286,6 +278,7 @@
def get_accountwise_gle(filters, gl_entries, gle_map):
totals = get_totals_dict()
entries = []
+ consolidated_gle = OrderedDict()
group_by = group_by_field(filters.get('group_by'))
def update_value_in_dict(data, key, gle):
@@ -310,12 +303,20 @@
update_value_in_dict(totals, 'total', gle)
if filters.get("group_by") != _('Group by Voucher (Consolidated)'):
gle_map[gle.get(group_by)].entries.append(gle)
- else:
- entries.append(gle)
+ elif filters.get("group_by") == _('Group by Voucher (Consolidated)'):
+ key = (gle.get("voucher_type"), gle.get("voucher_no"),
+ gle.get("account"), gle.get("cost_center"))
+ if key not in consolidated_gle:
+ consolidated_gle.setdefault(key, gle)
+ else:
+ update_value_in_dict(consolidated_gle, key, gle)
update_value_in_dict(gle_map[gle.get(group_by)].totals, 'closing', gle)
update_value_in_dict(totals, 'closing', gle)
+ for key, value in consolidated_gle.items():
+ entries.append(value)
+
return totals, entries
def get_result_as_list(data, filters):
diff --git a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.js b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.js
index ca24394..2343eaa 100644
--- a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.js
+++ b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.js
@@ -27,8 +27,8 @@
fieldname:"payment_type",
label: __("Payment Type"),
fieldtype: "Select",
- options: "Incoming\nOutgoing",
- default: "Incoming"
+ options: __("Incoming") + "\n" + __("Outgoing"),
+ default: __("Incoming")
},
{
"fieldname":"party_type",
diff --git a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py
index 89e0113..24b5d87 100644
--- a/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py
+++ b/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py
@@ -39,8 +39,8 @@
return columns, data
def validate_filters(filters):
- if (filters.get("payment_type") == "Incoming" and filters.get("party_type") == "Supplier") or \
- (filters.get("payment_type") == "Outgoing" and filters.get("party_type") == "Customer"):
+ if (filters.get("payment_type") == _("Incoming") and filters.get("party_type") == "Supplier") or \
+ (filters.get("payment_type") == _("Outgoing") and filters.get("party_type") == "Customer"):
frappe.throw(_("{0} payment entries can not be filtered by {1}")\
.format(filters.payment_type, filters.party_type))
@@ -51,7 +51,7 @@
_("Party Type") + "::100",
_("Party") + ":Dynamic Link/Party Type:140",
_("Posting Date") + ":Date:100",
- _("Invoice") + (":Link/Purchase Invoice:130" if filters.get("payment_type") == "Outgoing" else ":Link/Sales Invoice:130"),
+ _("Invoice") + (":Link/Purchase Invoice:130" if filters.get("payment_type") == _("Outgoing") else ":Link/Sales Invoice:130"),
_("Invoice Posting Date") + ":Date:130",
_("Payment Due Date") + ":Date:130",
_("Debit") + ":Currency:120",
@@ -69,7 +69,7 @@
conditions = []
if not filters.party_type:
- if filters.payment_type == "Outgoing":
+ if filters.payment_type == _("Outgoing"):
filters.party_type = "Supplier"
else:
filters.party_type = "Customer"
@@ -101,7 +101,7 @@
def get_invoice_posting_date_map(filters):
invoice_details = {}
- dt = "Sales Invoice" if filters.get("payment_type") == "Incoming" else "Purchase Invoice"
+ dt = "Sales Invoice" if filters.get("payment_type") == _("Incoming") else "Purchase Invoice"
for t in frappe.db.sql("select name, posting_date, due_date from `tab{0}`".format(dt), as_dict=1):
invoice_details[t.name] = t
diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py
index ac11868..d500c81 100644
--- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py
+++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py
@@ -75,11 +75,11 @@
datasets = []
if income_data:
- datasets.append({'name': 'Income', 'values': income_data})
+ datasets.append({'name': _('Income'), 'values': income_data})
if expense_data:
- datasets.append({'name': 'Expense', 'values': expense_data})
+ datasets.append({'name': _('Expense'), 'values': expense_data})
if net_profit:
- datasets.append({'name': 'Net Profit/Loss', 'values': net_profit})
+ datasets.append({'name': _('Net Profit/Loss'), 'values': net_profit})
chart = {
"data": {
diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js
index 2d78d26..c5cad73 100644
--- a/erpnext/assets/doctype/asset/asset.js
+++ b/erpnext/assets/doctype/asset/asset.js
@@ -303,14 +303,17 @@
},
set_depreciation_rate: function(frm, row) {
- if (row.total_number_of_depreciations && row.frequency_of_depreciation) {
+ if (row.total_number_of_depreciations && row.frequency_of_depreciation
+ && row.expected_value_after_useful_life) {
frappe.call({
method: "get_depreciation_rate",
doc: frm.doc,
args: row,
callback: function(r) {
if (r.message) {
- frappe.model.set_value(row.doctype, row.name, "rate_of_depreciation", r.message);
+ frappe.flags.dont_change_rate = true;
+ frappe.model.set_value(row.doctype, row.name,
+ "rate_of_depreciation", flt(r.message, precision("rate_of_depreciation", row)));
}
}
});
@@ -338,6 +341,14 @@
total_number_of_depreciations: function(frm, cdt, cdn) {
const row = locals[cdt][cdn];
frm.events.set_depreciation_rate(frm, row);
+ },
+
+ rate_of_depreciation: function(frm, cdt, cdn) {
+ if(!frappe.flags.dont_change_rate) {
+ frappe.model.set_value(cdt, cdn, "expected_value_after_useful_life", 0);
+ }
+
+ frappe.flags.dont_change_rate = false;
}
});
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index c398a73..8f208e2 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -6,7 +6,7 @@
import frappe, erpnext, math, json
from frappe import _
from six import string_types
-from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff
+from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff, add_days
from frappe.model.document import Document
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
from erpnext.assets.doctype.asset.depreciation \
@@ -101,97 +101,88 @@
def set_depreciation_rate(self):
for d in self.get("finance_books"):
- d.rate_of_depreciation = self.get_depreciation_rate(d, on_validate=True)
+ d.rate_of_depreciation = flt(self.get_depreciation_rate(d, on_validate=True),
+ d.precision("rate_of_depreciation"))
def make_depreciation_schedule(self):
- depreciation_method = [d.depreciation_method for d in self.finance_books]
-
- if 'Manual' not in depreciation_method:
+ if 'Manual' not in [d.depreciation_method for d in self.finance_books]:
self.schedules = []
- if not self.get("schedules") and self.available_for_use_date:
- total_depreciations = sum([d.total_number_of_depreciations for d in self.get('finance_books')])
+ if self.get("schedules") or not self.available_for_use_date:
+ return
- for d in self.get('finance_books'):
- self.validate_asset_finance_books(d)
+ for d in self.get('finance_books'):
+ self.validate_asset_finance_books(d)
- value_after_depreciation = (flt(self.gross_purchase_amount) -
- flt(self.opening_accumulated_depreciation))
+ value_after_depreciation = (flt(self.gross_purchase_amount) -
+ flt(self.opening_accumulated_depreciation))
- d.value_after_depreciation = value_after_depreciation
+ d.value_after_depreciation = value_after_depreciation
- no_of_depreciations = cint(d.total_number_of_depreciations - 1) - cint(self.number_of_depreciations_booked)
- end_date = add_months(d.depreciation_start_date,
- no_of_depreciations * cint(d.frequency_of_depreciation))
+ number_of_pending_depreciations = cint(d.total_number_of_depreciations) - \
+ cint(self.number_of_depreciations_booked)
- total_days = date_diff(end_date, self.available_for_use_date)
- rate_per_day = (value_after_depreciation - d.get("expected_value_after_useful_life")) / total_days
+ has_pro_rata = self.check_is_pro_rata(d)
- number_of_pending_depreciations = cint(d.total_number_of_depreciations) - \
- cint(self.number_of_depreciations_booked)
+ if has_pro_rata:
+ number_of_pending_depreciations += 1
- from_date = self.available_for_use_date
- if number_of_pending_depreciations:
- next_depr_date = getdate(add_months(self.available_for_use_date,
- number_of_pending_depreciations * 12))
- if (cint(frappe.db.get_value("Asset Settings", None, "schedule_based_on_fiscal_year")) == 1
- and getdate(d.depreciation_start_date) < next_depr_date):
+ skip_row = False
+ for n in range(number_of_pending_depreciations):
+ # If depreciation is already completed (for double declining balance)
+ if skip_row: continue
- number_of_pending_depreciations += 1
- for n in range(number_of_pending_depreciations):
- if n == list(range(number_of_pending_depreciations))[-1]:
- schedule_date = add_months(self.available_for_use_date, n * 12)
- previous_scheduled_date = add_months(d.depreciation_start_date, (n-1) * 12)
- depreciation_amount = \
- self.get_depreciation_amount_prorata_temporis(value_after_depreciation,
- d, previous_scheduled_date, schedule_date)
+ depreciation_amount = self.get_depreciation_amount(value_after_depreciation,
+ d.total_number_of_depreciations, d)
- elif n == list(range(number_of_pending_depreciations))[0]:
- schedule_date = d.depreciation_start_date
- depreciation_amount = \
- self.get_depreciation_amount_prorata_temporis(value_after_depreciation,
- d, self.available_for_use_date, schedule_date)
+ if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1:
+ schedule_date = add_months(d.depreciation_start_date,
+ n * cint(d.frequency_of_depreciation))
- else:
- schedule_date = add_months(d.depreciation_start_date, n * 12)
- depreciation_amount = \
- self.get_depreciation_amount_prorata_temporis(value_after_depreciation, d)
+ # For first row
+ if has_pro_rata and n==0:
+ depreciation_amount, days = get_pro_rata_amt(d, depreciation_amount,
+ self.available_for_use_date, d.depreciation_start_date)
+ # For last row
+ elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1:
+ to_date = add_months(self.available_for_use_date,
+ n * cint(d.frequency_of_depreciation))
- if value_after_depreciation != 0:
- value_after_depreciation -= flt(depreciation_amount)
+ depreciation_amount, days = get_pro_rata_amt(d,
+ depreciation_amount, schedule_date, to_date)
- self.append("schedules", {
- "schedule_date": schedule_date,
- "depreciation_amount": depreciation_amount,
- "depreciation_method": d.depreciation_method,
- "finance_book": d.finance_book,
- "finance_book_id": d.idx
- })
- else:
- for n in range(number_of_pending_depreciations):
- schedule_date = add_months(d.depreciation_start_date,
- n * cint(d.frequency_of_depreciation))
+ schedule_date = add_days(schedule_date, days)
- if d.depreciation_method in ("Straight Line", "Manual"):
- days = date_diff(schedule_date, from_date)
- if n == 0: days += 1
+ if not depreciation_amount: continue
+ value_after_depreciation -= flt(depreciation_amount,
+ self.precision("gross_purchase_amount"))
- depreciation_amount = days * rate_per_day
- from_date = schedule_date
- else:
- depreciation_amount = self.get_depreciation_amount(value_after_depreciation,
- d.total_number_of_depreciations, d)
+ # Adjust depreciation amount in the last period based on the expected value after useful life
+ if d.expected_value_after_useful_life and ((n == cint(number_of_pending_depreciations) - 1
+ and value_after_depreciation != d.expected_value_after_useful_life)
+ or value_after_depreciation < d.expected_value_after_useful_life):
+ depreciation_amount += (value_after_depreciation - d.expected_value_after_useful_life)
+ skip_row = True
- if depreciation_amount:
- value_after_depreciation -= flt(depreciation_amount)
+ if depreciation_amount > 0:
+ self.append("schedules", {
+ "schedule_date": schedule_date,
+ "depreciation_amount": depreciation_amount,
+ "depreciation_method": d.depreciation_method,
+ "finance_book": d.finance_book,
+ "finance_book_id": d.idx
+ })
- self.append("schedules", {
- "schedule_date": schedule_date,
- "depreciation_amount": depreciation_amount,
- "depreciation_method": d.depreciation_method,
- "finance_book": d.finance_book,
- "finance_book_id": d.idx
- })
+ def check_is_pro_rata(self, row):
+ has_pro_rata = False
+
+ days = date_diff(row.depreciation_start_date, self.available_for_use_date) + 1
+ total_days = get_total_days(row.depreciation_start_date, row.frequency_of_depreciation)
+
+ if days < total_days:
+ has_pro_rata = True
+
+ return has_pro_rata
def validate_asset_finance_books(self, row):
if flt(row.expected_value_after_useful_life) >= flt(self.gross_purchase_amount):
@@ -261,31 +252,20 @@
return flt(self.get('finance_books')[cint(idx)-1].value_after_depreciation)
def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row):
- if row.depreciation_method in ["Straight Line", "Manual"]:
- amt = (flt(self.gross_purchase_amount) - flt(row.expected_value_after_useful_life) -
- flt(self.opening_accumulated_depreciation))
-
- depreciation_amount = amt * row.rate_of_depreciation
- else:
- depreciation_amount = flt(depreciable_value) * (flt(row.rate_of_depreciation) / 100)
- value_after_depreciation = flt(depreciable_value) - depreciation_amount
- if value_after_depreciation < flt(row.expected_value_after_useful_life):
- depreciation_amount = flt(depreciable_value) - flt(row.expected_value_after_useful_life)
-
- return depreciation_amount
-
- def get_depreciation_amount_prorata_temporis(self, depreciable_value, row, start_date=None, end_date=None):
- if start_date and end_date:
- prorata_temporis = min(abs(flt(date_diff(str(end_date), str(start_date)))) / flt(frappe.db.get_value("Asset Settings", None, "number_of_days_in_fiscal_year")), 1)
- else:
- prorata_temporis = 1
+ precision = self.precision("gross_purchase_amount")
if row.depreciation_method in ("Straight Line", "Manual"):
+ depreciation_left = (cint(row.total_number_of_depreciations) - cint(self.number_of_depreciations_booked))
+
+ if not depreciation_left:
+ frappe.msgprint(_("All the depreciations has been booked"))
+ depreciation_amount = flt(row.expected_value_after_useful_life)
+ return depreciation_amount
+
depreciation_amount = (flt(row.value_after_depreciation) -
- flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) -
- cint(self.number_of_depreciations_booked)) * prorata_temporis
+ flt(row.expected_value_after_useful_life)) / depreciation_left
else:
- depreciation_amount = self.get_depreciation_amount(depreciable_value, row.total_number_of_depreciations, row)
+ depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100), precision)
return depreciation_amount
@@ -301,20 +281,17 @@
flt(accumulated_depreciation_after_full_schedule),
self.precision('gross_purchase_amount'))
- if row.expected_value_after_useful_life < asset_value_after_full_schedule:
+ if (row.expected_value_after_useful_life and
+ row.expected_value_after_useful_life < asset_value_after_full_schedule):
frappe.throw(_("Depreciation Row {0}: Expected value after useful life must be greater than or equal to {1}")
.format(row.idx, asset_value_after_full_schedule))
+ elif not row.expected_value_after_useful_life:
+ row.expected_value_after_useful_life = asset_value_after_full_schedule
def validate_cancellation(self):
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
frappe.throw(_("Asset cannot be cancelled, as it is already {0}").format(self.status))
- if self.purchase_invoice:
- frappe.throw(_("Please cancel Purchase Invoice {0} first").format(self.purchase_invoice))
-
- if self.purchase_receipt:
- frappe.throw(_("Please cancel Purchase Receipt {0} first").format(self.purchase_receipt))
-
def delete_depreciation_entries(self):
for d in self.get("schedules"):
if d.journal_entry:
@@ -412,15 +389,7 @@
if isinstance(args, string_types):
args = json.loads(args)
- number_of_depreciations_booked = 0
- if self.is_existing_asset:
- number_of_depreciations_booked = self.number_of_depreciations_booked
-
float_precision = cint(frappe.db.get_default("float_precision")) or 2
- tot_no_of_depreciation = flt(args.get("total_number_of_depreciations")) - flt(number_of_depreciations_booked)
-
- if args.get("depreciation_method") in ["Straight Line", "Manual"]:
- return 1.0 / tot_no_of_depreciation
if args.get("depreciation_method") == 'Double Declining Balance':
return 200.0 / args.get("total_number_of_depreciations")
@@ -600,3 +569,15 @@
def is_cwip_accounting_disabled():
return cint(frappe.db.get_single_value("Asset Settings", "disable_cwip_accounting"))
+
+def get_pro_rata_amt(row, depreciation_amount, from_date, to_date):
+ days = date_diff(to_date, from_date)
+ total_days = get_total_days(to_date, row.frequency_of_depreciation)
+
+ return (depreciation_amount * flt(days)) / flt(total_days), days
+
+def get_total_days(date, frequency):
+ period_start_date = add_months(date,
+ cint(frequency) * -1)
+
+ return date_diff(date, period_start_date)
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index fceccfb..c09b94f 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -88,23 +88,23 @@
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
asset = frappe.get_doc('Asset', asset_name)
asset.calculate_depreciation = 1
- asset.available_for_use_date = '2020-06-06'
- asset.purchase_date = '2020-06-06'
+ asset.available_for_use_date = '2030-01-01'
+ asset.purchase_date = '2030-01-01'
asset.append("finance_books", {
"expected_value_after_useful_life": 10000,
- "next_depreciation_date": "2020-12-31",
"depreciation_method": "Straight Line",
"total_number_of_depreciations": 3,
- "frequency_of_depreciation": 10,
- "depreciation_start_date": "2020-06-06"
+ "frequency_of_depreciation": 12,
+ "depreciation_start_date": "2030-12-31"
})
asset.save()
+
self.assertEqual(asset.status, "Draft")
expected_schedules = [
- ["2020-06-06", 147.54, 147.54],
- ["2021-04-06", 44852.46, 45000.0],
- ["2022-02-06", 45000.0, 90000.00]
+ ["2030-12-31", 30000.00, 30000.00],
+ ["2031-12-31", 30000.00, 60000.00],
+ ["2032-12-31", 30000.00, 90000.00]
]
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
@@ -118,20 +118,21 @@
asset.calculate_depreciation = 1
asset.number_of_depreciations_booked = 1
asset.opening_accumulated_depreciation = 40000
+ asset.available_for_use_date = "2030-06-06"
asset.append("finance_books", {
"expected_value_after_useful_life": 10000,
- "next_depreciation_date": "2020-12-31",
"depreciation_method": "Straight Line",
"total_number_of_depreciations": 3,
- "frequency_of_depreciation": 10,
- "depreciation_start_date": "2020-06-06"
+ "frequency_of_depreciation": 12,
+ "depreciation_start_date": "2030-12-31"
})
asset.insert()
self.assertEqual(asset.status, "Draft")
asset.save()
expected_schedules = [
- ["2020-06-06", 164.47, 40164.47],
- ["2021-04-06", 49835.53, 90000.00]
+ ["2030-12-31", 14246.58, 54246.58],
+ ["2031-12-31", 25000.00, 79246.58],
+ ["2032-06-06", 10753.42, 90000.00]
]
schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount]
for d in asset.get("schedules")]
@@ -145,24 +146,23 @@
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
asset = frappe.get_doc('Asset', asset_name)
asset.calculate_depreciation = 1
- asset.available_for_use_date = '2020-06-06'
- asset.purchase_date = '2020-06-06'
+ asset.available_for_use_date = '2030-01-01'
+ asset.purchase_date = '2030-01-01'
asset.append("finance_books", {
"expected_value_after_useful_life": 10000,
- "next_depreciation_date": "2020-12-31",
"depreciation_method": "Double Declining Balance",
"total_number_of_depreciations": 3,
- "frequency_of_depreciation": 10,
- "depreciation_start_date": "2020-06-06"
+ "frequency_of_depreciation": 12,
+ "depreciation_start_date": '2030-12-31'
})
asset.insert()
self.assertEqual(asset.status, "Draft")
asset.save()
expected_schedules = [
- ["2020-06-06", 66666.67, 66666.67],
- ["2021-04-06", 22222.22, 88888.89],
- ["2022-02-06", 1111.11, 90000.0]
+ ['2030-12-31', 66667.00, 66667.00],
+ ['2031-12-31', 22222.11, 88889.11],
+ ['2032-12-31', 1110.89, 90000.0]
]
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
@@ -177,23 +177,21 @@
asset.is_existing_asset = 1
asset.number_of_depreciations_booked = 1
asset.opening_accumulated_depreciation = 50000
+ asset.available_for_use_date = '2030-01-01'
+ asset.purchase_date = '2029-11-30'
asset.append("finance_books", {
"expected_value_after_useful_life": 10000,
- "next_depreciation_date": "2020-12-31",
"depreciation_method": "Double Declining Balance",
"total_number_of_depreciations": 3,
- "frequency_of_depreciation": 10,
- "depreciation_start_date": "2020-06-06"
+ "frequency_of_depreciation": 12,
+ "depreciation_start_date": "2030-12-31"
})
asset.insert()
self.assertEqual(asset.status, "Draft")
- asset.save()
-
- asset.save()
expected_schedules = [
- ["2020-06-06", 33333.33, 83333.33],
- ["2021-04-06", 6666.67, 90000.0]
+ ["2030-12-31", 33333.50, 83333.50],
+ ["2031-12-31", 6666.50, 90000.0]
]
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
@@ -209,25 +207,25 @@
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
asset = frappe.get_doc('Asset', asset_name)
asset.calculate_depreciation = 1
- asset.purchase_date = '2020-01-30'
+ asset.purchase_date = '2030-01-30'
asset.is_existing_asset = 0
- asset.available_for_use_date = "2020-01-30"
+ asset.available_for_use_date = "2030-01-30"
asset.append("finance_books", {
"expected_value_after_useful_life": 10000,
"depreciation_method": "Straight Line",
"total_number_of_depreciations": 3,
- "frequency_of_depreciation": 10,
- "depreciation_start_date": "2020-12-31"
+ "frequency_of_depreciation": 12,
+ "depreciation_start_date": "2030-12-31"
})
asset.insert()
asset.save()
expected_schedules = [
- ["2020-12-31", 28000.0, 28000.0],
- ["2021-12-31", 30000.0, 58000.0],
- ["2022-12-31", 30000.0, 88000.0],
- ["2023-01-30", 2000.0, 90000.0]
+ ["2030-12-31", 27534.25, 27534.25],
+ ["2031-12-31", 30000.0, 57534.25],
+ ["2032-12-31", 30000.0, 87534.25],
+ ["2033-01-30", 2465.75, 90000.0]
]
schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)]
@@ -266,8 +264,8 @@
self.assertEqual(asset.get("schedules")[0].journal_entry[:4], "DEPR")
expected_gle = (
- ("_Test Accumulated Depreciations - _TC", 0.0, 32129.24),
- ("_Test Depreciations - _TC", 32129.24, 0.0)
+ ("_Test Accumulated Depreciations - _TC", 0.0, 30000.0),
+ ("_Test Depreciations - _TC", 30000.0, 0.0)
)
gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
@@ -277,15 +275,15 @@
self.assertEqual(gle, expected_gle)
self.assertEqual(asset.get("value_after_depreciation"), 0)
- def test_depreciation_entry_for_wdv(self):
+ def test_depreciation_entry_for_wdv_without_pro_rata(self):
pr = make_purchase_receipt(item_code="Macbook Pro",
qty=1, rate=8000.0, location="Test Location")
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
asset = frappe.get_doc('Asset', asset_name)
asset.calculate_depreciation = 1
- asset.available_for_use_date = '2030-06-06'
- asset.purchase_date = '2030-06-06'
+ asset.available_for_use_date = '2030-01-01'
+ asset.purchase_date = '2030-01-01'
asset.append("finance_books", {
"expected_value_after_useful_life": 1000,
"depreciation_method": "Written Down Value",
@@ -298,9 +296,41 @@
self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0)
expected_schedules = [
- ["2030-12-31", 4000.0, 4000.0],
- ["2031-12-31", 2000.0, 6000.0],
- ["2032-12-31", 1000.0, 7000.0],
+ ["2030-12-31", 4000.00, 4000.00],
+ ["2031-12-31", 2000.00, 6000.00],
+ ["2032-12-31", 1000.00, 7000.0],
+ ]
+
+ schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)]
+ for d in asset.get("schedules")]
+
+ self.assertEqual(schedules, expected_schedules)
+
+ def test_pro_rata_depreciation_entry_for_wdv(self):
+ pr = make_purchase_receipt(item_code="Macbook Pro",
+ qty=1, rate=8000.0, location="Test Location")
+
+ asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
+ asset = frappe.get_doc('Asset', asset_name)
+ asset.calculate_depreciation = 1
+ asset.available_for_use_date = '2030-06-06'
+ asset.purchase_date = '2030-01-01'
+ asset.append("finance_books", {
+ "expected_value_after_useful_life": 1000,
+ "depreciation_method": "Written Down Value",
+ "total_number_of_depreciations": 3,
+ "frequency_of_depreciation": 12,
+ "depreciation_start_date": "2030-12-31"
+ })
+ asset.save(ignore_permissions=True)
+
+ self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0)
+
+ expected_schedules = [
+ ["2030-12-31", 2279.45, 2279.45],
+ ["2031-12-31", 2860.28, 5139.73],
+ ["2032-12-31", 1430.14, 6569.87],
+ ["2033-06-06", 430.13, 7000.0],
]
schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)]
@@ -346,18 +376,19 @@
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
asset = frappe.get_doc('Asset', asset_name)
asset.calculate_depreciation = 1
- asset.available_for_use_date = '2020-06-06'
- asset.purchase_date = '2020-06-06'
+ asset.available_for_use_date = nowdate()
+ asset.purchase_date = nowdate()
asset.append("finance_books", {
"expected_value_after_useful_life": 10000,
"depreciation_method": "Straight Line",
"total_number_of_depreciations": 3,
"frequency_of_depreciation": 10,
- "depreciation_start_date": "2020-06-06"
+ "depreciation_start_date": nowdate()
})
asset.insert()
asset.submit()
- post_depreciation_entries(date="2021-01-01")
+
+ post_depreciation_entries(date=add_months(nowdate(), 10))
scrap_asset(asset.name)
@@ -366,9 +397,9 @@
self.assertTrue(asset.journal_entry_for_scrap)
expected_gle = (
- ("_Test Accumulated Depreciations - _TC", 147.54, 0.0),
+ ("_Test Accumulated Depreciations - _TC", 30000.0, 0.0),
("_Test Fixed Asset - _TC", 0.0, 100000.0),
- ("_Test Gain/Loss on Asset Disposal - _TC", 99852.46, 0.0)
+ ("_Test Gain/Loss on Asset Disposal - _TC", 70000.0, 0.0)
)
gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
@@ -412,9 +443,9 @@
self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold")
expected_gle = (
- ("_Test Accumulated Depreciations - _TC", 23051.47, 0.0),
+ ("_Test Accumulated Depreciations - _TC", 20392.16, 0.0),
("_Test Fixed Asset - _TC", 0.0, 100000.0),
- ("_Test Gain/Loss on Asset Disposal - _TC", 51948.53, 0.0),
+ ("_Test Gain/Loss on Asset Disposal - _TC", 54607.84, 0.0),
("Debtors - _TC", 25000.0, 0.0)
)
@@ -425,8 +456,6 @@
self.assertEqual(gle, expected_gle)
si.cancel()
- frappe.delete_doc("Sales Invoice", si.name)
-
self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated")
def test_asset_expected_value_after_useful_life(self):
diff --git a/erpnext/assets/doctype/asset_settings/asset_settings.json b/erpnext/assets/doctype/asset_settings/asset_settings.json
index a3fee96..edc5ce1 100644
--- a/erpnext/assets/doctype/asset_settings/asset_settings.json
+++ b/erpnext/assets/doctype/asset_settings/asset_settings.json
@@ -54,75 +54,6 @@
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
- "fieldname": "schedule_based_on_fiscal_year",
- "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": "Calculate Prorated Depreciation Schedule Based on Fiscal Year",
- "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,
- "default": "360",
- "depends_on": "eval:doc.schedule_based_on_fiscal_year",
- "description": "This value is used for pro-rata temporis calculation",
- "fetch_if_empty": 0,
- "fieldname": "number_of_days_in_fiscal_year",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Number of Days in Fiscal Year",
- "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,
- "fetch_if_empty": 0,
"fieldname": "disable_cwip_accounting",
"fieldtype": "Check",
"hidden": 0,
@@ -159,7 +90,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
- "modified": "2019-03-08 10:44:41.924547",
+ "modified": "2019-05-26 18:31:19.930563",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Settings",
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.js b/erpnext/buying/doctype/buying_settings/buying_settings.js
new file mode 100644
index 0000000..403b1c9
--- /dev/null
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Buying Settings', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json
index f2eec4f..a492519 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.json
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.json
@@ -1,379 +1,111 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2013-06-25 11:04:03",
- "custom": 0,
- "description": "Settings for Buying Module",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Other",
- "editable_grid": 0,
+ "creation": "2013-06-25 11:04:03",
+ "description": "Settings for Buying Module",
+ "doctype": "DocType",
+ "document_type": "Other",
+ "field_order": [
+ "supp_master_name",
+ "supplier_group",
+ "buying_price_list",
+ "column_break_3",
+ "po_required",
+ "pr_required",
+ "maintain_same_rate",
+ "allow_multiple_items",
+ "subcontract",
+ "backflush_raw_materials_of_subcontract_based_on",
+ "column_break_11",
+ "over_transfer_allowance"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Supplier Name",
- "fieldname": "supp_master_name",
- "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": "Supplier Naming By",
- "length": 0,
- "no_copy": 0,
- "options": "Supplier Name\nNaming Series",
- "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": "supplier_group",
- "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": "Default Supplier Group",
- "length": 0,
- "no_copy": 0,
- "options": "Supplier Group",
- "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": "buying_price_list",
- "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": "Default Buying Price List",
- "length": 0,
- "no_copy": 0,
- "options": "Price List",
- "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": "column_break_3",
- "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,
- "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": "po_required",
- "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": "Purchase Order Required",
- "length": 0,
- "no_copy": 0,
- "options": "No\nYes",
- "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": "pr_required",
- "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": "Purchase Receipt Required",
- "length": 0,
- "no_copy": 0,
- "options": "No\nYes",
- "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": "maintain_same_rate",
- "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": "Maintain same rate throughout purchase cycle",
- "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": "allow_multiple_items",
- "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": "Allow Item to be added multiple times in a transaction",
- "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
+ "default": "Supplier Name",
+ "fieldname": "supp_master_name",
+ "fieldtype": "Select",
+ "label": "Supplier Naming By",
+ "options": "Supplier Name\nNaming Series"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "subcontract",
- "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": "Subcontract",
- "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
- },
+ "fieldname": "supplier_group",
+ "fieldtype": "Link",
+ "label": "Default Supplier Group",
+ "options": "Supplier Group"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Material Transferred for Subcontract",
- "fieldname": "backflush_raw_materials_of_subcontract_based_on",
- "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": "Backflush Raw Materials of Subcontract Based On",
- "length": 0,
- "no_copy": 0,
- "options": "BOM\nMaterial Transferred for Subcontract",
- "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
+ "fieldname": "buying_price_list",
+ "fieldtype": "Link",
+ "label": "Default Buying Price List",
+ "options": "Price List"
+ },
+ {
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "po_required",
+ "fieldtype": "Select",
+ "label": "Purchase Order Required",
+ "options": "No\nYes"
+ },
+ {
+ "fieldname": "pr_required",
+ "fieldtype": "Select",
+ "label": "Purchase Receipt Required",
+ "options": "No\nYes"
+ },
+ {
+ "default": "0",
+ "fieldname": "maintain_same_rate",
+ "fieldtype": "Check",
+ "label": "Maintain same rate throughout purchase cycle"
+ },
+ {
+ "default": "0",
+ "fieldname": "allow_multiple_items",
+ "fieldtype": "Check",
+ "label": "Allow Item to be added multiple times in a transaction"
+ },
+ {
+ "fieldname": "subcontract",
+ "fieldtype": "Section Break",
+ "label": "Subcontract"
+ },
+ {
+ "default": "Material Transferred for Subcontract",
+ "fieldname": "backflush_raw_materials_of_subcontract_based_on",
+ "fieldtype": "Select",
+ "label": "Backflush Raw Materials of Subcontract Based On",
+ "options": "BOM\nMaterial Transferred for Subcontract"
+ },
+ {
+ "depends_on": "eval:doc.backflush_raw_materials_of_subcontract_based_on == \"BOM\"",
+ "description": "Percentage you are allowed to transfer more against the quantity ordered. For example: If you have ordered 100 units. and your Allowance is 10% then you are allowed to transfer 110 units.",
+ "fieldname": "over_transfer_allowance",
+ "fieldtype": "Float",
+ "label": "Over Transfer Allowance (%)"
+ },
+ {
+ "fieldname": "column_break_11",
+ "fieldtype": "Column Break"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-cog",
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 1,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-07-31 07:52:38.062488",
- "modified_by": "Administrator",
- "module": "Buying",
- "name": "Buying Settings",
- "owner": "Administrator",
+ ],
+ "icon": "fa fa-cog",
+ "idx": 1,
+ "issingle": 1,
+ "modified": "2019-08-20 13:13:09.055189",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Buying Settings",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 0,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "role": "System Manager",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "track_changes": 0,
- "track_seen": 0
-}
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/buying/doctype/buying_settings/test_buying_settings.py b/erpnext/buying/doctype/buying_settings/test_buying_settings.py
new file mode 100644
index 0000000..bf6eec6
--- /dev/null
+++ b/erpnext/buying/doctype/buying_settings/test_buying_settings.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestBuyingSettings(unittest.TestCase):
+ pass
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 8117d9d..e3e2f1e 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -477,13 +477,14 @@
rm_item_code = rm_item_data["rm_item_code"]
items_dict = {
rm_item_code: {
+ "po_detail": rm_item_data.get("name"),
"item_name": rm_item_data["item_name"],
"description": item_wh.get(rm_item_code, {}).get('description', ""),
'qty': rm_item_data["qty"],
'from_warehouse': rm_item_data["warehouse"],
'stock_uom': rm_item_data["stock_uom"],
'main_item_code': rm_item_data["item_code"],
- 'allow_alternative_item': item_wh[rm_item_code].get('allow_alternative_item')
+ 'allow_alternative_item': item_wh.get(rm_item_code, {}).get('allow_alternative_item')
}
}
stock_entry.add_to_stock_entry_detail(items_dict)
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order_list.js b/erpnext/buying/doctype/purchase_order/purchase_order_list.js
index a67d69d..8413eb6 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order_list.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order_list.js
@@ -16,9 +16,9 @@
return [__("To Receive"), "orange",
"per_received,<,100|per_billed,=,100|status,!=,Closed"];
}
- } else if (flt(doc.per_received, 2) == 100 && flt(doc.per_billed, 2) < 100 && doc.status !== "Closed") {
+ } else if (flt(doc.per_received, 2) >= 100 && flt(doc.per_billed, 2) < 100 && doc.status !== "Closed") {
return [__("To Bill"), "orange", "per_received,=,100|per_billed,<,100|status,!=,Closed"];
- } else if (flt(doc.per_received, 2) == 100 && flt(doc.per_billed, 2) == 100 && doc.status !== "Closed") {
+ } else if (flt(doc.per_received, 2) >= 100 && flt(doc.per_billed, 2) == 100 && doc.status !== "Closed") {
return [__("Completed"), "green", "per_received,=,100|per_billed,=,100|status,!=,Closed"];
}
},
diff --git a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
index 7016853..8435bbb 100644
--- a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
+++ b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
@@ -1,404 +1,134 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2013-02-22 01:27:42",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "editable_grid": 1,
+ "creation": "2013-02-22 01:27:42",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "field_order": [
+ "main_item_code",
+ "rm_item_code",
+ "required_qty",
+ "supplied_qty",
+ "rate",
+ "amount",
+ "column_break_6",
+ "bom_detail_no",
+ "reference_name",
+ "conversion_factor",
+ "stock_uom",
+ "reserve_warehouse"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fieldname": "main_item_code",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Item Code",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "main_item_code",
- "oldfieldtype": "Data",
- "options": "Item",
- "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
- },
+ "columns": 2,
+ "fieldname": "main_item_code",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Item Code",
+ "oldfieldname": "main_item_code",
+ "oldfieldtype": "Data",
+ "options": "Item",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fieldname": "rm_item_code",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Raw Material Item Code",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "rm_item_code",
- "oldfieldtype": "Data",
- "options": "Item",
- "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
- },
+ "columns": 2,
+ "fieldname": "rm_item_code",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Raw Material Item Code",
+ "oldfieldname": "rm_item_code",
+ "oldfieldtype": "Data",
+ "options": "Item",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fieldname": "required_qty",
- "fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Supplied Qty",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "required_qty",
- "oldfieldtype": "Currency",
- "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
- },
+ "columns": 2,
+ "fieldname": "required_qty",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Required Qty",
+ "oldfieldname": "required_qty",
+ "oldfieldtype": "Currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fieldname": "rate",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Rate",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "rate",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "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
- },
+ "columns": 2,
+ "fieldname": "rate",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Rate",
+ "oldfieldname": "rate",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amount",
- "fieldtype": "Currency",
- "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": "Amount",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "amount",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "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
- },
+ "fieldname": "amount",
+ "fieldtype": "Currency",
+ "label": "Amount",
+ "oldfieldname": "amount",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_6",
- "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
- },
+ "fieldname": "column_break_6",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "bom_detail_no",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "BOM Detail No",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "bom_detail_no",
- "oldfieldtype": "Data",
- "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
- },
+ "fieldname": "bom_detail_no",
+ "fieldtype": "Data",
+ "label": "BOM Detail No",
+ "oldfieldname": "bom_detail_no",
+ "oldfieldtype": "Data",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "reference_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Reference Name",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "reference_name",
- "oldfieldtype": "Data",
- "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
- },
+ "fieldname": "reference_name",
+ "fieldtype": "Data",
+ "label": "Reference Name",
+ "oldfieldname": "reference_name",
+ "oldfieldtype": "Data",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "conversion_factor",
- "fieldtype": "Float",
- "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": "Conversion Factor",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "conversion_factor",
- "oldfieldtype": "Currency",
- "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
- },
+ "fieldname": "conversion_factor",
+ "fieldtype": "Float",
+ "hidden": 1,
+ "label": "Conversion Factor",
+ "oldfieldname": "conversion_factor",
+ "oldfieldtype": "Currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "stock_uom",
- "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",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "stock_uom",
- "oldfieldtype": "Data",
- "options": "UOM",
- "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
- },
+ "fieldname": "stock_uom",
+ "fieldtype": "Link",
+ "label": "Stock Uom",
+ "oldfieldname": "stock_uom",
+ "oldfieldtype": "Data",
+ "options": "UOM",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fieldname": "reserve_warehouse",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Reserve Warehouse",
- "length": 0,
- "no_copy": 0,
- "options": "Warehouse",
- "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
+ "columns": 2,
+ "fieldname": "reserve_warehouse",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Reserve Warehouse",
+ "options": "Warehouse"
+ },
+ {
+ "fieldname": "supplied_qty",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Supplied Qty",
+ "read_only": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 1,
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2019-01-07 16:51:58.016007",
- "modified_by": "Administrator",
- "module": "Buying",
- "name": "Purchase Order Item Supplied",
- "owner": "dhanalekshmi@webnotestech.com",
- "permissions": [],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "hide_toolbar": 1,
+ "idx": 1,
+ "istable": 1,
+ "modified": "2019-08-20 13:37:32.702068",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Purchase Order Item Supplied",
+ "owner": "dhanalekshmi@webnotestech.com",
+ "permissions": []
}
\ No newline at end of file
diff --git a/erpnext/change_log/v12/v12_0_0.md b/erpnext/change_log/v12/v12_0_0.md
new file mode 100644
index 0000000..c2f33a8
--- /dev/null
+++ b/erpnext/change_log/v12/v12_0_0.md
@@ -0,0 +1,41 @@
+# Version 12 Release Notes
+
+### Accounting
+1. [Accounting Dimensions](https://erpnext.com/docs/user/manual/en/accounts/accounting-dimensions)
+1. [Chart of Accounts Importer](https://erpnext.com/docs/user/manual/en/setting-up/chart-of-accounts-importer)
+1. [Invoice Discounting](https://erpnext.com/docs/user/manual/en/accounts/invoice_discounting)
+1. [Tally Migrator](https://github.com/frappe/erpnext/pull/17405)
+
+### Stock
+1. [Serialized & Batched Item Reconciliation](https://erpnext.com/docs/user/manual/en/setting-up/stock-reconciliation#12-for-serialized-items)
+1. [Auto Fetch Serialized Items](https://erpnext.com/version-12/release-notes/features#new-upload-dialog)
+1. [Item Tax Templates](https://erpnext.com/docs/user/manual/en/accounts/item-tax-template)
+
+### HR
+1. [Auto Attendance](https://erpnext.com/docs/user/manual/en/human-resources/auto-attendance)
+1. [Employee Skill Map](https://erpnext.com/docs/user/manual/en/human-resources/employee_skill_map)
+1. [Encrypted Salary Slips](https://erpnext.com/docs/user/manual/en/human-resources/hr-settings#24-encrypt-salary-slips-in-emails)
+1. [Leave Ledger](https://erpnext.com/docs/user/manual/en/human-resources/leave-ledger-entry)
+1. [Staffing Plan](https://erpnext.com/docs/user/manual/en/human-resources/staffing-plan)
+
+### CRM
+1. [Promotional Scheme](https://erpnext.com/docs/user/manual/en/accounts/promotional-schemes)
+1. [SLA](https://erpnext.com/docs/user/manual/en/support/service-level-agreement)
+1. [Exotel Call Integration](https://erpnext.com/docs/user/manual/en/erpnext_integration/exotel_integration)
+1. [Email Campaign](https://erpnext.com/docs/user/manual/en/CRM/email-campaign)
+
+### Domain Specific Features
+1. [Learning Management System](https://erpnext.com/docs/user/manual/en/education/setting-up-lms)
+1. [Quality Management System](https://erpnext.com/docs/user/manual/en/quality-management)
+1. [Production Planning Enhancements](https://erpnext.com/docs/user/manual/en/manufacturing/production-plan/planning-for-material-requests)
+1. [Project Template](https://erpnext.com/docs/user/manual/en/projects/project-template)
+
+### New Reports
+1. [Bank Remittance](https://erpnext.com/docs/user/manual/en/human-resources/human-resources-reports#bank-remittance-report)
+1. [BOM Explorer](https://erpnext.com/docs/user/manual/en/stock/articles/bom_explorer)
+1. [Billing Summary Report](https://erpnext.com/docs/user/manual/en/projects/reports/billing_summary_reports)
+1. [Procurement Tracker Report](docs/user/manual/en/buying/articles/procurement-tracker-report)
+1. [Loan Repayment](https://erpnext.com/docs/user/manual/en/human-resources/human-resources-reports#loan-repayment-report)
+1. [GSTR-3B](https://erpnext.com/docs/user/manual/en/regional/india/gst-3b-report)
+1. [Sales Partner](https://erpnext.com/docs/user/manual/en/selling/sales-partner#sales-partner-reports)
+1. [Sales Partner Target Variance based on Item Group](https://erpnext.com/docs/user/manual/en/selling/sales-partner#sales-partner-target-variance-based-on-item-group)
diff --git a/erpnext/change_log/v12/v12_1_0.md b/erpnext/change_log/v12/v12_1_0.md
new file mode 100644
index 0000000..aed09c7
--- /dev/null
+++ b/erpnext/change_log/v12/v12_1_0.md
@@ -0,0 +1,6 @@
+# Version 12.1.0 Release Notes
+
+### Stock
+
+1. [Pick List](https://erpnext.com/docs/user/manual/en/stock/pick-list)
+2. [Refactored Accounts Receivable Reports](https://erpnext.com/docs/user/manual/en/accounts/accounting-reports#2-accounting-statements)
diff --git a/erpnext/communication/doctype/call_log/call_log.py b/erpnext/communication/doctype/call_log/call_log.py
index c9fdfbe..5343bef 100644
--- a/erpnext/communication/doctype/call_log/call_log.py
+++ b/erpnext/communication/doctype/call_log/call_log.py
@@ -6,15 +6,13 @@
import frappe
from frappe import _
from frappe.model.document import Document
-from erpnext.crm.doctype.utils import get_scheduled_employees_for_popup
+from erpnext.crm.doctype.utils import get_scheduled_employees_for_popup, strip_number
from frappe.contacts.doctype.contact.contact import get_contact_with_phone_number
from erpnext.crm.doctype.lead.lead import get_lead_with_phone_number
class CallLog(Document):
def before_insert(self):
- # strip 0 from the start of the number for proper number comparisions
- # eg. 07888383332 should match with 7888383332
- number = self.get('from').lstrip('0')
+ number = strip_number(self.get('from'))
self.contact = get_contact_with_phone_number(number)
self.lead = get_lead_with_phone_number(number)
@@ -30,7 +28,7 @@
self.trigger_call_popup()
def trigger_call_popup(self):
- scheduled_employees = get_scheduled_employees_for_popup(self.to)
+ scheduled_employees = get_scheduled_employees_for_popup(self.medium)
employee_emails = get_employees_with_number(self.to)
# check if employees with matched number are scheduled to receive popup
@@ -48,13 +46,14 @@
doc.add_comment('Comment', frappe.bold(_('Call Summary')) + '<br><br>' + summary)
def get_employees_with_number(number):
+ number = strip_number(number)
if not number: return []
employee_emails = frappe.cache().hget('employees_with_number', number)
if employee_emails: return employee_emails
employees = frappe.get_all('Employee', filters={
- 'cell_number': ['like', '%{}'.format(number.lstrip('0'))],
+ 'cell_number': ['like', '%{}%'.format(number)],
'user_id': ['!=', '']
}, fields=['user_id'])
@@ -64,23 +63,33 @@
return employee
def set_caller_information(doc, state):
- '''Called from hoooks on creation of Lead or Contact'''
+ '''Called from hooks on creation of Lead or Contact'''
if doc.doctype not in ['Lead', 'Contact']: return
numbers = [doc.get('phone'), doc.get('mobile_no')]
- for_doc = doc.doctype.lower()
+ # contact for Contact and lead for Lead
+ fieldname = doc.doctype.lower()
+
+ # contact_name or lead_name
+ display_name_field = '{}_name'.format(fieldname)
+
+ # Contact now has all the nos saved in child table
+ if doc.doctype == 'Contact':
+ numbers = [d.phone for d in doc.phone_nos]
for number in numbers:
+ number = strip_number(number)
if not number: continue
- print(number)
+
filters = frappe._dict({
- 'from': ['like', '%{}'.format(number.lstrip('0'))],
- for_doc: ''
+ 'from': ['like', '%{}'.format(number)],
+ fieldname: ''
})
logs = frappe.get_all('Call Log', filters=filters)
for log in logs:
- call_log = frappe.get_doc('Call Log', log.name)
- call_log.set(for_doc, doc.name)
- call_log.save(ignore_permissions=True)
+ frappe.db.set_value('Call Log', log.name, {
+ fieldname: doc.name,
+ display_name_field: doc.get_title()
+ }, update_modified=False)
diff --git a/erpnext/config/buying.py b/erpnext/config/buying.py
index f5d8da7..6f5ab32 100644
--- a/erpnext/config/buying.py
+++ b/erpnext/config/buying.py
@@ -16,6 +16,12 @@
},
{
"type": "doctype",
+ "name": "Purchase Invoice",
+ "onboard": 1,
+ "dependencies": ["Item", "Supplier"]
+ },
+ {
+ "type": "doctype",
"name": "Material Request",
"onboard": 1,
"dependencies": ["Item"],
diff --git a/erpnext/config/crm.py b/erpnext/config/crm.py
index 70784f3..eba6c7a 100644
--- a/erpnext/config/crm.py
+++ b/erpnext/config/crm.py
@@ -41,6 +41,11 @@
"name": "Lead Source",
"description": _("Track Leads by Lead Source.")
},
+ {
+ "type": "doctype",
+ "name": "Contract",
+ "description": _("Helps you keep tracks of Contracts based on Supplier, Customer and Employee"),
+ },
]
},
{
diff --git a/erpnext/config/hr.py b/erpnext/config/hr.py
index 0d05cb1..4e5e903 100644
--- a/erpnext/config/hr.py
+++ b/erpnext/config/hr.py
@@ -134,6 +134,12 @@
"name": "Employee Leave Balance",
"doctype": "Leave Application"
},
+ {
+ "type": "report",
+ "is_query_report": True,
+ "name": "Leave Ledger Entry",
+ "doctype": "Leave Ledger Entry"
+ },
]
},
{
@@ -162,6 +168,10 @@
},
{
"type": "doctype",
+ "name": "Payroll Period",
+ },
+ {
+ "type": "doctype",
"name": "Salary Component",
},
{
diff --git a/erpnext/config/integrations.py b/erpnext/config/integrations.py
index 52c9ab8..f8b3257 100644
--- a/erpnext/config/integrations.py
+++ b/erpnext/config/integrations.py
@@ -40,6 +40,11 @@
"type": "doctype",
"name": "Plaid Settings",
"description": _("Connect your bank accounts to ERPNext"),
+ },
+ {
+ "type": "doctype",
+ "name": "Exotel Settings",
+ "description": _("Connect your Exotel Account to ERPNext and track call logs"),
}
]
}
diff --git a/erpnext/config/manufacturing.py b/erpnext/config/manufacturing.py
index c79c5b8..2c18eeb 100644
--- a/erpnext/config/manufacturing.py
+++ b/erpnext/config/manufacturing.py
@@ -94,6 +94,13 @@
"name": "BOM Update Tool",
"description": _("Replace BOM and update latest price in all BOMs"),
},
+ {
+ "type": "page",
+ "label": _("BOM Comparison Tool"),
+ "name": "bom-comparison-tool",
+ "description": _("Compare BOMs for changes in Raw Materials and Operations"),
+ "data_doctype": "BOM"
+ },
]
},
{
diff --git a/erpnext/config/selling.py b/erpnext/config/selling.py
index 844710d..928bd5f 100644
--- a/erpnext/config/selling.py
+++ b/erpnext/config/selling.py
@@ -309,12 +309,6 @@
"is_query_report": True,
"name": "Sales Partners Commission",
"doctype": "Customer"
- },
- {
- "type": "report",
- "is_query_report": True,
- "name": "Sales Partners Commission",
- "doctype": "Customer"
}
]
},
diff --git a/erpnext/config/stock.py b/erpnext/config/stock.py
index 7d66df2..441a3ab 100644
--- a/erpnext/config/stock.py
+++ b/erpnext/config/stock.py
@@ -32,6 +32,12 @@
},
{
"type": "doctype",
+ "name": "Pick List",
+ "onboard": 1,
+ "dependencies": ["Item"],
+ },
+ {
+ "type": "doctype",
"name": "Delivery Trip"
},
]
@@ -329,5 +335,5 @@
}
]
},
-
+
]
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 14bf9d5..37548ea 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -89,7 +89,7 @@
self.validate_currency()
if self.doctype == 'Purchase Invoice':
- self.validate_paid_amount()
+ self.calculate_paid_amount()
if self.doctype in ['Purchase Invoice', 'Sales Invoice']:
pos_check_field = "is_pos" if self.doctype=="Sales Invoice" else "is_paid"
@@ -135,22 +135,23 @@
else:
df.set("print_hide", 1)
- def validate_paid_amount(self):
+ def calculate_paid_amount(self):
if hasattr(self, "is_pos") or hasattr(self, "is_paid"):
is_paid = self.get("is_pos") or self.get("is_paid")
- if cint(is_paid) == 1:
- if flt(self.paid_amount) == 0 and flt(self.outstanding_amount) > 0:
- if self.cash_bank_account:
- self.paid_amount = flt(flt(self.outstanding_amount), self.precision("paid_amount"))
- self.base_paid_amount = flt(self.paid_amount * self.conversion_rate,
- self.precision("base_paid_amount"))
- else:
- # show message that the amount is not paid
- self.paid_amount = 0
- frappe.throw(
- _("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
- else:
- frappe.db.set(self, 'paid_amount', 0)
+
+ if is_paid:
+ if not self.cash_bank_account:
+ # show message that the amount is not paid
+ frappe.throw(_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
+
+ if cint(self.is_return) and self.grand_total > self.paid_amount:
+ self.paid_amount = flt(flt(self.grand_total), self.precision("paid_amount"))
+
+ elif not flt(self.paid_amount) and flt(self.outstanding_amount) > 0:
+ self.paid_amount = flt(flt(self.outstanding_amount), self.precision("paid_amount"))
+
+ self.base_paid_amount = flt(self.paid_amount * self.conversion_rate,
+ self.precision("base_paid_amount"))
def set_missing_values(self, for_validate=False):
if frappe.flags.in_test:
@@ -263,7 +264,7 @@
if self.get("is_subcontracted"):
args["is_subcontracted"] = self.is_subcontracted
- ret = get_item_details(args, self)
+ ret = get_item_details(args, self, overwrite_warehouse=False)
for fieldname, value in ret.items():
if item.meta.get_field(fieldname) and value is not None:
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 588f74d..084f84b 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -337,7 +337,7 @@
if self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
rm.consumed_qty = required_qty
rm.description = bom_item.description
- if item.batch_no and not rm.batch_no:
+ if item.batch_no and frappe.db.get_value("Item", rm.rm_item_code, "has_batch_no") and not rm.batch_no:
rm.batch_no = item.batch_no
# get raw materials rate
@@ -727,7 +727,7 @@
where
t2.parent = t1.name and t1.item = %s
and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
- and t2.item_code = t3.name and t3.is_stock_item = 1""".format(doctype),
+ and t2.item_code = t3.name""".format(doctype),
(item_code, bom), as_dict=1)
if not bom_items:
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 57c063a..19ec053 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -371,7 +371,7 @@
return frappe.db.sql("""select tabAccount.name from `tabAccount`
where (tabAccount.report_type = "Profit and Loss"
- or tabAccount.account_type in ("Expense Account", "Fixed Asset", "Temporary", "Asset Received But Not Billed"))
+ or tabAccount.account_type in ("Expense Account", "Fixed Asset", "Temporary", "Asset Received But Not Billed", "Capital Work in Progress"))
and tabAccount.is_group=0
and tabAccount.docstatus!=2
and tabAccount.{key} LIKE %(txt)s
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index 2fddcdf..8595292 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -18,34 +18,31 @@
validate_returned_items(doc)
def validate_return_against(doc):
- filters = {"doctype": doc.doctype, "docstatus": 1, "company": doc.company}
- if doc.meta.get_field("customer") and doc.customer:
- filters["customer"] = doc.customer
- elif doc.meta.get_field("supplier") and doc.supplier:
- filters["supplier"] = doc.supplier
-
- if not frappe.db.exists(filters):
+ if not frappe.db.exists(doc.doctype, doc.return_against):
frappe.throw(_("Invalid {0}: {1}")
.format(doc.meta.get_label("return_against"), doc.return_against))
else:
ref_doc = frappe.get_doc(doc.doctype, doc.return_against)
- # validate posting date time
- return_posting_datetime = "%s %s" % (doc.posting_date, doc.get("posting_time") or "00:00:00")
- ref_posting_datetime = "%s %s" % (ref_doc.posting_date, ref_doc.get("posting_time") or "00:00:00")
+ party_type = "customer" if doc.doctype in ("Sales Invoice", "Delivery Note") else "supplier"
- if get_datetime(return_posting_datetime) < get_datetime(ref_posting_datetime):
- frappe.throw(_("Posting timestamp must be after {0}").format(format_datetime(ref_posting_datetime)))
+ if ref_doc.company == doc.company and ref_doc.get(party_type) == doc.get(party_type) and ref_doc.docstatus == 1:
+ # validate posting date time
+ return_posting_datetime = "%s %s" % (doc.posting_date, doc.get("posting_time") or "00:00:00")
+ ref_posting_datetime = "%s %s" % (ref_doc.posting_date, ref_doc.get("posting_time") or "00:00:00")
- # validate same exchange rate
- if doc.conversion_rate != ref_doc.conversion_rate:
- frappe.throw(_("Exchange Rate must be same as {0} {1} ({2})")
- .format(doc.doctype, doc.return_against, ref_doc.conversion_rate))
+ if get_datetime(return_posting_datetime) < get_datetime(ref_posting_datetime):
+ frappe.throw(_("Posting timestamp must be after {0}").format(format_datetime(ref_posting_datetime)))
- # validate update stock
- if doc.doctype == "Sales Invoice" and doc.update_stock and not ref_doc.update_stock:
- frappe.throw(_("'Update Stock' can not be checked because items are not delivered via {0}")
- .format(doc.return_against))
+ # validate same exchange rate
+ if doc.conversion_rate != ref_doc.conversion_rate:
+ frappe.throw(_("Exchange Rate must be same as {0} {1} ({2})")
+ .format(doc.doctype, doc.return_against, ref_doc.conversion_rate))
+
+ # validate update stock
+ if doc.doctype == "Sales Invoice" and doc.update_stock and not ref_doc.update_stock:
+ frappe.throw(_("'Update Stock' can not be checked because items are not delivered via {0}")
+ .format(doc.return_against))
def validate_returned_items(doc):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
@@ -249,6 +246,8 @@
elif doc.doctype == 'Purchase Invoice':
doc.paid_amount = -1 * source.paid_amount
doc.base_paid_amount = -1 * source.base_paid_amount
+ doc.payment_terms_template = ''
+ doc.payment_schedule = []
if doc.get("is_return") and hasattr(doc, "packed_items"):
for d in doc.get("packed_items"):
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 2cbe596..9dbd5be 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -45,6 +45,7 @@
self.set_gross_profit()
set_default_income_account_for_item(self)
self.set_customer_address()
+ self.validate_for_duplicate_items()
def set_missing_values(self, for_validate=False):
@@ -381,6 +382,34 @@
if self.get(address_field):
self.set(address_display_field, get_address_display(self.get(address_field)))
+ def validate_for_duplicate_items(self):
+ check_list, chk_dupl_itm = [], []
+ if cint(frappe.db.get_single_value("Selling Settings", "allow_multiple_items")):
+ return
+
+ for d in self.get('items'):
+ if self.doctype == "Sales Invoice":
+ e = [d.item_code, d.description, d.warehouse, d.sales_order or d.delivery_note, d.batch_no or '']
+ f = [d.item_code, d.description, d.sales_order or d.delivery_note]
+ elif self.doctype == "Delivery Note":
+ e = [d.item_code, d.description, d.warehouse, d.against_sales_order or d.against_sales_invoice, d.batch_no or '']
+ f = [d.item_code, d.description, d.against_sales_order or d.against_sales_invoice]
+ elif self.doctype in ["Sales Order", "Quotation"]:
+ e = [d.item_code, d.description, d.warehouse, '']
+ f = [d.item_code, d.description]
+
+ if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1:
+ if e in check_list:
+ frappe.throw(_("Note: Item {0} entered multiple times").format(d.item_code))
+ else:
+ check_list.append(e)
+ else:
+ if f in chk_dupl_itm:
+ frappe.throw(_("Note: Item {0} entered multiple times").format(d.item_code))
+ else:
+ chk_dupl_itm.append(f)
+
+
def validate_items(self):
# validate items to see if they have is_sales_item enabled
from erpnext.controllers.buying_controller import validate_item_type
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index b2057ca..64d49b4 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -57,9 +57,9 @@
"Purchase Order": [
["Draft", None],
["To Receive and Bill", "eval:self.per_received < 100 and self.per_billed < 100 and self.docstatus == 1"],
- ["To Bill", "eval:self.per_received == 100 and self.per_billed < 100 and self.docstatus == 1"],
+ ["To Bill", "eval:self.per_received >= 100 and self.per_billed < 100 and self.docstatus == 1"],
["To Receive", "eval:self.per_received < 100 and self.per_billed == 100 and self.docstatus == 1"],
- ["Completed", "eval:self.per_received == 100 and self.per_billed == 100 and self.docstatus == 1"],
+ ["Completed", "eval:self.per_received >= 100 and self.per_billed == 100 and self.docstatus == 1"],
["Delivered", "eval:self.status=='Delivered'"],
["Cancelled", "eval:self.docstatus==2"],
["On Hold", "eval:self.status=='On Hold'"],
diff --git a/erpnext/controllers/trends.py b/erpnext/controllers/trends.py
index 28a8fdd..da44325 100644
--- a/erpnext/controllers/trends.py
+++ b/erpnext/controllers/trends.py
@@ -39,7 +39,6 @@
frappe.throw(_("'Based On' and 'Group By' can not be same"))
def get_data(filters, conditions):
-
data = []
inc, cond= '',''
query_details = conditions["based_on_select"] + conditions["period_wise_select"]
@@ -47,13 +46,17 @@
posting_date = 't1.transaction_date'
if conditions.get('trans') in ['Sales Invoice', 'Purchase Invoice', 'Purchase Receipt', 'Delivery Note']:
posting_date = 't1.posting_date'
+ if filters.period_based_on:
+ posting_date = 't1.'+filters.period_based_on
if conditions["based_on_select"] in ["t1.project,", "t2.project,"]:
cond = ' and '+ conditions["based_on_select"][:-1] +' IS Not NULL'
-
if conditions.get('trans') in ['Sales Order', 'Purchase Order']:
cond += " and t1.status != 'Closed'"
+ if conditions.get('trans') == 'Quotation' and filters.get("group_by") == 'Customer':
+ cond += " and t1.quotation_to = 'Customer'"
+
year_start_date, year_end_date = frappe.db.get_value("Fiscal Year",
filters.get('fiscal_year'), ["year_start_date", "year_end_date"])
@@ -64,7 +67,7 @@
if filters.get("group_by") == 'Item':
sel_col = 't2.item_code'
elif filters.get("group_by") == 'Customer':
- sel_col = 't1.customer'
+ sel_col = 't1.party_name' if conditions.get('trans') == 'Quotation' else 't1.customer'
elif filters.get("group_by") == 'Supplier':
sel_col = 't1.supplier'
@@ -225,7 +228,7 @@
elif based_on == "Customer":
based_on_details["based_on_cols"] = ["Customer:Link/Customer:120", "Territory:Link/Territory:120"]
based_on_details["based_on_select"] = "t1.customer_name, t1.territory, "
- based_on_details["based_on_group_by"] = 't1.customer'
+ based_on_details["based_on_group_by"] = 't1.party_name' if trans == 'Quotation' else 't1.customer'
based_on_details["addl_tables"] = ''
elif based_on == "Customer Group":
diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py
index ed48fd1..0738fd5 100644
--- a/erpnext/controllers/website_list_for_contact.py
+++ b/erpnext/controllers/website_list_for_contact.py
@@ -21,42 +21,45 @@
def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_page_length=20, order_by="modified"):
user = frappe.session.user
- key = None
+ ignore_permissions = False
if not filters: filters = []
if doctype == 'Supplier Quotation':
- filters.append((doctype, "docstatus", "<", 2))
+ filters.append((doctype, 'docstatus', '<', 2))
else:
- filters.append((doctype, "docstatus", "=", 1))
+ filters.append((doctype, 'docstatus', '=', 1))
- if (user != "Guest" and is_website_user()) or doctype == 'Request for Quotation':
+ if (user != 'Guest' and is_website_user()) or doctype == 'Request for Quotation':
parties_doctype = 'Request for Quotation Supplier' if doctype == 'Request for Quotation' else doctype
# find party for this contact
customers, suppliers = get_customers_suppliers(parties_doctype, user)
- if not customers and not suppliers: return []
-
- key, parties = get_party_details(customers, suppliers)
-
- if doctype == 'Request for Quotation':
- return rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length)
-
- filters.append((doctype, key, "in", parties))
-
- if key:
- return post_process(doctype, get_list_for_transactions(doctype, txt,
- filters=filters, fields="name",limit_start=limit_start,
- limit_page_length=limit_page_length,ignore_permissions=True,
- order_by="modified desc"))
+ if customers:
+ if doctype == 'Quotation':
+ filters.append(('quotation_to', '=', 'Customer'))
+ filters.append(('party_name', 'in', customers))
+ else:
+ filters.append(('customer', 'in', customers))
+ elif suppliers:
+ filters.append(('supplier', 'in', suppliers))
else:
return []
- return post_process(doctype, get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length,
- fields="name", order_by="modified desc"))
+ if doctype == 'Request for Quotation':
+ parties = customers or suppliers
+ return rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length)
+
+ # Since customers and supplier do not have direct access to internal doctypes
+ ignore_permissions = True
+
+ transactions = get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length,
+ fields='name', ignore_permissions=ignore_permissions, order_by='modified desc')
+
+ return post_process(doctype, transactions)
def get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length=20,
- ignore_permissions=False,fields=None, order_by=None):
+ ignore_permissions=False, fields=None, order_by=None):
""" Get List of transactions like Invoices, Orders """
from frappe.www.list import get_list
meta = frappe.get_meta(doctype)
@@ -77,22 +80,12 @@
if or_filters:
for r in frappe.get_list(doctype, fields=fields,filters=filters, or_filters=or_filters,
- limit_start=limit_start, limit_page_length=limit_page_length,
+ limit_start=limit_start, limit_page_length=limit_page_length,
ignore_permissions=ignore_permissions, order_by=order_by):
data.append(r)
return data
-def get_party_details(customers, suppliers):
- if customers:
- key, parties = "customer", customers
- elif suppliers:
- key, parties = "supplier", suppliers
- else:
- key, parties = "customer", []
-
- return key, parties
-
def rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length):
data = frappe.db.sql("""select distinct parent as name, supplier from `tab{doctype}`
where supplier = '{supplier}' and docstatus=1 order by modified desc limit {start}, {len}""".
@@ -130,38 +123,56 @@
suppliers = []
meta = frappe.get_meta(doctype)
+ customer_field_name = get_customer_field_name(doctype)
+
+ has_customer_field = meta.has_field(customer_field_name)
+ has_supplier_field = meta.has_field('supplier')
+
if has_common(["Supplier", "Customer"], frappe.get_roles(user)):
contacts = frappe.db.sql("""
- select
+ select
`tabContact`.email_id,
`tabDynamic Link`.link_doctype,
`tabDynamic Link`.link_name
- from
+ from
`tabContact`, `tabDynamic Link`
where
`tabContact`.name=`tabDynamic Link`.parent and `tabContact`.email_id =%s
""", user, as_dict=1)
- customers = [c.link_name for c in contacts if c.link_doctype == 'Customer'] \
- if meta.get_field("customer") else None
- suppliers = [c.link_name for c in contacts if c.link_doctype == 'Supplier'] \
- if meta.get_field("supplier") else None
+ customers = [c.link_name for c in contacts if c.link_doctype == 'Customer']
+ suppliers = [c.link_name for c in contacts if c.link_doctype == 'Supplier']
elif frappe.has_permission(doctype, 'read', user=user):
- customers = [customer.name for customer in frappe.get_list("Customer")] \
- if meta.get_field("customer") else None
- suppliers = [supplier.name for supplier in frappe.get_list("Customer")] \
- if meta.get_field("supplier") else None
+ customer_list = frappe.get_list("Customer")
+ customers = suppliers = [customer.name for customer in customer_list]
- return customers, suppliers
+ return customers if has_customer_field else None, \
+ suppliers if has_supplier_field else None
def has_website_permission(doc, ptype, user, verbose=False):
doctype = doc.doctype
customers, suppliers = get_customers_suppliers(doctype, user)
if customers:
- return frappe.get_all(doctype, filters=[(doctype, "customer", "in", customers),
- (doctype, "name", "=", doc.name)]) and True or False
+ return frappe.db.exists(doctype, get_customer_filter(doc, customers))
elif suppliers:
fieldname = 'suppliers' if doctype == 'Request for Quotation' else 'supplier'
- return frappe.get_all(doctype, filters=[(doctype, fieldname, "in", suppliers),
- (doctype, "name", "=", doc.name)]) and True or False
+ return frappe.db.exists(doctype, filters={
+ 'name': doc.name,
+ fieldname: ["in", suppliers]
+ })
else:
return False
+
+def get_customer_filter(doc, customers):
+ doctype = doc.doctype
+ filters = frappe._dict()
+ filters.name = doc.name
+ filters[get_customer_field_name(doctype)] = ['in', customers]
+ if doctype == 'Quotation':
+ filters.quotation_to = 'Customer'
+ return filters
+
+def get_customer_field_name(doctype):
+ if doctype == 'Quotation':
+ return 'party_name'
+ else:
+ return 'customer'
\ No newline at end of file
diff --git a/erpnext/crm/doctype/contract/contract.py b/erpnext/crm/doctype/contract/contract.py
index 64cc97b..18444cc 100644
--- a/erpnext/crm/doctype/contract/contract.py
+++ b/erpnext/crm/doctype/contract/contract.py
@@ -88,7 +88,7 @@
end_date = getdate(end_date)
now_date = getdate(nowdate())
- return "Active" if start_date < now_date < end_date else "Inactive"
+ return "Active" if start_date <= now_date <= end_date else "Inactive"
def update_status_for_contracts():
diff --git a/erpnext/crm/doctype/opportunity/test_opportunity.py b/erpnext/crm/doctype/opportunity/test_opportunity.py
index 1a9f66a..8f61edf 100644
--- a/erpnext/crm/doctype/opportunity/test_opportunity.py
+++ b/erpnext/crm/doctype/opportunity/test_opportunity.py
@@ -45,15 +45,16 @@
# create new customer and create new contact against 'new.opportunity@example.com'
customer = make_customer(opp_doc.party_name).insert(ignore_permissions=True)
- frappe.get_doc({
+ contact = frappe.get_doc({
"doctype": "Contact",
- "email_id": new_lead_email_id,
"first_name": "_Test Opportunity Customer",
"links": [{
"link_doctype": "Customer",
"link_name": customer.name
}]
- }).insert(ignore_permissions=True)
+ })
+ contact.add_email(new_lead_email_id)
+ contact.insert(ignore_permissions=True)
opp_doc = frappe.get_doc(args).insert(ignore_permissions=True)
self.assertTrue(opp_doc.party_name)
diff --git a/erpnext/crm/doctype/utils.py b/erpnext/crm/doctype/utils.py
index 5553276..535458a 100644
--- a/erpnext/crm/doctype/utils.py
+++ b/erpnext/crm/doctype/utils.py
@@ -54,6 +54,8 @@
def get_scheduled_employees_for_popup(communication_medium):
+ if not communication_medium: return []
+
now_time = frappe.utils.nowtime()
weekday = frappe.utils.get_weekday()
@@ -73,3 +75,10 @@
employee_emails = set([employee.user_id for employee in employees])
return employee_emails
+
+def strip_number(number):
+ if not number: return
+ # strip 0 from the start of the number for proper number comparisions
+ # eg. 07888383332 should match with 7888383332
+ number = number.lstrip('0')
+ return number
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_activity/course_activity.json b/erpnext/education/doctype/course_activity/course_activity.json
index 99ae9ae..3e23c90 100644
--- a/erpnext/education/doctype/course_activity/course_activity.json
+++ b/erpnext/education/doctype/course_activity/course_activity.json
@@ -30,7 +30,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Enrollment",
+ "label": "Course Enrollment",
"length": 0,
"no_copy": 0,
"options": "Course Enrollment",
@@ -298,4 +298,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
-}
\ No newline at end of file
+}
diff --git a/erpnext/education/doctype/program_course/program_course.json b/erpnext/education/doctype/program_course/program_course.json
index 3465040..a24e88a 100644
--- a/erpnext/education/doctype/program_course/program_course.json
+++ b/erpnext/education/doctype/program_course/program_course.json
@@ -5,6 +5,7 @@
"engine": "InnoDB",
"field_order": [
"course",
+ "course_name",
"required"
],
"fields": [
@@ -17,6 +18,14 @@
"options": "Course",
"reqd": 1
},
+ {
+ "fieldname": "course_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Course Name",
+ "fetch_from": "course.course_name",
+ "read_only":1
+ },
{
"default": "0",
"fieldname": "required",
@@ -36,4 +45,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py
index da25880..705c6e4 100644
--- a/erpnext/education/doctype/student/student.py
+++ b/erpnext/education/doctype/student/student.py
@@ -54,6 +54,7 @@
'send_welcome_email': 1,
'user_type': 'Website User'
})
+ student_user.flags.ignore_permissions = True
student_user.add_roles("Student")
student_user.save()
update_password_link = student_user.reset_password()
diff --git a/erpnext/education/doctype/student_applicant/student_applicant.json b/erpnext/education/doctype/student_applicant/student_applicant.json
index 71134e0..e5d0bd3 100644
--- a/erpnext/education/doctype/student_applicant/student_applicant.json
+++ b/erpnext/education/doctype/student_applicant/student_applicant.json
@@ -705,7 +705,6 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "default": "INDIAN",
"fieldname": "nationality",
"fieldtype": "Data",
"hidden": 0,
@@ -1231,4 +1230,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
-}
\ No newline at end of file
+}
diff --git a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py
index 16933dc..c0a7359 100644
--- a/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py
+++ b/erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.py
@@ -55,7 +55,7 @@
"courses": courses,
"assessment_groups": assessment_groups,
"course_criteria": course_criteria,
- "letterhead": letterhead.content,
+ "letterhead": letterhead and letterhead.get('content', None),
"add_letterhead": doc.add_letterhead if doc.add_letterhead else 0
})
final_template = frappe.render_template(base_template_path, {"body": html, "title": "Report Card"})
@@ -89,4 +89,4 @@
attendance["Present"] = 0
return attendance
else:
- frappe.throw(_("Provide the academic year and set the starting and ending date."))
\ No newline at end of file
+ frappe.throw(_("Provide the academic year and set the starting and ending date."))
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py
index fd364e8..cc4ccc5 100755
--- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_api.py
@@ -71,7 +71,7 @@
Helper function that removes all keys from a dictionary (d),
that have an empty value.
"""
- for key in d.keys():
+ for key in list(d):
if not d[key]:
del d[key]
return d
diff --git a/erpnext/erpnext_integrations/doctype/exotel_settings/exotel_settings.py b/erpnext/erpnext_integrations/doctype/exotel_settings/exotel_settings.py
index 77de84c..6a846ef 100644
--- a/erpnext/erpnext_integrations/doctype/exotel_settings/exotel_settings.py
+++ b/erpnext/erpnext_integrations/doctype/exotel_settings/exotel_settings.py
@@ -3,7 +3,6 @@
# For license information, please see license.txt
from __future__ import unicode_literals
-# import frappe
from frappe.model.document import Document
import requests
import frappe
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py
index fbb0ebc..532e19c 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_connector.py
@@ -3,30 +3,31 @@
# For license information, please see license.txt
from __future__ import unicode_literals
-import frappe
from frappe import _
-import requests
+from frappe.utils.password import get_decrypted_password
from plaid import Client
from plaid.errors import APIError, ItemError
+import frappe
+import requests
+
class PlaidConnector():
def __init__(self, access_token=None):
- if not(frappe.conf.get("plaid_client_id") and frappe.conf.get("plaid_secret") and frappe.conf.get("plaid_public_key")):
- frappe.throw(_("Please complete your Plaid API configuration before synchronizing your account"))
+ plaid_settings = frappe.get_single("Plaid Settings")
self.config = {
- "plaid_client_id": frappe.conf.get("plaid_client_id"),
- "plaid_secret": frappe.conf.get("plaid_secret"),
- "plaid_public_key": frappe.conf.get("plaid_public_key"),
- "plaid_env": frappe.conf.get("plaid_env")
+ "plaid_client_id": plaid_settings.plaid_client_id,
+ "plaid_secret": get_decrypted_password("Plaid Settings", "Plaid Settings", 'plaid_secret'),
+ "plaid_public_key": plaid_settings.plaid_public_key,
+ "plaid_env": plaid_settings.plaid_env
}
- self.client = Client(client_id=self.config["plaid_client_id"],
- secret=self.config["plaid_secret"],
- public_key=self.config["plaid_public_key"],
- environment=self.config["plaid_env"]
- )
+ self.client = Client(client_id=self.config.get("plaid_client_id"),
+ secret=self.config.get("plaid_secret"),
+ public_key=self.config.get("plaid_public_key"),
+ environment=self.config.get("plaid_env")
+ )
self.access_token = access_token
@@ -78,4 +79,4 @@
transactions.extend(response['transactions'])
return transactions
except Exception:
- frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
\ No newline at end of file
+ frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js
index ace4fbf..0ffbb87 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.js
@@ -4,8 +4,18 @@
frappe.provide("erpnext.integrations");
frappe.ui.form.on('Plaid Settings', {
- link_new_account: function(frm) {
- new erpnext.integrations.plaidLink(frm);
+ enabled: function(frm) {
+ frm.toggle_reqd('plaid_client_id', frm.doc.enabled);
+ frm.toggle_reqd('plaid_secret', frm.doc.enabled);
+ frm.toggle_reqd('plaid_public_key', frm.doc.enabled);
+ frm.toggle_reqd('plaid_env', frm.doc.enabled);
+ },
+ refresh: function(frm) {
+ if(frm.doc.enabled) {
+ frm.add_custom_button('Link a new bank account', () => {
+ new erpnext.integrations.plaidLink(frm);
+ });
+ }
}
});
@@ -19,20 +29,10 @@
init_config() {
const me = this;
- frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.plaid_configuration')
- .then(result => {
- if (result !== "disabled") {
- if (result.plaid_env == undefined || result.plaid_public_key == undefined) {
- frappe.throw(__("Please add valid Plaid api keys in site_config.json first"));
- }
- me.plaid_env = result.plaid_env;
- me.plaid_public_key = result.plaid_public_key;
- me.client_name = result.client_name;
- me.init_plaid();
- } else {
- frappe.throw(__("Please save your document before adding a new account"));
- }
- });
+ me.plaid_env = me.frm.doc.plaid_env;
+ me.plaid_public_key = me.frm.doc.plaid_public_key;
+ me.client_name = frappe.boot.sitename;
+ me.init_plaid();
}
init_plaid() {
@@ -104,4 +104,4 @@
});
}, __("Select a company"), __("Continue"));
}
-};
\ No newline at end of file
+};
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.json b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.json
index ed51c4e..9903048 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.json
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.json
@@ -1,161 +1,96 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2018-10-25 10:02:48.656165",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "creation": "2018-10-25 10:02:48.656165",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "enabled",
+ "column_break_2",
+ "automatic_sync",
+ "section_break_4",
+ "plaid_client_id",
+ "plaid_secret",
+ "column_break_7",
+ "plaid_public_key",
+ "plaid_env"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "enabled",
- "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": "Enabled",
- "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
- },
+ "default": "0",
+ "fieldname": "enabled",
+ "fieldtype": "Check",
+ "label": "Enabled"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.enabled==1",
- "fieldname": "automatic_sync",
- "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": "Synchronize all accounts every hour",
- "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
- },
+ "default": "0",
+ "depends_on": "eval:doc.enabled==1",
+ "fieldname": "automatic_sync",
+ "fieldtype": "Check",
+ "label": "Synchronize all accounts every hour"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:(doc.enabled==1)&&(!doc.__islocal)",
- "fieldname": "link_new_account",
- "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": "Link a new bank account",
- "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
+ "depends_on": "eval:doc.enabled==1",
+ "fieldname": "plaid_client_id",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Plaid Client ID",
+ "reqd": 1
+ },
+ {
+ "depends_on": "eval:doc.enabled==1",
+ "fieldname": "plaid_secret",
+ "fieldtype": "Password",
+ "in_list_view": 1,
+ "label": "Plaid Secret",
+ "reqd": 1
+ },
+ {
+ "depends_on": "eval:doc.enabled==1",
+ "fieldname": "plaid_public_key",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Plaid Public Key",
+ "reqd": 1
+ },
+ {
+ "depends_on": "eval:doc.enabled==1",
+ "fieldname": "plaid_env",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Plaid Environment",
+ "reqd": 1
+ },
+ {
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "section_break_4",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "column_break_7",
+ "fieldtype": "Column Break"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 1,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-12-14 12:51:12.331395",
- "modified_by": "Administrator",
- "module": "ERPNext Integrations",
- "name": "Plaid Settings",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "issingle": 1,
+ "modified": "2019-08-13 17:00:06.939422",
+ "modified_by": "Administrator",
+ "module": "ERPNext Integrations",
+ "name": "Plaid Settings",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 0,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "role": "System Manager",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
index 8d31e24..4af1d74 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
@@ -16,8 +16,13 @@
@frappe.whitelist()
def plaid_configuration():
- if frappe.db.get_value("Plaid Settings", None, "enabled") == "1":
- return {"plaid_public_key": frappe.conf.get("plaid_public_key") or None, "plaid_env": frappe.conf.get("plaid_env") or None, "client_name": frappe.local.site }
+ if frappe.db.get_single_value("Plaid Settings", "enabled"):
+ plaid_settings = frappe.get_single("Plaid Settings")
+ return {
+ "plaid_public_key": plaid_settings.plaid_public_key,
+ "plaid_env": plaid_settings.plaid_env,
+ "client_name": frappe.local.site
+ }
else:
return "disabled"
diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
index 7f4b7ba..4943053 100644
--- a/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
+++ b/erpnext/erpnext_integrations/doctype/shopify_settings/shopify_settings.py
@@ -58,7 +58,7 @@
d.raise_for_status()
self.update_webhook_table(method, d.json())
except Exception as e:
- make_shopify_log(status="Warning", message=e.message, exception=False)
+ make_shopify_log(status="Warning", message=e, exception=False)
def unregister_webhooks(self):
session = get_request_session()
@@ -71,7 +71,7 @@
res.raise_for_status()
deleted_webhooks.append(d)
except Exception as e:
- frappe.log_error(message=frappe.get_traceback(), title=e.message[:140])
+ frappe.log_error(message=frappe.get_traceback(), title=e)
for d in deleted_webhooks:
self.remove(d)
diff --git a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
index ed9eae3..ad32e94 100644
--- a/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
+++ b/erpnext/healthcare/doctype/healthcare_practitioner/healthcare_practitioner.py
@@ -69,33 +69,10 @@
def get_practitioner_list(doctype, txt, searchfield, start, page_len, filters=None):
fields = ["name", "first_name", "mobile_phone"]
- match_conditions = build_match_conditions("Healthcare Practitioner")
- match_conditions = "and {}".format(match_conditions) if match_conditions else ""
- if filters:
- filter_conditions = get_filters_cond(doctype, filters, [])
- match_conditions += "{}".format(filter_conditions)
+ filters = {
+ 'name': ("like", "%%%s%%" % txt)
+ }
- return frappe.db.sql("""select %s from `tabHealthcare Practitioner` where docstatus < 2
- and (%s like %s or first_name like %s)
- and active = 1
- {match_conditions}
- order by
- case when name like %s then 0 else 1 end,
- case when first_name like %s then 0 else 1 end,
- name, first_name limit %s, %s""".format(
- match_conditions=match_conditions) %
- (
- ", ".join(fields),
- frappe.db.escape(searchfield),
- "%s", "%s", "%s", "%s", "%s", "%s"
- ),
- (
- "%%%s%%" % frappe.db.escape(txt),
- "%%%s%%" % frappe.db.escape(txt),
- "%%%s%%" % frappe.db.escape(txt),
- "%%%s%%" % frappe.db.escape(txt),
- start,
- page_len
- )
- )
+ return frappe.get_all("Healthcare Practitioner", fields = fields,
+ filters = filters, start=start, page_length=page_len, order_by="name, first_name", as_list=1)
diff --git a/erpnext/healthcare/doctype/patient/patient.py b/erpnext/healthcare/doctype/patient/patient.py
index bf15cad..e3eea96 100644
--- a/erpnext/healthcare/doctype/patient/patient.py
+++ b/erpnext/healthcare/doctype/patient/patient.py
@@ -6,7 +6,7 @@
import frappe
from frappe import _
from frappe.model.document import Document
-from frappe.utils import cint, cstr, getdate
+from frappe.utils import cint, cstr, getdate, flt
import dateutil
from frappe.model.naming import set_name_by_naming_series
from erpnext.healthcare.doctype.healthcare_settings.healthcare_settings import get_receivable_account,get_income_account,send_registration_sms
@@ -64,7 +64,7 @@
def invoice_patient_registration(self):
frappe.db.set_value("Patient", self.name, "disabled", 0)
send_registration_sms(self)
- if(frappe.get_value("Healthcare Settings", None, "registration_fee")>0):
+ if(flt(frappe.get_value("Healthcare Settings", None, "registration_fee"))>0):
company = frappe.defaults.get_user_default('company')
if not company:
company = frappe.db.get_value("Global Defaults", None, "default_company")
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index be9a4fb..7e33a14 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -283,7 +283,9 @@
"erpnext.crm.doctype.email_campaign.email_campaign.set_email_campaign_status"
],
"daily_long": [
- "erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms"
+ "erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms",
+ "erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry.process_expired_allocation",
+ "erpnext.hr.utils.generate_leave_encashment"
],
"monthly_long": [
"erpnext.accounts.deferred_revenue.convert_deferred_revenue_to_income",
diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.py b/erpnext/hr/doctype/additional_salary/additional_salary.py
index 82f2a22..8498b3d 100644
--- a/erpnext/hr/doctype/additional_salary/additional_salary.py
+++ b/erpnext/hr/doctype/additional_salary/additional_salary.py
@@ -11,7 +11,7 @@
class AdditionalSalary(Document):
def before_insert(self):
if frappe.db.exists("Additional Salary", {"employee": self.employee, "salary_component": self.salary_component,
- "amount": self.amount, "payroll_date": self.payroll_date, "company": self.company}):
+ "amount": self.amount, "payroll_date": self.payroll_date, "company": self.company, "docstatus": 1}):
frappe.throw(_("Additional Salary Component Exists."))
diff --git a/erpnext/hr/doctype/attendance/attendance.json b/erpnext/hr/doctype/attendance/attendance.json
index eb38147..bc89b36 100644
--- a/erpnext/hr/doctype/attendance/attendance.json
+++ b/erpnext/hr/doctype/attendance/attendance.json
@@ -4,6 +4,7 @@
"creation": "2013-01-10 16:34:13",
"doctype": "DocType",
"document_type": "Setup",
+ "engine": "InnoDB",
"field_order": [
"attendance_details",
"naming_series",
@@ -19,7 +20,9 @@
"department",
"shift",
"attendance_request",
- "amended_from"
+ "amended_from",
+ "late_entry",
+ "early_exit"
],
"fields": [
{
@@ -153,12 +156,24 @@
"fieldtype": "Link",
"label": "Shift",
"options": "Shift Type"
+ },
+ {
+ "default": "0",
+ "fieldname": "late_entry",
+ "fieldtype": "Check",
+ "label": "Late Entry"
+ },
+ {
+ "default": "0",
+ "fieldname": "early_exit",
+ "fieldtype": "Check",
+ "label": "Early Exit"
}
],
"icon": "fa fa-ok",
"idx": 1,
"is_submittable": 1,
- "modified": "2019-06-05 19:37:30.410071",
+ "modified": "2019-07-29 20:35:40.845422",
"modified_by": "Administrator",
"module": "HR",
"name": "Attendance",
diff --git a/erpnext/hr/doctype/employee/employee.json b/erpnext/hr/doctype/employee/employee.json
index 5202218..9291820 100644
--- a/erpnext/hr/doctype/employee/employee.json
+++ b/erpnext/hr/doctype/employee/employee.json
@@ -7,6 +7,7 @@
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
+ "engine": "InnoDB",
"field_order": [
"basic_information",
"employee",
@@ -54,6 +55,7 @@
"column_break_44",
"holiday_list",
"default_shift",
+ "leave_approver",
"salary_information",
"salary_mode",
"bank_name",
@@ -169,6 +171,8 @@
"read_only": 1
},
{
+ "fetch_from": "user_id.user_image",
+ "fetch_if_empty": 1,
"fieldname": "image",
"fieldtype": "Attach Image",
"hidden": 1,
@@ -767,12 +771,18 @@
"fieldtype": "Link",
"label": "Default Shift",
"options": "Shift Type"
+ },
+ {
+ "fieldname": "leave_approver",
+ "fieldtype": "Link",
+ "label": "Leave Approver",
+ "options": "User"
}
],
"icon": "fa fa-user",
"idx": 24,
"image_field": "image",
- "modified": "2019-06-01 16:05:55.132180",
+ "modified": "2019-09-12 14:21:12.711280",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee",
diff --git a/erpnext/hr/doctype/employee_checkin/employee_checkin.json b/erpnext/hr/doctype/employee_checkin/employee_checkin.json
index 15ec7c0..08fa4af 100644
--- a/erpnext/hr/doctype/employee_checkin/employee_checkin.json
+++ b/erpnext/hr/doctype/employee_checkin/employee_checkin.json
@@ -14,8 +14,6 @@
"device_id",
"skip_auto_attendance",
"attendance",
- "entry_grace_period_consequence",
- "exit_grace_period_consequence",
"shift_start",
"shift_end",
"shift_actual_start",
@@ -81,20 +79,6 @@
"read_only": 1
},
{
- "default": "0",
- "fieldname": "entry_grace_period_consequence",
- "fieldtype": "Check",
- "hidden": 1,
- "label": "Entry Grace Period Consequence"
- },
- {
- "default": "0",
- "fieldname": "exit_grace_period_consequence",
- "fieldtype": "Check",
- "hidden": 1,
- "label": "Exit Grace Period Consequence"
- },
- {
"fieldname": "shift_start",
"fieldtype": "Datetime",
"hidden": 1,
@@ -119,7 +103,7 @@
"label": "Shift Actual End"
}
],
- "modified": "2019-06-10 15:33:22.731697",
+ "modified": "2019-07-23 23:47:33.975263",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Checkin",
diff --git a/erpnext/hr/doctype/employee_checkin/employee_checkin.py b/erpnext/hr/doctype/employee_checkin/employee_checkin.py
index b0e15d9..8670512 100644
--- a/erpnext/hr/doctype/employee_checkin/employee_checkin.py
+++ b/erpnext/hr/doctype/employee_checkin/employee_checkin.py
@@ -72,7 +72,7 @@
return doc
-def mark_attendance_and_link_log(logs, attendance_status, attendance_date, working_hours=None, shift=None):
+def mark_attendance_and_link_log(logs, attendance_status, attendance_date, working_hours=None, late_entry=False, early_exit=False, shift=None):
"""Creates an attendance and links the attendance to the Employee Checkin.
Note: If attendance is already present for the given date, the logs are marked as skipped and no exception is thrown.
@@ -98,7 +98,9 @@
'status': attendance_status,
'working_hours': working_hours,
'company': employee_doc.company,
- 'shift': shift
+ 'shift': shift,
+ 'late_entry': late_entry,
+ 'early_exit': early_exit
}
attendance = frappe.get_doc(doc_dict).insert()
attendance.submit()
@@ -124,25 +126,36 @@
:param working_hours_calc_type: One of: 'First Check-in and Last Check-out', 'Every Valid Check-in and Check-out'
"""
total_hours = 0
+ in_time = out_time = None
if check_in_out_type == 'Alternating entries as IN and OUT during the same shift':
+ in_time = logs[0].time
+ if len(logs) >= 2:
+ out_time = logs[-1].time
if working_hours_calc_type == 'First Check-in and Last Check-out':
# assumption in this case: First log always taken as IN, Last log always taken as OUT
- total_hours = time_diff_in_hours(logs[0].time, logs[-1].time)
+ total_hours = time_diff_in_hours(in_time, logs[-1].time)
elif working_hours_calc_type == 'Every Valid Check-in and Check-out':
+ logs = logs[:]
while len(logs) >= 2:
total_hours += time_diff_in_hours(logs[0].time, logs[1].time)
del logs[:2]
elif check_in_out_type == 'Strictly based on Log Type in Employee Checkin':
if working_hours_calc_type == 'First Check-in and Last Check-out':
- first_in_log = logs[find_index_in_dict(logs, 'log_type', 'IN')]
- last_out_log = logs[len(logs)-1-find_index_in_dict(reversed(logs), 'log_type', 'OUT')]
+ first_in_log_index = find_index_in_dict(logs, 'log_type', 'IN')
+ first_in_log = logs[first_in_log_index] if first_in_log_index or first_in_log_index == 0 else None
+ last_out_log_index = find_index_in_dict(reversed(logs), 'log_type', 'OUT')
+ last_out_log = logs[len(logs)-1-last_out_log_index] if last_out_log_index or last_out_log_index == 0 else None
if first_in_log and last_out_log:
- total_hours = time_diff_in_hours(first_in_log.time, last_out_log.time)
+ in_time, out_time = first_in_log.time, last_out_log.time
+ total_hours = time_diff_in_hours(in_time, out_time)
elif working_hours_calc_type == 'Every Valid Check-in and Check-out':
in_log = out_log = None
for log in logs:
if in_log and out_log:
+ if not in_time:
+ in_time = in_log.time
+ out_time = out_log.time
total_hours += time_diff_in_hours(in_log.time, out_log.time)
in_log = out_log = None
if not in_log:
@@ -150,8 +163,9 @@
elif not out_log:
out_log = log if log.log_type == 'OUT' else None
if in_log and out_log:
+ out_time = out_log.time
total_hours += time_diff_in_hours(in_log.time, out_log.time)
- return total_hours
+ return total_hours, in_time, out_time
def time_diff_in_hours(start, end):
return round((end-start).total_seconds() / 3600, 1)
diff --git a/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py b/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py
index 424d1a3..9f12ef2 100644
--- a/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py
+++ b/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py
@@ -70,16 +70,16 @@
logs_type_2 = [frappe._dict(x) for x in logs_type_2]
working_hours = calculate_working_hours(logs_type_1,check_in_out_type[0],working_hours_calc_type[0])
- self.assertEqual(working_hours, 6.5)
+ self.assertEqual(working_hours, (6.5, logs_type_1[0].time, logs_type_1[-1].time))
working_hours = calculate_working_hours(logs_type_1,check_in_out_type[0],working_hours_calc_type[1])
- self.assertEqual(working_hours, 4.5)
+ self.assertEqual(working_hours, (4.5, logs_type_1[0].time, logs_type_1[-1].time))
working_hours = calculate_working_hours(logs_type_2,check_in_out_type[1],working_hours_calc_type[0])
- self.assertEqual(working_hours, 5)
+ self.assertEqual(working_hours, (5, logs_type_2[1].time, logs_type_2[-1].time))
working_hours = calculate_working_hours(logs_type_2,check_in_out_type[1],working_hours_calc_type[1])
- self.assertEqual(working_hours, 4.5)
+ self.assertEqual(working_hours, (4.5, logs_type_2[1].time, logs_type_2[-1].time))
def make_n_checkins(employee, n, hours_to_reverse=1):
logs = [make_checkin(employee, now_datetime() - timedelta(hours=hours_to_reverse, minutes=n+1))]
diff --git a/erpnext/hr/doctype/employee_incentive/employee_incentive.js b/erpnext/hr/doctype/employee_incentive/employee_incentive.js
index d2ddfb6..db0f83a 100644
--- a/erpnext/hr/doctype/employee_incentive/employee_incentive.js
+++ b/erpnext/hr/doctype/employee_incentive/employee_incentive.js
@@ -2,7 +2,21 @@
// For license information, please see license.txt
frappe.ui.form.on('Employee Incentive', {
- refresh: function(frm) {
+ setup: function(frm) {
+ frm.set_query("employee", function() {
+ return {
+ filters: {
+ "status": "Active"
+ }
+ };
+ });
+ frm.set_query("salary_component", function() {
+ return {
+ filters: {
+ "type": "Earning"
+ }
+ };
+ });
}
});
diff --git a/erpnext/hr/doctype/employee_incentive/employee_incentive.json b/erpnext/hr/doctype/employee_incentive/employee_incentive.json
index 5ba1d63..3bc772c 100644
--- a/erpnext/hr/doctype/employee_incentive/employee_incentive.json
+++ b/erpnext/hr/doctype/employee_incentive/employee_incentive.json
@@ -1,330 +1,130 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "HR-EINV-.YY.-.MM.-.#####",
- "beta": 0,
- "creation": "2018-04-13 16:13:43.404546",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "autoname": "HR-EINV-.YY.-.MM.-.#####",
+ "creation": "2018-04-13 16:13:43.404546",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "employee",
+ "incentive_amount",
+ "payroll_date",
+ "salary_component",
+ "amended_from",
+ "column_break_5",
+ "employee_name",
+ "department",
+ "additional_salary"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "employee",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Employee",
- "length": 0,
- "no_copy": 0,
- "options": "Employee",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "employee",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Employee",
+ "options": "Employee",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "incentive_amount",
- "fieldtype": "Currency",
- "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": "Incentive Amount",
- "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "incentive_amount",
+ "fieldtype": "Currency",
+ "label": "Incentive Amount",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "payroll_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": "Payroll Date",
- "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
- },
+ "fieldname": "payroll_date",
+ "fieldtype": "Date",
+ "label": "Payroll Date",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amended_from",
- "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",
- "length": 0,
- "no_copy": 1,
- "options": "Employee Incentive",
- "permlevel": 0,
- "print_hide": 1,
- "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
- },
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Employee Incentive",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_5",
- "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
- },
+ "fieldname": "column_break_5",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "employee.employee_name",
- "fieldname": "employee_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Employee Name",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
- },
+ "fetch_from": "employee.employee_name",
+ "fieldname": "employee_name",
+ "fieldtype": "Data",
+ "label": "Employee Name",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "employee.department",
- "fieldname": "department",
- "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",
- "length": 0,
- "no_copy": 0,
- "options": "Department",
- "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
+ "fetch_from": "employee.department",
+ "fieldname": "department",
+ "fieldtype": "Link",
+ "label": "Department",
+ "options": "Department",
+ "read_only": 1
+ },
+ {
+ "fieldname": "additional_salary",
+ "fieldtype": "Link",
+ "label": "Additional Salary",
+ "no_copy": 1,
+ "options": "Additional Salary",
+ "read_only": 1
+ },
+ {
+ "fieldname": "salary_component",
+ "fieldtype": "Link",
+ "label": "Salary Component",
+ "options": "Salary Component",
+ "reqd": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-08-21 16:15:51.811149",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Employee Incentive",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_submittable": 1,
+ "modified": "2019-09-03 16:48:16.822252",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Employee Incentive",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "HR Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR Manager",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Employee",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
- },
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Employee",
+ "share": 1
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "HR User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR User",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "employee_name",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "employee_name",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_incentive/employee_incentive.py b/erpnext/hr/doctype/employee_incentive/employee_incentive.py
index 6c9a315..2e138f8 100644
--- a/erpnext/hr/doctype/employee_incentive/employee_incentive.py
+++ b/erpnext/hr/doctype/employee_incentive/employee_incentive.py
@@ -7,4 +7,39 @@
from frappe.model.document import Document
class EmployeeIncentive(Document):
- pass
+ def on_submit(self):
+ company = frappe.db.get_value('Employee', self.employee, 'company')
+ additional_salary = frappe.db.exists('Additional Salary', {
+ 'employee': self.employee,
+ 'salary_component': self.salary_component,
+ 'payroll_date': self.payroll_date,
+ 'company': company,
+ 'docstatus': 1
+ })
+
+ if not additional_salary:
+ additional_salary = frappe.new_doc('Additional Salary')
+ additional_salary.employee = self.employee
+ additional_salary.salary_component = self.salary_component
+ additional_salary.amount = self.incentive_amount
+ additional_salary.payroll_date = self.payroll_date
+ additional_salary.company = company
+ additional_salary.submit()
+ self.db_set('additional_salary', additional_salary.name)
+
+ else:
+ incentive_added = frappe.db.get_value('Additional Salary', additional_salary, 'amount') + self.incentive_amount
+ frappe.db.set_value('Additional Salary', additional_salary, 'amount', incentive_added)
+ self.db_set('additional_salary', additional_salary)
+
+ def on_cancel(self):
+ if self.additional_salary:
+ incentive_removed = frappe.db.get_value('Additional Salary', self.additional_salary, 'amount') - self.incentive_amount
+ if incentive_removed == 0:
+ frappe.get_doc('Additional Salary', self.additional_salary).cancel()
+ else:
+ frappe.db.set_value('Additional Salary', self.additional_salary, 'amount', incentive_removed)
+
+ self.db_set('additional_salary', '')
+
+
diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.py b/erpnext/hr/doctype/expense_claim/test_expense_claim.py
index 6618a4f..b559dfd 100644
--- a/erpnext/hr/doctype/expense_claim/test_expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/test_expense_claim.py
@@ -45,7 +45,6 @@
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_expense_claim"), 700)
expense_claim2.cancel()
- frappe.delete_doc("Expense Claim", expense_claim2.name)
self.assertEqual(frappe.db.get_value("Task", task_name, "total_expense_claim"), 200)
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_expense_claim"), 200)
diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.json b/erpnext/hr/doctype/hr_settings/hr_settings.json
index 8dd0acf..a41c887 100644
--- a/erpnext/hr/doctype/hr_settings/hr_settings.json
+++ b/erpnext/hr/doctype/hr_settings/hr_settings.json
@@ -24,6 +24,7 @@
"column_break_18",
"leave_approver_mandatory_in_leave_application",
"show_leaves_of_all_department_members_in_calendar",
+ "auto_leave_encashment",
"hiring_settings",
"check_vacancies"
],
@@ -153,12 +154,18 @@
"fieldname": "check_vacancies",
"fieldtype": "Check",
"label": "Check Vacancies On Job Offer Creation"
+ },
+ {
+ "default": "0",
+ "fieldname": "auto_leave_encashment",
+ "fieldtype": "Check",
+ "label": "Auto Leave Encashment"
}
],
"icon": "fa fa-cog",
"idx": 1,
"issingle": 1,
- "modified": "2019-07-01 18:59:55.256878",
+ "modified": "2019-08-05 13:07:17.993968",
"modified_by": "Administrator",
"module": "HR",
"name": "HR Settings",
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.js b/erpnext/hr/doctype/leave_allocation/leave_allocation.js
index 4b4bfaf..210a73c 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.js
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.js
@@ -21,11 +21,41 @@
})
},
+ refresh: function(frm) {
+ if(frm.doc.docstatus === 1 && frm.doc.expired) {
+ var valid_expiry = moment(frappe.datetime.get_today()).isBetween(frm.doc.from_date, frm.doc.to_date);
+ if(valid_expiry) {
+ // expire current allocation
+ frm.add_custom_button(__('Expire Allocation'), function() {
+ frm.trigger("expire_allocation");
+ });
+ }
+ }
+ },
+
+ expire_allocation: function(frm) {
+ frappe.call({
+ method: 'erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry.expire_allocation',
+ args: {
+ 'allocation': frm.doc,
+ 'expiry_date': frappe.datetime.get_today()
+ },
+ freeze: true,
+ callback: function(r){
+ if(!r.exc){
+ frappe.msgprint(__("Allocation Expired!"));
+ }
+ frm.refresh();
+ }
+ });
+ },
+
employee: function(frm) {
frm.trigger("calculate_total_leaves_allocated");
},
leave_type: function(frm) {
+ frm.trigger("leave_policy");
frm.trigger("calculate_total_leaves_allocated");
},
@@ -33,37 +63,38 @@
frm.trigger("calculate_total_leaves_allocated");
},
- carry_forwarded_leaves: function(frm) {
+ unused_leaves: function(frm) {
frm.set_value("total_leaves_allocated",
- flt(frm.doc.carry_forwarded_leaves) + flt(frm.doc.new_leaves_allocated));
+ flt(frm.doc.unused_leaves) + flt(frm.doc.new_leaves_allocated));
},
new_leaves_allocated: function(frm) {
frm.set_value("total_leaves_allocated",
- flt(frm.doc.carry_forwarded_leaves) + flt(frm.doc.new_leaves_allocated));
+ flt(frm.doc.unused_leaves) + flt(frm.doc.new_leaves_allocated));
},
+ leave_policy: function(frm) {
+ if(frm.doc.leave_policy && frm.doc.leave_type) {
+ frappe.db.get_value("Leave Policy Detail",{
+ 'parent': frm.doc.leave_policy,
+ 'leave_type': frm.doc.leave_type
+ }, 'annual_allocation', (r) => {
+ if (r && !r.exc) frm.set_value("new_leaves_allocated", flt(r.annual_allocation));
+ }, "Leave Policy");
+ }
+ },
calculate_total_leaves_allocated: function(frm) {
if (cint(frm.doc.carry_forward) == 1 && frm.doc.leave_type && frm.doc.employee) {
return frappe.call({
- method: "erpnext.hr.doctype.leave_allocation.leave_allocation.get_carry_forwarded_leaves",
- args: {
- "employee": frm.doc.employee,
- "date": frm.doc.from_date,
- "leave_type": frm.doc.leave_type,
- "carry_forward": frm.doc.carry_forward
- },
+ method: "set_total_leaves_allocated",
+ doc: frm.doc,
callback: function(r) {
- if (!r.exc && r.message) {
- frm.set_value('carry_forwarded_leaves', r.message);
- frm.set_value("total_leaves_allocated",
- flt(r.message) + flt(frm.doc.new_leaves_allocated));
- }
+ frm.refresh_fields();
}
})
} else if (cint(frm.doc.carry_forward) == 0) {
- frm.set_value("carry_forwarded_leaves", 0);
+ frm.set_value("unused_leaves", 0);
frm.set_value("total_leaves_allocated", flt(frm.doc.new_leaves_allocated));
}
}
-})
+});
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.json b/erpnext/hr/doctype/leave_allocation/leave_allocation.json
index 6d61fe3..007497e 100644
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.json
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.json
@@ -1,683 +1,220 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
"allow_import": 1,
- "allow_rename": 0,
"autoname": "naming_series:",
- "beta": 0,
"creation": "2013-02-20 19:10:38",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
- "editable_grid": 0,
"engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "employee",
+ "employee_name",
+ "department",
+ "column_break1",
+ "leave_type",
+ "from_date",
+ "to_date",
+ "section_break_6",
+ "new_leaves_allocated",
+ "carry_forward",
+ "unused_leaves",
+ "total_leaves_allocated",
+ "total_leaves_encashed",
+ "column_break_10",
+ "compensatory_request",
+ "leave_period",
+ "leave_policy",
+ "carry_forwarded_leaves_count",
+ "expired",
+ "amended_from",
+ "notes",
+ "description"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
"fieldname": "naming_series",
"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",
- "length": 0,
"no_copy": 1,
"options": "HR-LAL-.YYYY.-",
- "permlevel": 0,
- "precision": "",
"print_hide": 1,
- "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": 1,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "employee",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Employee",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "employee",
"oldfieldtype": "Link",
"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,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "employee.employee_name",
"fieldname": "employee_name",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Employee Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
"read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "employee.department",
"fieldname": "department",
"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",
- "length": 0,
- "no_copy": 0,
"options": "Department",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_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,
"width": "50%"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "leave_type",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Leave Type",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "leave_type",
"oldfieldtype": "Link",
"options": "Leave Type",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
"reqd": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "from_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": "From Date",
- "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "to_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": "To Date",
- "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "section_break_6",
"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": "Allocation",
- "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
+ "label": "Allocation"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
"bold": 1,
- "collapsible": 0,
- "columns": 0,
"fieldname": "new_leaves_allocated",
"fieldtype": "Float",
- "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": "New Leaves Allocated",
- "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
+ "label": "New Leaves Allocated"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
+ "default": "0",
"fieldname": "carry_forward",
"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": "Add unused leaves from previous allocations",
- "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
+ "label": "Add unused leaves from previous allocations"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "carry_forward",
- "fieldname": "carry_forwarded_leaves",
+ "fieldname": "unused_leaves",
"fieldtype": "Float",
- "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": "Unused leaves",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
"allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "total_leaves_allocated",
"fieldtype": "Float",
- "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": "Total Leaves Allocated",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
"read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "eval:doc.total_leaves_encashed>0",
"fieldname": "total_leaves_encashed",
"fieldtype": "Float",
- "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": "Total Leaves Encashed",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_10",
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "compensatory_request",
"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": "Compensatory Leave Request",
- "length": 0,
- "no_copy": 0,
"options": "Compensatory Leave Request",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "leave_period",
"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,
"label": "Leave Period",
- "length": 0,
- "no_copy": 0,
"options": "Leave Period",
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "fetch_from": "employee.leave_policy",
+ "fieldname": "leave_policy",
+ "fieldtype": "Link",
+ "in_standard_filter": 1,
+ "label": "Leave Policy",
+ "options": "Leave Policy",
+ "read_only": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "expired",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "in_standard_filter": 1,
+ "label": "Expired",
+ "read_only": 1
+ },
+ {
"fieldname": "amended_from",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Amended From",
- "length": 0,
"no_copy": 1,
"oldfieldname": "amended_from",
"oldfieldtype": "Data",
"options": "Leave Allocation",
- "permlevel": 0,
"print_hide": 1,
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
- "columns": 0,
"fieldname": "notes",
"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": "Notes",
- "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
+ "label": "Notes"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "description",
"fieldtype": "Small Text",
- "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": "Description",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "reason",
"oldfieldtype": "Small Text",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
"width": "300px"
+ },
+ {
+ "depends_on": "carry_forwarded_leaves_count",
+ "fieldname": "carry_forwarded_leaves_count",
+ "fieldtype": "Float",
+ "label": "Carry Forwarded Leaves",
+ "read_only": 1
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
"icon": "fa fa-ok",
"idx": 1,
- "image_view": 0,
- "in_create": 0,
"is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-01-30 11:28:09.360525",
+ "modified": "2019-08-08 15:08:42.440909",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Allocation",
@@ -689,15 +226,10 @@
"create": 1,
"delete": 1,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "HR User",
- "set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
@@ -709,28 +241,19 @@
"delete": 1,
"email": 1,
"export": 1,
- "if_owner": 0,
"import": 1,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "HR Manager",
- "set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
}
],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
"search_fields": "employee,employee_name,leave_type,total_leaves_allocated",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
- "timeline_field": "employee",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ "timeline_field": "employee"
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
index dc270db..874ae7a 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
@@ -3,11 +3,11 @@
from __future__ import unicode_literals
import frappe
-from frappe.utils import flt, date_diff, formatdate
+from frappe.utils import flt, date_diff, formatdate, add_days, today, getdate
from frappe import _
from frappe.model.document import Document
from erpnext.hr.utils import set_employee_name, get_leave_period
-from erpnext.hr.doctype.leave_application.leave_application import get_approved_leaves_for_period
+from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import expire_allocation, create_leave_ledger_entry
class OverlapError(frappe.ValidationError): pass
class BackDatedAllocationError(frappe.ValidationError): pass
@@ -34,20 +34,25 @@
if max_leaves_allowed > 0:
leave_allocated = 0
if leave_period:
- leave_allocated = get_leave_allocation_for_period(self.employee, self.leave_type, leave_period[0].from_date, leave_period[0].to_date)
+ leave_allocated = get_leave_allocation_for_period(self.employee, self.leave_type,
+ leave_period[0].from_date, leave_period[0].to_date)
leave_allocated += self.new_leaves_allocated
if leave_allocated > max_leaves_allowed:
- frappe.throw(_("Total allocated leaves are more days than maximum allocation of {0} leave type for employee {1} in the period")\
+ frappe.throw(_("Total allocated leaves are more days than maximum allocation of {0} leave type for employee {1} in the period")
.format(self.leave_type, self.employee))
- def on_update_after_submit(self):
- self.validate_new_leaves_allocated_value()
- self.set_total_leaves_allocated()
+ def on_submit(self):
+ self.create_leave_ledger_entry()
- frappe.db.set(self,'carry_forwarded_leaves', flt(self.carry_forwarded_leaves))
- frappe.db.set(self,'total_leaves_allocated',flt(self.total_leaves_allocated))
+ # expire all unused leaves in the ledger on creation of carry forward allocation
+ allocation = get_previous_allocation(self.from_date, self.leave_type, self.employee)
+ if self.carry_forward and allocation:
+ expire_allocation(allocation)
- self.validate_against_leave_applications()
+ def on_cancel(self):
+ self.create_leave_ledger_entry(submit=False)
+ if self.carry_forward:
+ self.set_carry_forwarded_leaves_in_previous_allocation(on_cancel=True)
def validate_period(self):
if date_diff(self.to_date, self.from_date) <= 0:
@@ -87,13 +92,36 @@
BackDatedAllocationError)
def set_total_leaves_allocated(self):
- self.carry_forwarded_leaves = get_carry_forwarded_leaves(self.employee,
+ self.unused_leaves = get_carry_forwarded_leaves(self.employee,
self.leave_type, self.from_date, self.carry_forward)
- self.total_leaves_allocated = flt(self.carry_forwarded_leaves) + flt(self.new_leaves_allocated)
+ self.total_leaves_allocated = flt(self.unused_leaves) + flt(self.new_leaves_allocated)
- if not self.total_leaves_allocated and not frappe.db.get_value("Leave Type", self.leave_type, "is_earned_leave") and not frappe.db.get_value("Leave Type", self.leave_type, "is_compensatory"):
- frappe.throw(_("Total leaves allocated is mandatory for Leave Type {0}".format(self.leave_type)))
+ self.limit_carry_forward_based_on_max_allowed_leaves()
+
+ if self.carry_forward:
+ self.set_carry_forwarded_leaves_in_previous_allocation()
+
+ if not self.total_leaves_allocated \
+ and not frappe.db.get_value("Leave Type", self.leave_type, "is_earned_leave") \
+ and not frappe.db.get_value("Leave Type", self.leave_type, "is_compensatory"):
+ frappe.throw(_("Total leaves allocated is mandatory for Leave Type {0}")
+ .format(self.leave_type))
+
+ def limit_carry_forward_based_on_max_allowed_leaves(self):
+ max_leaves_allowed = frappe.db.get_value("Leave Type", self.leave_type, "max_leaves_allowed")
+ if max_leaves_allowed and self.total_leaves_allocated > flt(max_leaves_allowed):
+ self.total_leaves_allocated = flt(max_leaves_allowed)
+ self.unused_leaves = max_leaves_allowed - flt(self.new_leaves_allocated)
+
+ def set_carry_forwarded_leaves_in_previous_allocation(self, on_cancel=False):
+ ''' Set carry forwarded leaves in previous allocation '''
+ previous_allocation = get_previous_allocation(self.from_date, self.leave_type, self.employee)
+ if on_cancel:
+ self.unused_leaves = 0.0
+ if previous_allocation:
+ frappe.db.set_value("Leave Allocation", previous_allocation.name,
+ 'carry_forwarded_leaves_count', self.unused_leaves)
def validate_total_leaves_allocated(self):
# Adding a day to include To Date in the difference
@@ -101,15 +129,37 @@
if date_difference < self.total_leaves_allocated:
frappe.throw(_("Total allocated leaves are more than days in the period"), OverAllocationError)
- def validate_against_leave_applications(self):
- leaves_taken = get_approved_leaves_for_period(self.employee, self.leave_type,
- self.from_date, self.to_date)
+ def create_leave_ledger_entry(self, submit=True):
+ if self.unused_leaves:
+ expiry_days = frappe.db.get_value("Leave Type", self.leave_type, "expire_carry_forwarded_leaves_after_days")
+ end_date = add_days(self.from_date, expiry_days - 1) if expiry_days else self.to_date
+ args = dict(
+ leaves=self.unused_leaves,
+ from_date=self.from_date,
+ to_date= min(getdate(end_date), getdate(self.to_date)),
+ is_carry_forward=1
+ )
+ create_leave_ledger_entry(self, args, submit)
- if flt(leaves_taken) > flt(self.total_leaves_allocated):
- if frappe.db.get_value("Leave Type", self.leave_type, "allow_negative"):
- frappe.msgprint(_("Note: Total allocated leaves {0} shouldn't be less than already approved leaves {1} for the period").format(self.total_leaves_allocated, leaves_taken))
- else:
- frappe.throw(_("Total allocated leaves {0} cannot be less than already approved leaves {1} for the period").format(self.total_leaves_allocated, leaves_taken), LessAllocationError)
+ args = dict(
+ leaves=self.new_leaves_allocated,
+ from_date=self.from_date,
+ to_date=self.to_date,
+ is_carry_forward=0
+ )
+ create_leave_ledger_entry(self, args, submit)
+
+def get_previous_allocation(from_date, leave_type, employee):
+ ''' Returns document properties of previous allocation '''
+ return frappe.db.get_value("Leave Allocation",
+ filters={
+ 'to_date': ("<", from_date),
+ 'leave_type': leave_type,
+ 'employee': employee,
+ 'docstatus': 1
+ },
+ order_by='to_date DESC',
+ fieldname=['name', 'from_date', 'to_date', 'employee', 'leave_type'], as_dict=1)
def get_leave_allocation_for_period(employee, leave_type, from_date, to_date):
leave_allocated = 0
@@ -136,25 +186,34 @@
@frappe.whitelist()
def get_carry_forwarded_leaves(employee, leave_type, date, carry_forward=None):
- carry_forwarded_leaves = 0
-
- if carry_forward:
+ ''' Returns carry forwarded leaves for the given employee '''
+ unused_leaves = 0.0
+ previous_allocation = get_previous_allocation(date, leave_type, employee)
+ if carry_forward and previous_allocation:
validate_carry_forward(leave_type)
+ unused_leaves = get_unused_leaves(employee, leave_type,
+ previous_allocation.from_date, previous_allocation.to_date)
+ if unused_leaves:
+ max_carry_forwarded_leaves = frappe.db.get_value("Leave Type",
+ leave_type, "maximum_carry_forwarded_leaves")
+ if max_carry_forwarded_leaves and unused_leaves > flt(max_carry_forwarded_leaves):
+ unused_leaves = flt(max_carry_forwarded_leaves)
- previous_allocation = frappe.db.sql("""
- select name, from_date, to_date, total_leaves_allocated
- from `tabLeave Allocation`
- where employee=%s and leave_type=%s and docstatus=1 and to_date < %s
- order by to_date desc limit 1
- """, (employee, leave_type, date), as_dict=1)
- if previous_allocation:
- leaves_taken = get_approved_leaves_for_period(employee, leave_type,
- previous_allocation[0].from_date, previous_allocation[0].to_date)
+ return unused_leaves
- carry_forwarded_leaves = flt(previous_allocation[0].total_leaves_allocated) - flt(leaves_taken)
-
- return carry_forwarded_leaves
+def get_unused_leaves(employee, leave_type, from_date, to_date):
+ ''' Returns unused leaves between the given period while skipping leave allocation expiry '''
+ leaves = frappe.get_all("Leave Ledger Entry", filters={
+ 'employee': employee,
+ 'leave_type': leave_type,
+ 'from_date': ('>=', from_date),
+ 'to_date': ('<=', to_date)
+ }, or_filters={
+ 'is_expired': 0,
+ 'is_carry_forward': 1
+ }, fields=['sum(leaves) as leaves'])
+ return flt(leaves[0]['leaves'])
def validate_carry_forward(leave_type):
if not frappe.db.get_value("Leave Type", leave_type, "is_carry_forward"):
- frappe.throw(_("Leave Type {0} cannot be carry-forwarded").format(leave_type))
+ frappe.throw(_("Leave Type {0} cannot be carry-forwarded").format(leave_type))
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation_dashboard.py b/erpnext/hr/doctype/leave_allocation/leave_allocation_dashboard.py
index 72a1b7c..7456aeb 100644
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation_dashboard.py
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation_dashboard.py
@@ -12,4 +12,9 @@
'items': ['Leave Encashment']
}
],
+ 'reports': [
+ {
+ 'items': ['Employee Leave Balance']
+ }
+ ]
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation_list.js b/erpnext/hr/doctype/leave_allocation/leave_allocation_list.js
new file mode 100644
index 0000000..93f7b83
--- /dev/null
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation_list.js
@@ -0,0 +1,11 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
+// License: GNU General Public License v3. See license.txt
+
+// render
+frappe.listview_settings['Leave Allocation'] = {
+ get_indicator: function(doc) {
+ if(doc.status==="Expired") {
+ return [__("Expired"), "darkgrey", "expired, =, 1"];
+ }
+ },
+};
diff --git a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.js b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.js
index b8f4faf..0ef78f2 100644
--- a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.js
+++ b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.js
@@ -34,7 +34,7 @@
() => assert.equal(today_date, cur_frm.doc.from_date,
"from date correctly set"),
// check for total leaves
- () => assert.equal(cur_frm.doc.carry_forwarded_leaves + 2, cur_frm.doc.total_leaves_allocated,
+ () => assert.equal(cur_frm.doc.unused_leaves + 2, cur_frm.doc.total_leaves_allocated,
"total leave calculation is correctly set"),
() => done()
]);
diff --git a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py
index 3b22eb2..26f077a 100644
--- a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py
@@ -1,12 +1,14 @@
from __future__ import unicode_literals
import frappe
import unittest
-from frappe.utils import getdate
+from frappe.utils import nowdate, add_months, getdate, add_days
+from erpnext.hr.doctype.leave_type.test_leave_type import create_leave_type
+from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import process_expired_allocation, expire_allocation
class TestLeaveAllocation(unittest.TestCase):
def test_overlapping_allocation(self):
frappe.db.sql("delete from `tabLeave Allocation`")
-
+
employee = frappe.get_doc("Employee", frappe.db.sql_list("select name from tabEmployee limit 1")[0])
leaves = [
{
@@ -18,7 +20,7 @@
"from_date": getdate("2015-10-01"),
"to_date": getdate("2015-10-31"),
"new_leaves_allocated": 5,
- "docstatus": 1
+ "docstatus": 1
},
{
"doctype": "Leave Allocation",
@@ -28,17 +30,17 @@
"leave_type": "_Test Leave Type",
"from_date": getdate("2015-09-01"),
"to_date": getdate("2015-11-30"),
- "new_leaves_allocated": 5
+ "new_leaves_allocated": 5
}
]
frappe.get_doc(leaves[0]).save()
self.assertRaises(frappe.ValidationError, frappe.get_doc(leaves[1]).save)
-
- def test_invalid_period(self):
+
+ def test_invalid_period(self):
employee = frappe.get_doc("Employee", frappe.db.sql_list("select name from tabEmployee limit 1")[0])
-
- d = frappe.get_doc({
+
+ doc = frappe.get_doc({
"doctype": "Leave Allocation",
"__islocal": 1,
"employee": employee.name,
@@ -46,15 +48,15 @@
"leave_type": "_Test Leave Type",
"from_date": getdate("2015-09-30"),
"to_date": getdate("2015-09-1"),
- "new_leaves_allocated": 5
+ "new_leaves_allocated": 5
})
-
+
#invalid period
- self.assertRaises(frappe.ValidationError, d.save)
-
+ self.assertRaises(frappe.ValidationError, doc.save)
+
def test_allocated_leave_days_over_period(self):
employee = frappe.get_doc("Employee", frappe.db.sql_list("select name from tabEmployee limit 1")[0])
- d = frappe.get_doc({
+ doc = frappe.get_doc({
"doctype": "Leave Allocation",
"__islocal": 1,
"employee": employee.name,
@@ -62,10 +64,117 @@
"leave_type": "_Test Leave Type",
"from_date": getdate("2015-09-1"),
"to_date": getdate("2015-09-30"),
- "new_leaves_allocated": 35
+ "new_leaves_allocated": 35
})
-
- #allocated leave more than period
- self.assertRaises(frappe.ValidationError, d.save)
-
+ #allocated leave more than period
+ self.assertRaises(frappe.ValidationError, doc.save)
+
+ def test_carry_forward_calculation(self):
+ frappe.db.sql("delete from `tabLeave Allocation`")
+ frappe.db.sql("delete from `tabLeave Ledger Entry`")
+ leave_type = create_leave_type(leave_type_name="_Test_CF_leave", is_carry_forward=1)
+ leave_type.maximum_carry_forwarded_leaves = 10
+ leave_type.max_leaves_allowed = 30
+ leave_type.save()
+
+ # initial leave allocation = 15
+ leave_allocation = create_leave_allocation(
+ leave_type="_Test_CF_leave",
+ from_date=add_months(nowdate(), -12),
+ to_date=add_months(nowdate(), -1),
+ carry_forward=0)
+ leave_allocation.submit()
+
+ # carry forwarded leaves considering maximum_carry_forwarded_leaves
+ # new_leaves = 15, carry_forwarded = 10
+ leave_allocation_1 = create_leave_allocation(
+ leave_type="_Test_CF_leave",
+ carry_forward=1)
+ leave_allocation_1.submit()
+
+ self.assertEquals(leave_allocation_1.unused_leaves, 10)
+
+ leave_allocation_1.cancel()
+
+ # carry forwarded leaves considering max_leave_allowed
+ # max_leave_allowed = 30, new_leaves = 25, carry_forwarded = 5
+ leave_allocation_2 = create_leave_allocation(
+ leave_type="_Test_CF_leave",
+ carry_forward=1,
+ new_leaves_allocated=25)
+ leave_allocation_2.submit()
+
+ self.assertEquals(leave_allocation_2.unused_leaves, 5)
+
+ def test_carry_forward_leaves_expiry(self):
+ frappe.db.sql("delete from `tabLeave Allocation`")
+ frappe.db.sql("delete from `tabLeave Ledger Entry`")
+ leave_type = create_leave_type(
+ leave_type_name="_Test_CF_leave_expiry",
+ is_carry_forward=1,
+ expire_carry_forwarded_leaves_after_days=90)
+ leave_type.save()
+
+ # initial leave allocation
+ leave_allocation = create_leave_allocation(
+ leave_type="_Test_CF_leave_expiry",
+ from_date=add_months(nowdate(), -24),
+ to_date=add_months(nowdate(), -12),
+ carry_forward=0)
+ leave_allocation.submit()
+
+ leave_allocation = create_leave_allocation(
+ leave_type="_Test_CF_leave_expiry",
+ from_date=add_days(nowdate(), -90),
+ to_date=add_days(nowdate(), 100),
+ carry_forward=1)
+ leave_allocation.submit()
+
+ # expires all the carry forwarded leaves after 90 days
+ process_expired_allocation()
+
+ # leave allocation with carry forward of only new leaves allocated
+ leave_allocation_1 = create_leave_allocation(
+ leave_type="_Test_CF_leave_expiry",
+ carry_forward=1,
+ from_date=add_months(nowdate(), 6),
+ to_date=add_months(nowdate(), 12))
+ leave_allocation_1.submit()
+
+ self.assertEquals(leave_allocation_1.unused_leaves, leave_allocation.new_leaves_allocated)
+
+ def test_creation_of_leave_ledger_entry_on_submit(self):
+ frappe.db.sql("delete from `tabLeave Allocation`")
+
+ leave_allocation = create_leave_allocation()
+ leave_allocation.submit()
+
+ leave_ledger_entry = frappe.get_all('Leave Ledger Entry', fields='*', filters=dict(transaction_name=leave_allocation.name))
+
+ self.assertEquals(len(leave_ledger_entry), 1)
+ self.assertEquals(leave_ledger_entry[0].employee, leave_allocation.employee)
+ self.assertEquals(leave_ledger_entry[0].leave_type, leave_allocation.leave_type)
+ self.assertEquals(leave_ledger_entry[0].leaves, leave_allocation.new_leaves_allocated)
+
+ # check if leave ledger entry is deleted on cancellation
+ leave_allocation.cancel()
+ self.assertFalse(frappe.db.exists("Leave Ledger Entry", {'transaction_name':leave_allocation.name}))
+
+def create_leave_allocation(**args):
+ args = frappe._dict(args)
+
+ employee = frappe.get_doc("Employee", frappe.db.sql_list("select name from tabEmployee limit 1")[0])
+ leave_allocation = frappe.get_doc({
+ "doctype": "Leave Allocation",
+ "__islocal": 1,
+ "employee": args.employee or employee.name,
+ "employee_name": args.employee_name or employee.employee_name,
+ "leave_type": args.leave_type or "_Test Leave Type",
+ "from_date": args.from_date or nowdate(),
+ "new_leaves_allocated": args.new_leaves_allocated or 15,
+ "carry_forward": args.carry_forward or 0,
+ "to_date": args.to_date or add_months(nowdate(), 12)
+ })
+ return leave_allocation
+
test_dependencies = ["Employee", "Leave Type"]
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_application/leave_application.js b/erpnext/hr/doctype/leave_application/leave_application.js
index 5bce348..1746410 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.js
+++ b/erpnext/hr/doctype/leave_application/leave_application.js
@@ -49,7 +49,7 @@
async: false,
args: {
employee: frm.doc.employee,
- date: frm.doc.posting_date
+ date: frm.doc.from_date || frm.doc.posting_date
},
callback: function(r) {
if (!r.exc && r.message['leave_allocation']) {
@@ -60,9 +60,8 @@
}
}
});
-
$("div").remove(".form-dashboard-section");
- let section = frm.dashboard.add_section(
+ frm.dashboard.add_section(
frappe.render_template('leave_application_dashboard', {
data: leave_details
})
@@ -115,6 +114,7 @@
},
from_date: function(frm) {
+ frm.trigger("make_dashboard");
frm.trigger("half_day_datepicker");
frm.trigger("calculate_total_days");
},
@@ -138,12 +138,13 @@
},
get_leave_balance: function(frm) {
- if(frm.doc.docstatus==0 && frm.doc.employee && frm.doc.leave_type && frm.doc.from_date) {
+ if(frm.doc.docstatus==0 && frm.doc.employee && frm.doc.leave_type && frm.doc.from_date && frm.doc.to_date) {
return frappe.call({
method: "erpnext.hr.doctype.leave_application.leave_application.get_leave_balance_on",
args: {
employee: frm.doc.employee,
date: frm.doc.from_date,
+ to_date: frm.doc.to_date,
leave_type: frm.doc.leave_type,
consider_all_leaves_in_the_allocation_period: true
},
diff --git a/erpnext/hr/doctype/leave_application/leave_application.json b/erpnext/hr/doctype/leave_application/leave_application.json
index b3800e0..cdb1add 100644
--- a/erpnext/hr/doctype/leave_application/leave_application.json
+++ b/erpnext/hr/doctype/leave_application/leave_application.json
@@ -1,332 +1,332 @@
{
- "allow_import": 1,
- "autoname": "naming_series:",
- "creation": "2013-02-20 11:18:11",
- "description": "Apply / Approve Leaves",
- "doctype": "DocType",
- "document_type": "Document",
- "engine": "InnoDB",
- "field_order": [
- "naming_series",
- "employee",
- "employee_name",
- "column_break_4",
- "leave_type",
- "department",
- "leave_balance",
- "section_break_5",
- "from_date",
- "to_date",
- "half_day",
- "half_day_date",
- "total_leave_days",
- "column_break1",
- "description",
- "section_break_7",
- "leave_approver",
- "leave_approver_name",
- "column_break_18",
- "status",
- "salary_slip",
- "sb10",
- "posting_date",
- "follow_via_email",
- "color",
- "column_break_17",
- "company",
- "letter_head",
- "amended_from"
- ],
- "fields": [
- {
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "label": "Series",
- "no_copy": 1,
- "options": "HR-LAP-.YYYY.-",
- "print_hide": 1,
- "reqd": 1,
- "set_only_once": 1
- },
- {
- "fieldname": "employee",
- "fieldtype": "Link",
- "in_global_search": 1,
- "in_standard_filter": 1,
- "label": "Employee",
- "options": "Employee",
- "reqd": 1,
- "search_index": 1
- },
- {
- "fieldname": "employee_name",
- "fieldtype": "Data",
- "in_global_search": 1,
- "label": "Employee Name",
- "read_only": 1
- },
- {
- "fieldname": "column_break_4",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "leave_type",
- "fieldtype": "Link",
- "ignore_user_permissions": 1,
- "in_standard_filter": 1,
- "label": "Leave Type",
- "options": "Leave Type",
- "reqd": 1,
- "search_index": 1
- },
- {
- "fetch_from": "employee.department",
- "fieldname": "department",
- "fieldtype": "Link",
- "label": "Department",
- "options": "Department",
- "read_only": 1
- },
- {
- "fieldname": "leave_balance",
- "fieldtype": "Float",
- "label": "Leave Balance Before Application",
- "no_copy": 1,
- "read_only": 1
- },
- {
- "fieldname": "section_break_5",
- "fieldtype": "Section Break"
- },
- {
- "fieldname": "from_date",
- "fieldtype": "Date",
- "in_list_view": 1,
- "label": "From Date",
- "reqd": 1,
- "search_index": 1
- },
- {
- "fieldname": "to_date",
- "fieldtype": "Date",
- "label": "To Date",
- "reqd": 1,
- "search_index": 1
- },
- {
- "default": "0",
- "fieldname": "half_day",
- "fieldtype": "Check",
- "label": "Half Day"
- },
- {
- "depends_on": "eval:doc.half_day && (doc.from_date != doc.to_date)",
- "fieldname": "half_day_date",
- "fieldtype": "Date",
- "label": "Half Day Date"
- },
- {
- "fieldname": "total_leave_days",
- "fieldtype": "Float",
- "in_list_view": 1,
- "label": "Total Leave Days",
- "no_copy": 1,
- "precision": "1",
- "read_only": 1
- },
- {
- "fieldname": "column_break1",
- "fieldtype": "Column Break",
- "print_width": "50%",
- "width": "50%"
- },
- {
- "fieldname": "description",
- "fieldtype": "Small Text",
- "label": "Reason"
- },
- {
- "fieldname": "section_break_7",
- "fieldtype": "Section Break"
- },
- {
- "fieldname": "leave_approver",
- "fieldtype": "Link",
- "label": "Leave Approver",
- "options": "User"
- },
- {
- "fieldname": "leave_approver_name",
- "fieldtype": "Data",
- "label": "Leave Approver Name",
- "read_only": 1
- },
- {
- "fieldname": "column_break_18",
- "fieldtype": "Column Break"
- },
- {
- "default": "Open",
- "fieldname": "status",
- "fieldtype": "Select",
- "in_standard_filter": 1,
- "label": "Status",
- "no_copy": 1,
- "options": "Open\nApproved\nRejected\nCancelled"
- },
- {
- "fieldname": "salary_slip",
- "fieldtype": "Link",
- "label": "Salary Slip",
- "options": "Salary Slip",
- "print_hide": 1
- },
- {
- "fieldname": "sb10",
- "fieldtype": "Section Break"
- },
- {
- "default": "Today",
- "fieldname": "posting_date",
- "fieldtype": "Date",
- "label": "Posting Date",
- "no_copy": 1,
- "reqd": 1
- },
- {
- "allow_on_submit": 1,
- "default": "1",
- "fieldname": "follow_via_email",
- "fieldtype": "Check",
- "label": "Follow via Email",
- "print_hide": 1
- },
- {
- "allow_on_submit": 1,
- "fieldname": "color",
- "fieldtype": "Color",
- "label": "Color",
- "print_hide": 1
- },
- {
- "fieldname": "column_break_17",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "company",
- "fieldtype": "Link",
- "label": "Company",
- "options": "Company",
- "remember_last_selected_value": 1,
- "reqd": 1
- },
- {
- "allow_on_submit": 1,
- "fieldname": "letter_head",
- "fieldtype": "Link",
- "ignore_user_permissions": 1,
- "label": "Letter Head",
- "options": "Letter Head",
- "print_hide": 1
- },
- {
- "fieldname": "amended_from",
- "fieldtype": "Link",
- "ignore_user_permissions": 1,
- "label": "Amended From",
- "no_copy": 1,
- "options": "Leave Application",
- "print_hide": 1,
- "read_only": 1
- }
- ],
- "icon": "fa fa-calendar",
- "idx": 1,
- "is_submittable": 1,
- "max_attachments": 3,
- "modified": "2019-08-11 19:13:53.603011",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Leave Application",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "email": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Employee",
- "share": 1,
- "write": 1
- },
- {
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "HR Manager",
- "set_user_permissions": 1,
- "share": 1,
- "submit": 1,
- "write": 1
- },
- {
- "permlevel": 1,
- "read": 1,
- "role": "All"
- },
- {
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "HR User",
- "set_user_permissions": 1,
- "share": 1,
- "submit": 1,
- "write": 1
- },
- {
- "amend": 1,
- "cancel": 1,
- "delete": 1,
- "email": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Leave Approver",
- "share": 1,
- "submit": 1,
- "write": 1
- },
- {
- "permlevel": 1,
- "read": 1,
- "report": 1,
- "role": "HR User",
- "write": 1
- },
- {
- "permlevel": 1,
- "read": 1,
- "report": 1,
- "role": "Leave Approver",
- "write": 1
- }
- ],
- "search_fields": "employee,employee_name,leave_type,from_date,to_date,total_leave_days",
- "sort_field": "modified",
- "sort_order": "DESC",
- "timeline_field": "employee",
- "title_field": "employee_name"
-}
\ No newline at end of file
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "creation": "2013-02-20 11:18:11",
+ "description": "Apply / Approve Leaves",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "employee",
+ "employee_name",
+ "column_break_4",
+ "leave_type",
+ "department",
+ "leave_balance",
+ "section_break_5",
+ "from_date",
+ "to_date",
+ "half_day",
+ "half_day_date",
+ "total_leave_days",
+ "column_break1",
+ "description",
+ "section_break_7",
+ "leave_approver",
+ "leave_approver_name",
+ "column_break_18",
+ "status",
+ "salary_slip",
+ "sb10",
+ "posting_date",
+ "follow_via_email",
+ "color",
+ "column_break_17",
+ "company",
+ "letter_head",
+ "amended_from"
+ ],
+ "fields": [
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "no_copy": 1,
+ "options": "HR-LAP-.YYYY.-",
+ "print_hide": 1,
+ "reqd": 1,
+ "set_only_once": 1
+ },
+ {
+ "fieldname": "employee",
+ "fieldtype": "Link",
+ "in_global_search": 1,
+ "in_standard_filter": 1,
+ "label": "Employee",
+ "options": "Employee",
+ "reqd": 1,
+ "search_index": 1
+ },
+ {
+ "fieldname": "employee_name",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "label": "Employee Name",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "leave_type",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "in_standard_filter": 1,
+ "label": "Leave Type",
+ "options": "Leave Type",
+ "reqd": 1,
+ "search_index": 1
+ },
+ {
+ "fetch_from": "employee.department",
+ "fieldname": "department",
+ "fieldtype": "Link",
+ "label": "Department",
+ "options": "Department",
+ "read_only": 1
+ },
+ {
+ "fieldname": "leave_balance",
+ "fieldtype": "Float",
+ "label": "Leave Balance Before Application",
+ "no_copy": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "section_break_5",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "from_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "From Date",
+ "reqd": 1,
+ "search_index": 1
+ },
+ {
+ "fieldname": "to_date",
+ "fieldtype": "Date",
+ "label": "To Date",
+ "reqd": 1,
+ "search_index": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "half_day",
+ "fieldtype": "Check",
+ "label": "Half Day"
+ },
+ {
+ "depends_on": "eval:doc.half_day && (doc.from_date != doc.to_date)",
+ "fieldname": "half_day_date",
+ "fieldtype": "Date",
+ "label": "Half Day Date"
+ },
+ {
+ "fieldname": "total_leave_days",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Total Leave Days",
+ "no_copy": 1,
+ "precision": "1",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break1",
+ "fieldtype": "Column Break",
+ "print_width": "50%",
+ "width": "50%"
+ },
+ {
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Reason"
+ },
+ {
+ "fieldname": "section_break_7",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "leave_approver",
+ "fieldtype": "Link",
+ "label": "Leave Approver",
+ "options": "User"
+ },
+ {
+ "fieldname": "leave_approver_name",
+ "fieldtype": "Data",
+ "label": "Leave Approver Name",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_18",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "Open",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "in_standard_filter": 1,
+ "label": "Status",
+ "no_copy": 1,
+ "options": "Open\nApproved\nRejected\nCancelled"
+ },
+ {
+ "fieldname": "sb10",
+ "fieldtype": "Section Break"
+ },
+ {
+ "default": "Today",
+ "fieldname": "posting_date",
+ "fieldtype": "Date",
+ "label": "Posting Date",
+ "no_copy": 1,
+ "reqd": 1
+ },
+ {
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "options": "Company",
+ "remember_last_selected_value": 1,
+ "reqd": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "default": "1",
+ "fieldname": "follow_via_email",
+ "fieldtype": "Check",
+ "label": "Follow via Email",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "column_break_17",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "salary_slip",
+ "fieldtype": "Link",
+ "label": "Salary Slip",
+ "options": "Salary Slip",
+ "print_hide": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "letter_head",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Letter Head",
+ "options": "Letter Head",
+ "print_hide": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "color",
+ "fieldtype": "Color",
+ "label": "Color",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Leave Application",
+ "print_hide": 1,
+ "read_only": 1
+ }
+ ],
+ "icon": "fa fa-calendar",
+ "idx": 1,
+ "is_submittable": 1,
+ "max_attachments": 3,
+ "modified": "2019-08-13 13:32:04.860848",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Leave Application",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Employee",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR Manager",
+ "set_user_permissions": 1,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "permlevel": 1,
+ "read": 1,
+ "role": "All"
+ },
+ {
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR User",
+ "set_user_permissions": 1,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "cancel": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Leave Approver",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "permlevel": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR User",
+ "write": 1
+ },
+ {
+ "permlevel": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Leave Approver",
+ "write": 1
+ }
+ ],
+ "search_fields": "employee,employee_name,leave_type,from_date,to_date,total_leave_days",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "timeline_field": "employee",
+ "title_field": "employee_name"
+ }
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 1ef8ee0..d4da9c1 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -5,11 +5,12 @@
import frappe
from frappe import _
from frappe.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_link_to_form, \
- comma_or, get_fullname, add_days, nowdate
+ comma_or, get_fullname, add_days, nowdate, get_datetime_str
from erpnext.hr.utils import set_employee_name, get_leave_period
from erpnext.hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import daterange
+from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import create_leave_ledger_entry
class LeaveDayBlockedError(frappe.ValidationError): pass
class OverlapError(frappe.ValidationError): pass
@@ -50,6 +51,7 @@
# notify leave applier about approval
self.notify_employee()
+ self.create_leave_ledger_entry()
self.reload()
def on_cancel(self):
@@ -57,6 +59,7 @@
# notify leave applier about cancellation
self.notify_employee()
self.cancel_attendance()
+ self.create_leave_ledger_entry(submit=False)
def validate_applicable_after(self):
if self.leave_type:
@@ -193,9 +196,9 @@
frappe.throw(_("The day(s) on which you are applying for leave are holidays. You need not apply for leave."))
if not is_lwp(self.leave_type):
- self.leave_balance = get_leave_balance_on(self.employee, self.leave_type, self.from_date, docname=self.name,
+ self.leave_balance = get_leave_balance_on(self.employee, self.leave_type, self.from_date, self.to_date,
consider_all_leaves_in_the_allocation_period=True)
- if self.status != "Rejected" and self.leave_balance < self.total_leave_days:
+ if self.status != "Rejected" and (self.leave_balance < self.total_leave_days or not self.leave_balance):
if frappe.db.get_value("Leave Type", self.leave_type, "allow_negative"):
frappe.msgprint(_("Note: There is not enough leave balance for Leave Type {0}")
.format(self.leave_type))
@@ -347,6 +350,54 @@
except frappe.OutgoingEmailError:
pass
+ def create_leave_ledger_entry(self, submit=True):
+ expiry_date = get_allocation_expiry(self.employee, self.leave_type,
+ self.to_date, self.from_date)
+
+ lwp = frappe.db.get_value("Leave Type", self.leave_type, "is_lwp")
+
+ if expiry_date:
+ self.create_ledger_entry_for_intermediate_allocation_expiry(expiry_date, submit, lwp)
+ else:
+ args = dict(
+ leaves=self.total_leave_days * -1,
+ from_date=self.from_date,
+ to_date=self.to_date,
+ is_lwp=lwp
+ )
+ create_leave_ledger_entry(self, args, submit)
+
+ def create_ledger_entry_for_intermediate_allocation_expiry(self, expiry_date, submit, lwp):
+ ''' splits leave application into two ledger entries to consider expiry of allocation '''
+ args = dict(
+ from_date=self.from_date,
+ to_date=expiry_date,
+ leaves=(date_diff(expiry_date, self.from_date) + 1) * -1,
+ is_lwp=lwp
+ )
+ create_leave_ledger_entry(self, args, submit)
+
+ if getdate(expiry_date) != getdate(self.to_date):
+ start_date = add_days(expiry_date, 1)
+ args.update(dict(
+ from_date=start_date,
+ to_date=self.to_date,
+ leaves=date_diff(self.to_date, expiry_date) * -1
+ ))
+ create_leave_ledger_entry(self, args, submit)
+
+def get_allocation_expiry(employee, leave_type, to_date, from_date):
+ ''' Returns expiry of carry forward allocation in leave ledger entry '''
+ expiry = frappe.get_all("Leave Ledger Entry",
+ filters={
+ 'employee': employee,
+ 'leave_type': leave_type,
+ 'is_carry_forward': 1,
+ 'transaction_type': 'Leave Allocation',
+ 'to_date': ['between', (from_date, to_date)]
+ },fields=['to_date'])
+ return expiry[0]['to_date'] if expiry else None
+
@frappe.whitelist()
def get_number_of_leave_days(employee, leave_type, from_date, to_date, half_day = None, half_day_date = None):
number_of_days = 0
@@ -364,14 +415,16 @@
@frappe.whitelist()
def get_leave_details(employee, date):
- allocation_records = get_leave_allocation_records(date, employee).get(employee, frappe._dict())
+ allocation_records = get_leave_allocation_records(employee, date)
leave_allocation = {}
for d in allocation_records:
allocation = allocation_records.get(d, frappe._dict())
- date = allocation.to_date
- leaves_taken = get_leaves_for_period(employee, d, allocation.from_date, date, status="Approved")
- leaves_pending = get_leaves_for_period(employee, d, allocation.from_date, date, status="Open")
- remaining_leaves = allocation.total_leaves_allocated - leaves_taken - leaves_pending
+ remaining_leaves = get_leave_balance_on(employee, d, date, to_date = allocation.to_date,
+ consider_all_leaves_in_the_allocation_period=True)
+ end_date = allocation.to_date
+ leaves_taken = get_leaves_for_period(employee, d, allocation.from_date, end_date) * -1
+ leaves_pending = get_pending_leaves_for_period(employee, d, allocation.from_date, end_date)
+
leave_allocation[d] = {
"total_leaves": allocation.total_leaves_allocated,
"leaves_taken": leaves_taken,
@@ -386,27 +439,131 @@
return ret
@frappe.whitelist()
-def get_leave_balance_on(employee, leave_type, date, allocation_records=None, docname=None,
- consider_all_leaves_in_the_allocation_period=False, consider_encashed_leaves=True):
+def get_leave_balance_on(employee, leave_type, date, to_date=nowdate(), consider_all_leaves_in_the_allocation_period=False):
+ '''
+ Returns leave balance till date
+ :param employee: employee name
+ :param leave_type: leave type
+ :param date: date to check balance on
+ :param to_date: future date to check for allocation expiry
+ :param consider_all_leaves_in_the_allocation_period: consider all leaves taken till the allocation end date
+ '''
- if allocation_records == None:
- allocation_records = get_leave_allocation_records(date, employee).get(employee, frappe._dict())
+ allocation_records = get_leave_allocation_records(employee, date, leave_type)
allocation = allocation_records.get(leave_type, frappe._dict())
- if consider_all_leaves_in_the_allocation_period:
- date = allocation.to_date
- leaves_taken = get_leaves_for_period(employee, leave_type, allocation.from_date, date, status="Approved", docname=docname)
- leaves_encashed = 0
- if frappe.db.get_value("Leave Type", leave_type, 'allow_encashment') and consider_encashed_leaves:
- leaves_encashed = flt(allocation.total_leaves_encashed)
- return flt(allocation.total_leaves_allocated) - (flt(leaves_taken) + flt(leaves_encashed))
+ end_date = allocation.to_date if consider_all_leaves_in_the_allocation_period else date
+ expiry = get_allocation_expiry(employee, leave_type, to_date, date)
-def get_leaves_for_period(employee, leave_type, from_date, to_date, status, docname=None):
- leave_applications = frappe.db.sql("""
- select name, employee, leave_type, from_date, to_date, total_leave_days
- from `tabLeave Application`
+ leaves_taken = get_leaves_for_period(employee, leave_type, allocation.from_date, end_date)
+
+ return get_remaining_leaves(allocation, leaves_taken, date, expiry)
+
+def get_leave_allocation_records(employee, date, leave_type=None):
+ ''' returns the total allocated leaves and carry forwarded leaves based on ledger entries '''
+
+ conditions = ("and leave_type='%s'" % leave_type) if leave_type else ""
+ allocation_details = frappe.db.sql("""
+ SELECT
+ SUM(CASE WHEN is_carry_forward = 1 THEN leaves ELSE 0 END) as cf_leaves,
+ SUM(CASE WHEN is_carry_forward = 0 THEN leaves ELSE 0 END) as new_leaves,
+ MIN(from_date) as from_date,
+ MAX(to_date) as to_date,
+ leave_type
+ FROM `tabLeave Ledger Entry`
+ WHERE
+ from_date <= %(date)s
+ AND to_date >= %(date)s
+ AND docstatus=1
+ AND transaction_type="Leave Allocation"
+ AND employee=%(employee)s
+ AND is_expired=0
+ AND is_lwp=0
+ {0}
+ GROUP BY employee, leave_type
+ """.format(conditions), dict(date=date, employee=employee), as_dict=1) #nosec
+
+ allocated_leaves = frappe._dict()
+ for d in allocation_details:
+ allocated_leaves.setdefault(d.leave_type, frappe._dict({
+ "from_date": d.from_date,
+ "to_date": d.to_date,
+ "total_leaves_allocated": flt(d.cf_leaves) + flt(d.new_leaves),
+ "unused_leaves": d.cf_leaves,
+ "new_leaves_allocated": d.new_leaves,
+ "leave_type": d.leave_type
+ }))
+ return allocated_leaves
+
+def get_pending_leaves_for_period(employee, leave_type, from_date, to_date):
+ ''' Returns leaves that are pending approval '''
+ return frappe.db.get_value("Leave Application",
+ filters={
+ "employee": employee,
+ "leave_type": leave_type,
+ "from_date": ("<=", from_date),
+ "to_date": (">=", to_date),
+ "status": "Open"
+ }, fieldname=['SUM(total_leave_days)']) or flt(0)
+
+def get_remaining_leaves(allocation, leaves_taken, date, expiry):
+ ''' Returns minimum leaves remaining after comparing with remaining days for allocation expiry '''
+ def _get_remaining_leaves(allocated_leaves, end_date):
+ remaining_leaves = flt(allocated_leaves) + flt(leaves_taken)
+
+ if remaining_leaves > 0:
+ remaining_days = date_diff(end_date, date) + 1
+ remaining_leaves = min(remaining_days, remaining_leaves)
+
+ return remaining_leaves
+
+ total_leaves = allocation.total_leaves_allocated
+
+ if expiry and allocation.unused_leaves:
+ remaining_leaves = _get_remaining_leaves(allocation.unused_leaves, expiry)
+
+ total_leaves = flt(allocation.new_leaves_allocated) + flt(remaining_leaves)
+
+ return _get_remaining_leaves(total_leaves, allocation.to_date)
+
+def get_leaves_for_period(employee, leave_type, from_date, to_date):
+ leave_entries = get_leave_entries(employee, leave_type, from_date, to_date)
+ leave_days = 0
+
+ for leave_entry in leave_entries:
+ inclusive_period = leave_entry.from_date >= getdate(from_date) and leave_entry.to_date <= getdate(to_date)
+
+ if inclusive_period and leave_entry.transaction_type == 'Leave Encashment':
+ leave_days += leave_entry.leaves
+
+ elif inclusive_period and leave_entry.transaction_type == 'Leave Allocation' \
+ and not skip_expiry_leaves(leave_entry, to_date):
+ leave_days += leave_entry.leaves
+
+ else:
+ if leave_entry.from_date < getdate(from_date):
+ leave_entry.from_date = from_date
+ if leave_entry.to_date > getdate(to_date):
+ leave_entry.to_date = to_date
+
+ leave_days += get_number_of_leave_days(employee, leave_type,
+ leave_entry.from_date, leave_entry.to_date) * -1
+
+ return leave_days
+
+def skip_expiry_leaves(leave_entry, date):
+ ''' Checks whether the expired leaves coincide with the to_date of leave balance check '''
+ end_date = frappe.db.get_value("Leave Allocation", {'name': leave_entry.transaction_name}, ['to_date'])
+ return True if end_date == date and not leave_entry.is_carry_forward else False
+
+def get_leave_entries(employee, leave_type, from_date, to_date):
+ ''' Returns leave entries between from_date and to_date '''
+ return frappe.db.sql("""
+ select employee, leave_type, from_date, to_date, leaves, transaction_type, is_carry_forward
+ from `tabLeave Ledger Entry`
where employee=%(employee)s and leave_type=%(leave_type)s
- and status = %(status)s and docstatus != 2
+ and docstatus=1
+ and leaves<0
and (from_date between %(from_date)s and %(to_date)s
or to_date between %(from_date)s and %(to_date)s
or (from_date < %(from_date)s and to_date > %(to_date)s))
@@ -414,43 +571,8 @@
"from_date": from_date,
"to_date": to_date,
"employee": employee,
- "status": status,
"leave_type": leave_type
}, as_dict=1)
- leave_days = 0
- for leave_app in leave_applications:
- if docname and leave_app.name == docname:
- continue
- if leave_app.from_date >= getdate(from_date) and leave_app.to_date <= getdate(to_date):
- leave_days += leave_app.total_leave_days
- else:
- if leave_app.from_date < getdate(from_date):
- leave_app.from_date = from_date
- if leave_app.to_date > getdate(to_date):
- leave_app.to_date = to_date
-
- leave_days += get_number_of_leave_days(employee, leave_type,
- leave_app.from_date, leave_app.to_date)
-
- return leave_days
-
-def get_leave_allocation_records(date, employee=None):
- conditions = (" and employee='%s'" % employee) if employee else ""
-
- leave_allocation_records = frappe.db.sql("""
- select employee, leave_type, total_leaves_allocated, total_leaves_encashed, from_date, to_date
- from `tabLeave Allocation`
- where %s between from_date and to_date and docstatus=1 {0}""".format(conditions), (date), as_dict=1)
-
- allocated_leaves = frappe._dict()
- for d in leave_allocation_records:
- allocated_leaves.setdefault(d.employee, frappe._dict()).setdefault(d.leave_type, frappe._dict({
- "from_date": d.from_date,
- "to_date": d.to_date,
- "total_leaves_allocated": d.total_leaves_allocated,
- "total_leaves_encashed":d.total_leaves_encashed
- }))
- return allocated_leaves
@frappe.whitelist()
def get_holidays(employee, from_date, to_date):
@@ -623,10 +745,12 @@
return leave_days
@frappe.whitelist()
-def get_leave_approver(employee, department=None):
- if not department:
- department = frappe.db.get_value('Employee', employee, 'department')
+def get_leave_approver(employee):
+ leave_approver, department = frappe.db.get_value("Employee",
+ employee, ["leave_approver", "department"])
- if department:
- return frappe.db.get_value('Department Approver', {'parent': department,
+ if not leave_approver and department:
+ leave_approver = frappe.db.get_value('Department Approver', {'parent': department,
'parentfield': 'leave_approvers', 'idx': 1}, 'approver')
+
+ return leave_approver
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_application/leave_application_dashboard.py b/erpnext/hr/doctype/leave_application/leave_application_dashboard.py
new file mode 100644
index 0000000..8075b7b
--- /dev/null
+++ b/erpnext/hr/doctype/leave_application/leave_application_dashboard.py
@@ -0,0 +1,14 @@
+from __future__ import unicode_literals
+
+from frappe import _
+
+
+def get_data():
+ return {
+ 'reports': [
+ {
+ 'label': _('Reports'),
+ 'items': ['Employee Leave Balance']
+ }
+ ]
+ }
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_application/leave_application_list.js b/erpnext/hr/doctype/leave_application/leave_application_list.js
index f69b182..cbb4b73 100644
--- a/erpnext/hr/doctype/leave_application/leave_application_list.js
+++ b/erpnext/hr/doctype/leave_application/leave_application_list.js
@@ -5,6 +5,8 @@
return [__("Approved"), "green", "status,=,Approved"];
} else if (doc.status === "Rejected") {
return [__("Rejected"), "red", "status,=,Rejected"];
+ } else {
+ return [__("Open"), "red", "status,=,Open"];
}
}
};
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py
index d3dcca1..ad141a5 100644
--- a/erpnext/hr/doctype/leave_application/test_leave_application.py
+++ b/erpnext/hr/doctype/leave_application/test_leave_application.py
@@ -7,7 +7,9 @@
from erpnext.hr.doctype.leave_application.leave_application import LeaveDayBlockedError, OverlapError, NotAnOptionalHoliday, get_leave_balance_on
from frappe.permissions import clear_user_permissions_for_doctype
-from frappe.utils import add_days, nowdate, now_datetime, getdate
+from frappe.utils import add_days, nowdate, now_datetime, getdate, add_months
+from erpnext.hr.doctype.leave_type.test_leave_type import create_leave_type
+from erpnext.hr.doctype.leave_allocation.test_leave_allocation import create_leave_allocation
test_dependencies = ["Leave Allocation", "Leave Block List"]
@@ -17,6 +19,7 @@
"doctype": "Leave Application",
"employee": "_T-Employee-00001",
"from_date": "2013-05-01",
+ "description": "_Test Reason",
"leave_type": "_Test Leave Type",
"posting_date": "2013-01-02",
"to_date": "2013-05-05"
@@ -26,6 +29,7 @@
"doctype": "Leave Application",
"employee": "_T-Employee-00002",
"from_date": "2013-05-01",
+ "description": "_Test Reason",
"leave_type": "_Test Leave Type",
"posting_date": "2013-01-02",
"to_date": "2013-05-05"
@@ -35,6 +39,7 @@
"doctype": "Leave Application",
"employee": "_T-Employee-00001",
"from_date": "2013-01-15",
+ "description": "_Test Reason",
"leave_type": "_Test Leave Type LWP",
"posting_date": "2013-01-02",
"to_date": "2013-01-15"
@@ -44,8 +49,8 @@
class TestLeaveApplication(unittest.TestCase):
def setUp(self):
- for dt in ["Leave Application", "Leave Allocation", "Salary Slip"]:
- frappe.db.sql("delete from `tab%s`" % dt)
+ for dt in ["Leave Application", "Leave Allocation", "Salary Slip", "Leave Ledger Entry"]:
+ frappe.db.sql("DELETE FROM `tab%s`" % dt) #nosec
@classmethod
def setUpClass(cls):
@@ -268,13 +273,14 @@
doctype = 'Leave Application',
employee = employee.name,
company = '_Test Company',
+ description = "_Test Reason",
leave_type = leave_type,
from_date = date,
to_date = date,
))
# can only apply on optional holidays
- self.assertTrue(NotAnOptionalHoliday, leave_application.insert)
+ self.assertRaises(NotAnOptionalHoliday, leave_application.insert)
leave_application.from_date = today
leave_application.to_date = today
@@ -285,7 +291,6 @@
# check leave balance is reduced
self.assertEqual(get_leave_balance_on(employee.name, leave_type, today), 9)
-
def test_leaves_allowed(self):
employee = get_employee()
leave_period = get_leave_period()
@@ -301,24 +306,25 @@
allocate_leaves(employee, leave_period, leave_type.name, 5)
leave_application = frappe.get_doc(dict(
- doctype = 'Leave Application',
+ doctype = 'Leave Application',
employee = employee.name,
leave_type = leave_type.name,
+ description = "_Test Reason",
from_date = date,
to_date = add_days(date, 2),
company = "_Test Company",
docstatus = 1,
status = "Approved"
))
-
- self.assertTrue(leave_application.insert())
+ leave_application.submit()
leave_application = frappe.get_doc(dict(
doctype = 'Leave Application',
employee = employee.name,
leave_type = leave_type.name,
+ description = "_Test Reason",
from_date = add_days(date, 4),
- to_date = add_days(date, 7),
+ to_date = add_days(date, 8),
company = "_Test Company",
docstatus = 1,
status = "Approved"
@@ -342,6 +348,7 @@
doctype = 'Leave Application',
employee = employee.name,
leave_type = leave_type.name,
+ description = "_Test Reason",
from_date = date,
to_date = add_days(date, 4),
company = "_Test Company",
@@ -363,6 +370,7 @@
doctype = 'Leave Application',
employee = employee.name,
leave_type = leave_type_1.name,
+ description = "_Test Reason",
from_date = date,
to_date = add_days(date, 4),
company = "_Test Company",
@@ -392,6 +400,7 @@
doctype = 'Leave Application',
employee = employee.name,
leave_type = leave_type.name,
+ description = "_Test Reason",
from_date = date,
to_date = add_days(date, 4),
company = "_Test Company",
@@ -401,6 +410,18 @@
self.assertRaises(frappe.ValidationError, leave_application.insert)
+ def test_leave_balance_near_allocaton_expiry(self):
+ employee = get_employee()
+ leave_type = create_leave_type(
+ leave_type_name="_Test_CF_leave_expiry",
+ is_carry_forward=1,
+ expire_carry_forwarded_leaves_after_days=90)
+ leave_type.submit()
+
+ create_carry_forwarded_allocation(employee, leave_type)
+
+ self.assertEqual(get_leave_balance_on(employee.name, leave_type.name, nowdate(), add_days(nowdate(), 8)), 21)
+
def test_earned_leave(self):
leave_period = get_leave_period()
employee = get_employee()
@@ -444,9 +465,10 @@
allocation.insert(ignore_permissions=True)
allocation.submit()
leave_application = frappe.get_doc(dict(
- doctype = 'Leave Application',
+ doctype = 'Leave Application',
employee = employee.name,
leave_type = leave_type,
+ description = "_Test Reason",
from_date = '2018-10-02',
to_date = '2018-10-02',
company = '_Test Company',
@@ -457,9 +479,103 @@
leave_application.submit()
self.assertEqual(leave_application.docstatus, 1)
-def make_allocation_record(employee=None, leave_type=None):
- frappe.db.sql("delete from `tabLeave Allocation`")
+ def test_creation_of_leave_ledger_entry_on_submit(self):
+ employee = get_employee()
+ leave_type = create_leave_type(leave_type_name = 'Test Leave Type 1')
+ leave_type.save()
+
+ leave_allocation = create_leave_allocation(employee=employee.name, employee_name=employee.employee_name,
+ leave_type=leave_type.name)
+ leave_allocation.submit()
+
+ leave_application = frappe.get_doc(dict(
+ doctype = 'Leave Application',
+ employee = employee.name,
+ leave_type = leave_type.name,
+ from_date = add_days(nowdate(), 1),
+ to_date = add_days(nowdate(), 4),
+ description = "_Test Reason",
+ company = "_Test Company",
+ docstatus = 1,
+ status = "Approved"
+ ))
+ leave_application.submit()
+ leave_ledger_entry = frappe.get_all('Leave Ledger Entry', fields='*', filters=dict(transaction_name=leave_application.name))
+
+ self.assertEquals(leave_ledger_entry[0].employee, leave_application.employee)
+ self.assertEquals(leave_ledger_entry[0].leave_type, leave_application.leave_type)
+ self.assertEquals(leave_ledger_entry[0].leaves, leave_application.total_leave_days * -1)
+
+ # check if leave ledger entry is deleted on cancellation
+ leave_application.cancel()
+ self.assertFalse(frappe.db.exists("Leave Ledger Entry", {'transaction_name':leave_application.name}))
+
+ def test_ledger_entry_creation_on_intermediate_allocation_expiry(self):
+ employee = get_employee()
+ leave_type = create_leave_type(
+ leave_type_name="_Test_CF_leave_expiry",
+ is_carry_forward=1,
+ expire_carry_forwarded_leaves_after_days=90)
+ leave_type.submit()
+
+ create_carry_forwarded_allocation(employee, leave_type)
+
+ leave_application = frappe.get_doc(dict(
+ doctype = 'Leave Application',
+ employee = employee.name,
+ leave_type = leave_type.name,
+ from_date = add_days(nowdate(), -3),
+ to_date = add_days(nowdate(), 7),
+ description = "_Test Reason",
+ company = "_Test Company",
+ docstatus = 1,
+ status = "Approved"
+ ))
+ leave_application.submit()
+
+ leave_ledger_entry = frappe.get_all('Leave Ledger Entry', '*', filters=dict(transaction_name=leave_application.name))
+
+ self.assertEquals(len(leave_ledger_entry), 2)
+ self.assertEquals(leave_ledger_entry[0].employee, leave_application.employee)
+ self.assertEquals(leave_ledger_entry[0].leave_type, leave_application.leave_type)
+ self.assertEquals(leave_ledger_entry[0].leaves, -9)
+ self.assertEquals(leave_ledger_entry[1].leaves, -2)
+
+ def test_leave_application_creation_after_expiry(self):
+ # test leave balance for carry forwarded allocation
+ employee = get_employee()
+ leave_type = create_leave_type(
+ leave_type_name="_Test_CF_leave_expiry",
+ is_carry_forward=1,
+ expire_carry_forwarded_leaves_after_days=90)
+ leave_type.submit()
+
+ create_carry_forwarded_allocation(employee, leave_type)
+
+ self.assertEquals(get_leave_balance_on(employee.name, leave_type.name, add_days(nowdate(), -85), add_days(nowdate(), -84)), 0)
+
+def create_carry_forwarded_allocation(employee, leave_type):
+ # initial leave allocation
+ leave_allocation = create_leave_allocation(
+ leave_type="_Test_CF_leave_expiry",
+ employee=employee.name,
+ employee_name=employee.employee_name,
+ from_date=add_months(nowdate(), -24),
+ to_date=add_months(nowdate(), -12),
+ carry_forward=0)
+ leave_allocation.submit()
+
+ leave_allocation = create_leave_allocation(
+ leave_type="_Test_CF_leave_expiry",
+ employee=employee.name,
+ employee_name=employee.employee_name,
+ from_date=add_days(nowdate(), -84),
+ to_date=add_days(nowdate(), 100),
+ carry_forward=1)
+ leave_allocation.submit()
+
+def make_allocation_record(employee=None, leave_type=None):
allocation = frappe.get_doc({
"doctype": "Leave Allocation",
"employee": employee or "_T-Employee-00001",
@@ -513,4 +629,4 @@
"docstatus": 1
}).insert()
- allocate_leave.submit()
+ allocate_leave.submit()
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.py b/erpnext/hr/doctype/leave_encashment/leave_encashment.py
index 9944bc5..42f0179 100644
--- a/erpnext/hr/doctype/leave_encashment/leave_encashment.py
+++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.py
@@ -10,6 +10,8 @@
from erpnext.hr.utils import set_employee_name
from erpnext.hr.doctype.leave_application.leave_application import get_leave_balance_on
from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure
+from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import create_leave_ledger_entry
+from erpnext.hr.doctype.leave_allocation.leave_allocation import get_unused_leaves
class LeaveEncashment(Document):
def validate(self):
@@ -25,7 +27,7 @@
def on_submit(self):
if not self.leave_allocation:
- self.leave_allocation = self.get_leave_allocation()
+ self.leave_allocation = self.get_leave_allocation().get('name')
additional_salary = frappe.new_doc("Additional Salary")
additional_salary.company = frappe.get_value("Employee", self.employee, "company")
additional_salary.employee = self.employee
@@ -40,6 +42,8 @@
frappe.db.set_value("Leave Allocation", self.leave_allocation, "total_leaves_encashed",
frappe.db.get_value('Leave Allocation', self.leave_allocation, 'total_leaves_encashed') + self.encashable_days)
+ self.create_leave_ledger_entry()
+
def on_cancel(self):
if self.additional_salary:
frappe.get_doc("Additional Salary", self.additional_salary).cancel()
@@ -48,6 +52,7 @@
if self.leave_allocation:
frappe.db.set_value("Leave Allocation", self.leave_allocation, "total_leaves_encashed",
frappe.db.get_value('Leave Allocation', self.leave_allocation, 'total_leaves_encashed') - self.encashable_days)
+ self.create_leave_ledger_entry(submit=False)
def get_leave_details_for_encashment(self):
salary_structure = get_assigned_salary_structure(self.employee, self.encashment_date or getdate(nowdate()))
@@ -57,8 +62,10 @@
if not frappe.db.get_value("Leave Type", self.leave_type, 'allow_encashment'):
frappe.throw(_("Leave Type {0} is not encashable").format(self.leave_type))
- self.leave_balance = get_leave_balance_on(self.employee, self.leave_type,
- self.encashment_date or getdate(nowdate()), consider_all_leaves_in_the_allocation_period=True)
+ allocation = self.get_leave_allocation()
+
+ self.leave_balance = allocation.total_leaves_allocated - allocation.carry_forwarded_leaves_count\
+ - get_unused_leaves(self.employee, self.leave_type, allocation.from_date, self.encashment_date)
encashable_days = self.leave_balance - frappe.db.get_value('Leave Type', self.leave_type, 'encashment_threshold_days')
self.encashable_days = encashable_days if encashable_days > 0 else 0
@@ -66,12 +73,47 @@
per_day_encashment = frappe.db.get_value('Salary Structure', salary_structure , 'leave_encashment_amount_per_day')
self.encashment_amount = self.encashable_days * per_day_encashment if per_day_encashment > 0 else 0
- self.leave_allocation = self.get_leave_allocation()
+ self.leave_allocation = allocation.name
return True
def get_leave_allocation(self):
- leave_allocation = frappe.db.sql("""select name from `tabLeave Allocation` where '{0}'
+ leave_allocation = frappe.db.sql("""select name, to_date, total_leaves_allocated, carry_forwarded_leaves_count from `tabLeave Allocation` where '{0}'
between from_date and to_date and docstatus=1 and leave_type='{1}'
- and employee= '{2}'""".format(self.encashment_date or getdate(nowdate()), self.leave_type, self.employee))
+ and employee= '{2}'""".format(self.encashment_date or getdate(nowdate()), self.leave_type, self.employee), as_dict=1) #nosec
- return leave_allocation[0][0] if leave_allocation else None
+ return leave_allocation[0] if leave_allocation else None
+
+ def create_leave_ledger_entry(self, submit=True):
+ args = frappe._dict(
+ leaves=self.encashable_days * -1,
+ from_date=self.encashment_date,
+ to_date=self.encashment_date,
+ is_carry_forward=0
+ )
+ create_leave_ledger_entry(self, args, submit)
+
+ # create reverse entry for expired leaves
+ to_date = self.get_leave_allocation().get('to_date')
+ if to_date < getdate(nowdate()):
+ args = frappe._dict(
+ leaves=self.encashable_days,
+ from_date=to_date,
+ to_date=to_date,
+ is_carry_forward=0
+ )
+ create_leave_ledger_entry(self, args, submit)
+
+
+def create_leave_encashment(leave_allocation):
+ ''' Creates leave encashment for the given allocations '''
+ for allocation in leave_allocation:
+ if not get_assigned_salary_structure(allocation.employee, allocation.to_date):
+ continue
+ leave_encashment = frappe.get_doc(dict(
+ doctype="Leave Encashment",
+ leave_period=allocation.leave_period,
+ employee=allocation.employee,
+ leave_type=allocation.leave_type,
+ encashment_date=allocation.to_date
+ ))
+ leave_encashment.insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
index ef5c2aa..e5bd170 100644
--- a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
+++ b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
@@ -9,42 +9,43 @@
from erpnext.hr.doctype.employee.test_employee import make_employee
from erpnext.hr.doctype.salary_structure.test_salary_structure import make_salary_structure
from erpnext.hr.doctype.leave_period.test_leave_period import create_leave_period
+from erpnext.hr.doctype.leave_policy.test_leave_policy import create_leave_policy\
test_dependencies = ["Leave Type"]
class TestLeaveEncashment(unittest.TestCase):
def setUp(self):
frappe.db.sql('''delete from `tabLeave Period`''')
- def test_leave_balance_value_and_amount(self):
- employee = "test_employee_encashment@salary.com"
- leave_type = "_Test Leave Type Encashment"
+ frappe.db.sql('''delete from `tabLeave Allocation`''')
+ frappe.db.sql('''delete from `tabLeave Ledger Entry`''')
+ frappe.db.sql('''delete from `tabAdditional Salary`''')
# create the leave policy
- leave_policy = frappe.get_doc({
- "doctype": "Leave Policy",
- "leave_policy_details": [{
- "leave_type": leave_type,
- "annual_allocation": 10
- }]
- }).insert()
+ leave_policy = create_leave_policy(
+ leave_type="_Test Leave Type Encashment",
+ annual_allocation=10)
leave_policy.submit()
# create employee, salary structure and assignment
- employee = make_employee(employee)
- frappe.db.set_value("Employee", employee, "leave_policy", leave_policy.name)
- salary_structure = make_salary_structure("Salary Structure for Encashment", "Monthly", employee,
+ self.employee = make_employee("test_employee_encashment@example.com")
+
+ frappe.db.set_value("Employee", self.employee, "leave_policy", leave_policy.name)
+
+ salary_structure = make_salary_structure("Salary Structure for Encashment", "Monthly", self.employee,
other_details={"leave_encashment_amount_per_day": 50})
# create the leave period and assign the leaves
- leave_period = create_leave_period(add_months(today(), -3), add_months(today(), 3))
- leave_period.grant_leave_allocation(employee=employee)
+ self.leave_period = create_leave_period(add_months(today(), -3), add_months(today(), 3))
+ self.leave_period.grant_leave_allocation(employee=self.employee)
+ def test_leave_balance_value_and_amount(self):
+ frappe.db.sql('''delete from `tabLeave Encashment`''')
leave_encashment = frappe.get_doc(dict(
- doctype = 'Leave Encashment',
- employee = employee,
- leave_type = leave_type,
- leave_period = leave_period.name,
- payroll_date = today()
+ doctype='Leave Encashment',
+ employee=self.employee,
+ leave_type="_Test Leave Type Encashment",
+ leave_period=self.leave_period.name,
+ payroll_date=today()
)).insert()
self.assertEqual(leave_encashment.leave_balance, 10)
@@ -53,3 +54,26 @@
leave_encashment.submit()
self.assertTrue(frappe.db.get_value("Leave Encashment", leave_encashment.name, "additional_salary"))
+
+ def test_creation_of_leave_ledger_entry_on_submit(self):
+ frappe.db.sql('''delete from `tabLeave Encashment`''')
+ leave_encashment = frappe.get_doc(dict(
+ doctype='Leave Encashment',
+ employee=self.employee,
+ leave_type="_Test Leave Type Encashment",
+ leave_period=self.leave_period.name,
+ payroll_date=today()
+ )).insert()
+
+ leave_encashment.submit()
+
+ leave_ledger_entry = frappe.get_all('Leave Ledger Entry', fields='*', filters=dict(transaction_name=leave_encashment.name))
+
+ self.assertEquals(len(leave_ledger_entry), 1)
+ self.assertEquals(leave_ledger_entry[0].employee, leave_encashment.employee)
+ self.assertEquals(leave_ledger_entry[0].leave_type, leave_encashment.leave_type)
+ self.assertEquals(leave_ledger_entry[0].leaves, leave_encashment.encashable_days * -1)
+
+ # check if leave ledger entry is deleted on cancellation
+ leave_encashment.cancel()
+ self.assertFalse(frappe.db.exists("Leave Ledger Entry", {'transaction_name':leave_encashment.name}))
diff --git a/erpnext/hr/doctype/leave_ledger_entry/__init__.py b/erpnext/hr/doctype/leave_ledger_entry/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/doctype/leave_ledger_entry/__init__.py
diff --git a/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.js b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.js
new file mode 100644
index 0000000..c68d518
--- /dev/null
+++ b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Leave Ledger Entry', {
+ // refresh: function(frm) {
+
+ // }
+});
diff --git a/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.json b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.json
new file mode 100644
index 0000000..771e706
--- /dev/null
+++ b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.json
@@ -0,0 +1,169 @@
+{
+ "creation": "2019-05-09 15:47:39.760406",
+ "doctype": "DocType",
+ "engine": "InnoDB",
+ "field_order": [
+ "employee",
+ "employee_name",
+ "leave_type",
+ "transaction_type",
+ "transaction_name",
+ "leaves",
+ "column_break_7",
+ "from_date",
+ "to_date",
+ "is_carry_forward",
+ "is_expired",
+ "is_lwp",
+ "amended_from"
+ ],
+ "fields": [
+ {
+ "fieldname": "employee",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Employee",
+ "options": "Employee"
+ },
+ {
+ "fetch_from": "employee.employee_name",
+ "fieldname": "employee_name",
+ "fieldtype": "Data",
+ "label": "Employee Name"
+ },
+ {
+ "fieldname": "leave_type",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Leave Type",
+ "options": "Leave Type"
+ },
+ {
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Leave Ledger Entry",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "transaction_type",
+ "fieldtype": "Link",
+ "label": "Transaction Type",
+ "options": "DocType"
+ },
+ {
+ "fieldname": "transaction_name",
+ "fieldtype": "Dynamic Link",
+ "label": "Transaction Name",
+ "options": "transaction_type"
+ },
+ {
+ "fieldname": "leaves",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Leaves"
+ },
+ {
+ "fieldname": "from_date",
+ "fieldtype": "Date",
+ "label": "From Date"
+ },
+ {
+ "fieldname": "to_date",
+ "fieldtype": "Date",
+ "label": "To Date"
+ },
+ {
+ "default": "0",
+ "fieldname": "is_carry_forward",
+ "fieldtype": "Check",
+ "label": "Is Carry Forward"
+ },
+ {
+ "default": "0",
+ "fieldname": "is_expired",
+ "fieldtype": "Check",
+ "label": "Is Expired"
+ },
+ {
+ "fieldname": "column_break_7",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "0",
+ "fieldname": "is_lwp",
+ "fieldtype": "Check",
+ "label": "Is Leave Without Pay"
+ }
+ ],
+ "in_create": 1,
+ "is_submittable": 1,
+ "modified": "2019-08-20 14:40:04.130799",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Leave Ledger Entry",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR Manager",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR User",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "All",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ }
+ ],
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "title_field": "employee"
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.py b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.py
new file mode 100644
index 0000000..bfc6d95
--- /dev/null
+++ b/erpnext/hr/doctype/leave_ledger_entry/leave_ledger_entry.py
@@ -0,0 +1,173 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+from frappe import _
+from frappe.utils import add_days, today, flt, DATE_FORMAT, getdate
+
+class LeaveLedgerEntry(Document):
+ def validate(self):
+ if getdate(self.from_date) > getdate(self.to_date):
+ frappe.throw(_("To date needs to be before from date"))
+
+ def on_cancel(self):
+ # allow cancellation of expiry leaves
+ if self.is_expired:
+ frappe.db.set_value("Leave Allocation", self.transaction_name, "expired", 0)
+ else:
+ frappe.throw(_("Only expired allocation can be cancelled"))
+
+def validate_leave_allocation_against_leave_application(ledger):
+ ''' Checks that leave allocation has no leave application against it '''
+ leave_application_records = frappe.db.sql_list("""
+ SELECT transaction_name
+ FROM `tabLeave Ledger Entry`
+ WHERE
+ employee=%s
+ AND leave_type=%s
+ AND transaction_type='Leave Application'
+ AND from_date>=%s
+ AND to_date<=%s
+ """, (ledger.employee, ledger.leave_type, ledger.from_date, ledger.to_date))
+
+ if leave_application_records:
+ frappe.throw(_("Leave allocation %s is linked with leave application %s"
+ % (ledger.transaction_name, ', '.join(leave_application_records))))
+
+def create_leave_ledger_entry(ref_doc, args, submit=True):
+ ledger = frappe._dict(
+ doctype='Leave Ledger Entry',
+ employee=ref_doc.employee,
+ employee_name=ref_doc.employee_name,
+ leave_type=ref_doc.leave_type,
+ transaction_type=ref_doc.doctype,
+ transaction_name=ref_doc.name,
+ is_carry_forward=0,
+ is_expired=0,
+ is_lwp=0
+ )
+ ledger.update(args)
+
+ if submit:
+ frappe.get_doc(ledger).submit()
+ else:
+ delete_ledger_entry(ledger)
+
+def delete_ledger_entry(ledger):
+ ''' Delete ledger entry on cancel of leave application/allocation/encashment '''
+ if ledger.transaction_type == "Leave Allocation":
+ validate_leave_allocation_against_leave_application(ledger)
+
+ expired_entry = get_previous_expiry_ledger_entry(ledger)
+ frappe.db.sql("""DELETE
+ FROM `tabLeave Ledger Entry`
+ WHERE
+ `transaction_name`=%s
+ OR `name`=%s""", (ledger.transaction_name, expired_entry))
+
+def get_previous_expiry_ledger_entry(ledger):
+ ''' Returns the expiry ledger entry having same creation date as the ledger entry to be cancelled '''
+ creation_date = frappe.db.get_value("Leave Ledger Entry", filters={
+ 'transaction_name': ledger.transaction_name,
+ 'is_expired': 0,
+ 'transaction_type': 'Leave Allocation'
+ }, fieldname=['creation'])
+
+ creation_date = creation_date.strftime(DATE_FORMAT) if creation_date else ''
+
+ return frappe.db.get_value("Leave Ledger Entry", filters={
+ 'creation': ('like', creation_date+"%"),
+ 'employee': ledger.employee,
+ 'leave_type': ledger.leave_type,
+ 'is_expired': 1,
+ 'docstatus': 1,
+ 'is_carry_forward': 0
+ }, fieldname=['name'])
+
+def process_expired_allocation():
+ ''' Check if a carry forwarded allocation has expired and create a expiry ledger entry '''
+
+ # fetch leave type records that has carry forwarded leaves expiry
+ leave_type_records = frappe.db.get_values("Leave Type", filters={
+ 'expire_carry_forwarded_leaves_after_days': (">", 0)
+ }, fieldname=['name'])
+
+ leave_type = [record[0] for record in leave_type_records]
+
+ expired_allocation = frappe.db.sql_list("""SELECT name
+ FROM `tabLeave Ledger Entry`
+ WHERE
+ `transaction_type`='Leave Allocation'
+ AND `is_expired`=1""")
+
+ expire_allocation = frappe.get_all("Leave Ledger Entry",
+ fields=['leaves', 'to_date', 'employee', 'leave_type', 'is_carry_forward', 'transaction_name as name', 'transaction_type'],
+ filters={
+ 'to_date': ("<", today()),
+ 'transaction_type': 'Leave Allocation',
+ 'transaction_name': ('not in', expired_allocation)
+ },
+ or_filters={
+ 'is_carry_forward': 0,
+ 'leave_type': ('in', leave_type)
+ })
+
+ if expire_allocation:
+ create_expiry_ledger_entry(expire_allocation)
+
+def create_expiry_ledger_entry(allocations):
+ ''' Create ledger entry for expired allocation '''
+ for allocation in allocations:
+ if allocation.is_carry_forward:
+ expire_carried_forward_allocation(allocation)
+ else:
+ expire_allocation(allocation)
+
+def get_remaining_leaves(allocation):
+ ''' Returns remaining leaves from the given allocation '''
+ return frappe.db.get_value("Leave Ledger Entry",
+ filters={
+ 'employee': allocation.employee,
+ 'leave_type': allocation.leave_type,
+ 'to_date': ('<=', allocation.to_date),
+ }, fieldname=['SUM(leaves)'])
+
+@frappe.whitelist()
+def expire_allocation(allocation, expiry_date=None):
+ ''' expires non-carry forwarded allocation '''
+ leaves = get_remaining_leaves(allocation)
+ expiry_date = expiry_date if expiry_date else allocation.to_date
+
+ if leaves:
+ args = dict(
+ leaves=flt(leaves) * -1,
+ transaction_name=allocation.name,
+ transaction_type='Leave Allocation',
+ from_date=expiry_date,
+ to_date=expiry_date,
+ is_carry_forward=0,
+ is_expired=1
+ )
+ create_leave_ledger_entry(allocation, args)
+
+ frappe.db.set_value("Leave Allocation", allocation.name, "expired", 1)
+
+def expire_carried_forward_allocation(allocation):
+ ''' Expires remaining leaves in the on carried forward allocation '''
+ from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period
+ leaves_taken = get_leaves_for_period(allocation.employee, allocation.leave_type, allocation.from_date, allocation.to_date)
+ leaves = flt(allocation.leaves) + flt(leaves_taken)
+ if leaves > 0:
+ args = frappe._dict(
+ transaction_name=allocation.name,
+ transaction_type="Leave Allocation",
+ leaves=allocation.leaves * -1,
+ is_carry_forward=allocation.is_carry_forward,
+ is_expired=1,
+ from_date=allocation.to_date,
+ to_date=allocation.to_date
+ )
+ create_leave_ledger_entry(allocation, args)
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_ledger_entry/test_leave_ledger_entry.py b/erpnext/hr/doctype/leave_ledger_entry/test_leave_ledger_entry.py
new file mode 100644
index 0000000..6f7725c
--- /dev/null
+++ b/erpnext/hr/doctype/leave_ledger_entry/test_leave_ledger_entry.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestLeaveLedgerEntry(unittest.TestCase):
+ pass
diff --git a/erpnext/hr/doctype/leave_period/leave_period.js b/erpnext/hr/doctype/leave_period/leave_period.js
index b8c5f71..bad2b87 100644
--- a/erpnext/hr/doctype/leave_period/leave_period.js
+++ b/erpnext/hr/doctype/leave_period/leave_period.js
@@ -68,7 +68,7 @@
},
{
"label": "Add unused leaves from previous allocations",
- "fieldname": "carry_forward_leaves",
+ "fieldname": "carry_forward",
"fieldtype": "Check"
}
],
diff --git a/erpnext/hr/doctype/leave_period/leave_period.json b/erpnext/hr/doctype/leave_period/leave_period.json
index df28763..9e895c3 100644
--- a/erpnext/hr/doctype/leave_period/leave_period.json
+++ b/erpnext/hr/doctype/leave_period/leave_period.json
@@ -1,294 +1,294 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "HR-LPR-.YYYY.-.#####",
- "beta": 0,
- "creation": "2018-04-13 15:20:52.864288",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "HR-LPR-.YYYY.-.#####",
+ "beta": 0,
+ "creation": "2018-04-13 15:20:52.864288",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "from_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_standard_filter": 0,
- "label": "From Date",
- "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "from_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_standard_filter": 0,
+ "label": "From Date",
+ "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": 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": "to_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_standard_filter": 0,
- "label": "To Date",
- "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "to_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_standard_filter": 0,
+ "label": "To Date",
+ "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": 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_3",
- "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,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "is_active",
+ "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": "Is Active",
+ "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": "company",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_3",
+ "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": "is_active",
- "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": "Is Active",
- "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,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 1,
+ "in_standard_filter": 0,
+ "label": "Company",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Company",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 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,
- "fieldname": "optional_holiday_list",
- "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": "Holiday List for Optional Leave",
- "length": 0,
- "no_copy": 0,
- "options": "Holiday List",
- "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,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "optional_holiday_list",
+ "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": "Holiday List for Optional Leave",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Holiday List",
+ "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
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-08-21 16:15:43.305502",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Leave Period",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 0,
+ "max_attachments": 0,
+ "modified": "2019-05-30 16:15:43.305502",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Leave Period",
+ "name_case": "",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "HR Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR Manager",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "HR User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "amend": 0,
+ "cancel": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "if_owner": 0,
+ "import": 0,
+ "permlevel": 0,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR User",
+ "set_user_permissions": 0,
+ "share": 1,
+ "submit": 0,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
+ ],
+ "quick_entry": 0,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
+ "track_seen": 0,
"track_views": 0
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_period/leave_period.py b/erpnext/hr/doctype/leave_period/leave_period.py
index 15fa8d6..0973ac7 100644
--- a/erpnext/hr/doctype/leave_period/leave_period.py
+++ b/erpnext/hr/doctype/leave_period/leave_period.py
@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
-from frappe.utils import getdate, cstr
+from frappe.utils import getdate, cstr, add_days, date_diff, getdate, ceil
from frappe.model.document import Document
from erpnext.hr.utils import validate_overlap, get_employee_leave_policy
from frappe.utils.background_jobs import enqueue
@@ -21,8 +21,8 @@
condition_str = " and " + " and ".join(conditions) if len(conditions) else ""
- employees = frappe.db.sql_list("select name from tabEmployee where status='Active' {condition}"
- .format(condition=condition_str), tuple(values))
+ employees = frappe._dict(frappe.db.sql("select name, date_of_joining from tabEmployee where status='Active' {condition}" #nosec
+ .format(condition=condition_str), tuple(values)))
return employees
@@ -36,29 +36,29 @@
def grant_leave_allocation(self, grade=None, department=None, designation=None,
- employee=None, carry_forward_leaves=0):
- employees = self.get_employees({
+ employee=None, carry_forward=0):
+ employee_records = self.get_employees({
"grade": grade,
- "department": department,
- "designation": designation,
+ "department": department,
+ "designation": designation,
"name": employee
})
- if employees:
- if len(employees) > 20:
+ if employee_records:
+ if len(employee_records) > 20:
frappe.enqueue(grant_leave_alloc_for_employees, timeout=600,
- employees=employees, leave_period=self, carry_forward_leaves=carry_forward_leaves)
+ employee_records=employee_records, leave_period=self, carry_forward=carry_forward)
else:
- grant_leave_alloc_for_employees(employees, self, carry_forward_leaves)
+ grant_leave_alloc_for_employees(employee_records, self, carry_forward)
else:
frappe.msgprint(_("No Employee Found"))
-def grant_leave_alloc_for_employees(employees, leave_period, carry_forward_leaves=0):
+def grant_leave_alloc_for_employees(employee_records, leave_period, carry_forward=0):
leave_allocations = []
- existing_allocations_for = get_existing_allocations(employees, leave_period.name)
+ existing_allocations_for = get_existing_allocations(list(employee_records.keys()), leave_period.name)
leave_type_details = get_leave_type_details()
- count=0
- for employee in employees:
+ count = 0
+ for employee in employee_records.keys():
if employee in existing_allocations_for:
continue
count +=1
@@ -67,18 +67,24 @@
for leave_policy_detail in leave_policy.leave_policy_details:
if not leave_type_details.get(leave_policy_detail.leave_type).is_lwp:
leave_allocation = create_leave_allocation(employee, leave_policy_detail.leave_type,
- leave_policy_detail.annual_allocation, leave_type_details, leave_period, carry_forward_leaves)
+ leave_policy_detail.annual_allocation, leave_type_details, leave_period, carry_forward, employee_records.get(employee))
leave_allocations.append(leave_allocation)
frappe.db.commit()
- frappe.publish_progress(count*100/len(set(employees) - set(existing_allocations_for)), title = _("Allocating leaves..."))
+ frappe.publish_progress(count*100/len(set(employee_records.keys()) - set(existing_allocations_for)), title = _("Allocating leaves..."))
if leave_allocations:
frappe.msgprint(_("Leaves has been granted sucessfully"))
def get_existing_allocations(employees, leave_period):
leave_allocations = frappe.db.sql_list("""
- select distinct employee from `tabLeave Allocation`
- where leave_period=%s and employee in (%s) and docstatus=1
+ SELECT DISTINCT
+ employee
+ FROM `tabLeave Allocation`
+ WHERE
+ leave_period=%s
+ AND employee in (%s)
+ AND carry_forward=0
+ AND docstatus=1
""" % ('%s', ', '.join(['%s']*len(employees))), [leave_period] + employees)
if leave_allocations:
frappe.msgprint(_("Skipping Leave Allocation for the following employees, as Leave Allocation records already exists against them. {0}")
@@ -87,28 +93,36 @@
def get_leave_type_details():
leave_type_details = frappe._dict()
- leave_types = frappe.get_all("Leave Type", fields=["name", "is_lwp", "is_earned_leave", "is_compensatory", "is_carry_forward"])
+ leave_types = frappe.get_all("Leave Type",
+ fields=["name", "is_lwp", "is_earned_leave", "is_compensatory", "is_carry_forward", "expire_carry_forwarded_leaves_after_days"])
for d in leave_types:
leave_type_details.setdefault(d.name, d)
return leave_type_details
-def create_leave_allocation(employee, leave_type, new_leaves_allocated, leave_type_details, leave_period, carry_forward_leaves):
- allocation = frappe.new_doc("Leave Allocation")
- allocation.employee = employee
- allocation.leave_type = leave_type
- allocation.from_date = leave_period.from_date
- allocation.to_date = leave_period.to_date
+def create_leave_allocation(employee, leave_type, new_leaves_allocated, leave_type_details, leave_period, carry_forward, date_of_joining):
+ ''' Creates leave allocation for the given employee in the provided leave period '''
+ if carry_forward and not leave_type_details.get(leave_type).is_carry_forward:
+ carry_forward = 0
+
+ # Calculate leaves at pro-rata basis for employees joining after the beginning of the given leave period
+ if getdate(date_of_joining) > getdate(leave_period.from_date):
+ remaining_period = ((date_diff(leave_period.to_date, date_of_joining) + 1) / (date_diff(leave_period.to_date, leave_period.from_date) + 1))
+ new_leaves_allocated = ceil(new_leaves_allocated * remaining_period)
+
# Earned Leaves and Compensatory Leaves are allocated by scheduler, initially allocate 0
if leave_type_details.get(leave_type).is_earned_leave == 1 or leave_type_details.get(leave_type).is_compensatory == 1:
new_leaves_allocated = 0
- allocation.new_leaves_allocated = new_leaves_allocated
- allocation.leave_period = leave_period.name
- if carry_forward_leaves:
- if leave_type_details.get(leave_type).is_carry_forward:
- allocation.carry_forward = carry_forward_leaves
+ allocation = frappe.get_doc(dict(
+ doctype="Leave Allocation",
+ employee=employee,
+ leave_type=leave_type,
+ from_date=leave_period.from_date,
+ to_date=leave_period.to_date,
+ new_leaves_allocated=new_leaves_allocated,
+ leave_period=leave_period.name,
+ carry_forward=carry_forward
+ ))
allocation.save(ignore_permissions = True)
allocation.submit()
- return allocation.name
-
-
+ return allocation.name
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py b/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py
index f97d285..48a2045 100644
--- a/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py
+++ b/erpnext/hr/doctype/leave_policy/leave_policy_dashboard.py
@@ -12,6 +12,9 @@
},
{
'items': ['Employee Grade']
- }
+ },
+ {
+ 'items': ['Leave Allocation']
+ },
]
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_policy/test_leave_policy.py b/erpnext/hr/doctype/leave_policy/test_leave_policy.py
index 2c6f1d0..fc868ea 100644
--- a/erpnext/hr/doctype/leave_policy/test_leave_policy.py
+++ b/erpnext/hr/doctype/leave_policy/test_leave_policy.py
@@ -12,16 +12,20 @@
if random_leave_type:
random_leave_type = random_leave_type[0]
leave_type = frappe.get_doc("Leave Type", random_leave_type.name)
- old_max_leaves_allowed = leave_type.max_leaves_allowed
leave_type.max_leaves_allowed = 2
leave_type.save()
- leave_policy_details = {
- "doctype": "Leave Policy",
- "leave_policy_details": [{
- "leave_type": leave_type.name,
- "annual_allocation": leave_type.max_leaves_allowed + 1
- }]
- }
+ leave_policy = create_leave_policy(leave_type=leave_type.name, annual_allocation=leave_type.max_leaves_allowed + 1)
- self.assertRaises(frappe.ValidationError, frappe.get_doc(leave_policy_details).insert)
+ self.assertRaises(frappe.ValidationError, leave_policy.insert)
+
+def create_leave_policy(**args):
+ ''' Returns an object of leave policy '''
+ args = frappe._dict(args)
+ return frappe.get_doc({
+ "doctype": "Leave Policy",
+ "leave_policy_details": [{
+ "leave_type": args.leave_type or "_Test Leave Type",
+ "annual_allocation": args.annual_allocation or 10
+ }]
+ })
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_type/leave_type.json b/erpnext/hr/doctype/leave_type/leave_type.json
index 6a7a80a..550d536 100644
--- a/erpnext/hr/doctype/leave_type/leave_type.json
+++ b/erpnext/hr/doctype/leave_type/leave_type.json
@@ -1,694 +1,214 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:leave_type_name",
- "beta": 0,
"creation": "2013-02-21 09:55:58",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
- "editable_grid": 0,
+ "engine": "InnoDB",
+ "field_order": [
+ "leave_type_name",
+ "max_leaves_allowed",
+ "applicable_after",
+ "max_continuous_days_allowed",
+ "column_break_3",
+ "is_carry_forward",
+ "is_lwp",
+ "is_optional_leave",
+ "allow_negative",
+ "include_holiday",
+ "is_compensatory",
+ "carry_forward_section",
+ "maximum_carry_forwarded_leaves",
+ "expire_carry_forwarded_leaves_after_days",
+ "encashment",
+ "allow_encashment",
+ "encashment_threshold_days",
+ "earning_component",
+ "earned_leave",
+ "is_earned_leave",
+ "earned_leave_frequency",
+ "rounding"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "leave_type_name",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Leave Type Name",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "leave_type_name",
"oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
"reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "unique": 1
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
"fieldname": "max_leaves_allowed",
"fieldtype": "Int",
- "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": "Max Leaves Allowed",
- "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
+ "label": "Max Leaves Allowed"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "applicable_after",
"fieldtype": "Int",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Applicable After (Working Days)",
- "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
+ "label": "Applicable After (Working Days)"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "max_continuous_days_allowed",
"fieldtype": "Int",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Maximum Continuous Days Applicable",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "max_days_allowed",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "oldfieldtype": "Data"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "column_break_3",
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "default": "0",
"fieldname": "is_carry_forward",
"fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Is Carry Forward",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "is_carry_forward",
- "oldfieldtype": "Check",
- "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
+ "oldfieldtype": "Check"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "default": "0",
"fieldname": "is_lwp",
"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": "Is Leave Without Pay",
- "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
+ "label": "Is Leave Without Pay"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "default": "0",
"fieldname": "is_optional_leave",
"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": "Is Optional Leave",
- "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
+ "label": "Is Optional Leave"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "default": "0",
"fieldname": "allow_negative",
"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": "Allow Negative Balance",
- "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
+ "label": "Allow Negative Balance"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "default": "0",
"fieldname": "include_holiday",
"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 holidays within leaves as leaves",
- "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
+ "label": "Include holidays within leaves as leaves"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "default": "0",
"fieldname": "is_compensatory",
"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": "Is Compensatory",
- "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
+ "label": "Is Compensatory"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
- "columns": 0,
+ "depends_on": "eval: doc.is_carry_forward == 1",
+ "fieldname": "carry_forward_section",
+ "fieldtype": "Section Break",
+ "label": "Carry Forward"
+ },
+ {
+ "description": "Calculated in days",
+ "fieldname": "expire_carry_forwarded_leaves_after_days",
+ "fieldtype": "Int",
+ "label": "Expire Carry Forwarded Leaves (Days)"
+ },
+ {
+ "collapsible": 1,
"fieldname": "encashment",
"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": "Encashment",
- "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
+ "label": "Encashment"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "default": "0",
"fieldname": "allow_encashment",
"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": "Allow Encashment",
- "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
+ "label": "Allow Encashment"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "allow_encashment",
"fieldname": "encashment_threshold_days",
"fieldtype": "Int",
- "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": "Encashment Threshold Days",
- "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
+ "label": "Encashment Threshold Days"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "allow_encashment",
"fieldname": "earning_component",
"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": "Earning Component",
- "length": 0,
- "no_copy": 0,
- "options": "Salary Component",
- "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
+ "options": "Salary Component"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
- "columns": 0,
"fieldname": "earned_leave",
"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": "Earned Leave",
- "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
+ "label": "Earned Leave"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "default": "0",
"fieldname": "is_earned_leave",
"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": "Is Earned Leave",
- "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
+ "label": "Is Earned Leave"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "is_earned_leave",
"fieldname": "earned_leave_frequency",
"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": "Earned Leave Frequency",
- "length": 0,
- "no_copy": 0,
- "options": "Monthly\nQuarterly\nHalf-Yearly\nYearly",
- "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
+ "options": "Monthly\nQuarterly\nHalf-Yearly\nYearly"
},
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "0.5",
"depends_on": "is_earned_leave",
"fieldname": "rounding",
"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": "Rounding",
- "length": 0,
- "no_copy": 0,
- "options": "0.5\n1.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
+ "options": "0.5\n1.0"
+ },
+ {
+ "depends_on": "is_carry_forward",
+ "fieldname": "maximum_carry_forwarded_leaves",
+ "fieldtype": "Float",
+ "label": "Maximum Carry Forwarded Leaves"
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
"icon": "fa fa-flag",
"idx": 1,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-06-03 18:32:51.803472",
+ "modified": "2019-09-06 18:48:48.946074",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Type",
"owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "HR User",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "amend": 0,
- "cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "HR Manager",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
"read": 1,
- "report": 0,
- "role": "Employee",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Employee"
}
],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "track_changes": 0,
- "track_seen": 0
-}
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_type/leave_type.py b/erpnext/hr/doctype/leave_type/leave_type.py
index e0127e5..c0d1296 100644
--- a/erpnext/hr/doctype/leave_type/leave_type.py
+++ b/erpnext/hr/doctype/leave_type/leave_type.py
@@ -2,9 +2,22 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
+import calendar
import frappe
+from datetime import datetime
+from frappe.utils import today
+from frappe import _
from frappe.model.document import Document
class LeaveType(Document):
- pass
\ No newline at end of file
+ def validate(self):
+ if self.is_lwp:
+ leave_allocation = frappe.get_all("Leave Allocation", filters={
+ 'leave_type': self.name,
+ 'from_date': ("<=", today()),
+ 'to_date': (">=", today())
+ }, fields=['name'])
+ leave_allocation = [l['name'] for l in leave_allocation]
+ if leave_allocation:
+ frappe.throw(_('Leave application is linked with leave allocations {0}. Leave application cannot be set as leave without pay').format(", ".join(leave_allocation))) #nosec
diff --git a/erpnext/hr/doctype/leave_type/test_leave_type.py b/erpnext/hr/doctype/leave_type/test_leave_type.py
index b844e49..0c4f435 100644
--- a/erpnext/hr/doctype/leave_type/test_leave_type.py
+++ b/erpnext/hr/doctype/leave_type/test_leave_type.py
@@ -2,6 +2,25 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
-
import frappe
-test_records = frappe.get_test_records('Leave Type')
\ No newline at end of file
+from frappe import _
+
+test_records = frappe.get_test_records('Leave Type')
+
+def create_leave_type(**args):
+ args = frappe._dict(args)
+ if frappe.db.exists("Leave Type", args.leave_type_name):
+ return frappe.get_doc("Leave Type", args.leave_type_name)
+ leave_type = frappe.get_doc({
+ "doctype": "Leave Type",
+ "leave_type_name": args.leave_type_name or "_Test Leave Type",
+ "include_holiday": args.include_holidays or 1,
+ "allow_encashment": args.allow_encashment or 0,
+ "is_earned_leave": args.is_earned_leave or 0,
+ "is_lwp": args.is_lwp or 0,
+ "is_carry_forward": args.is_carry_forward or 0,
+ "expire_carry_forwarded_leaves_after_days": args.expire_carry_forwarded_leaves_after_days or 0,
+ "encashment_threshold_days": args.encashment_threshold_days or 5,
+ "earning_component": "Leave Encashment"
+ })
+ return leave_type
\ No newline at end of file
diff --git a/erpnext/hr/doctype/loan_application/loan_application.py b/erpnext/hr/doctype/loan_application/loan_application.py
index 28d9c43..582bf48 100644
--- a/erpnext/hr/doctype/loan_application/loan_application.py
+++ b/erpnext/hr/doctype/loan_application/loan_application.py
@@ -30,7 +30,7 @@
monthly_interest_rate = flt(self.rate_of_interest) / (12 *100)
if monthly_interest_rate:
min_repayment_amount = self.loan_amount*monthly_interest_rate
- if self.repayment_amount - min_repayment_amount <= 0:
+ if (self.repayment_amount - min_repayment_amount) <= 0:
frappe.throw(_("Repayment Amount must be greater than " \
+ str(flt(min_repayment_amount, 2))))
self.repayment_periods = math.ceil((math.log(self.repayment_amount) -
@@ -58,10 +58,13 @@
doclist = get_mapped_doc("Loan Application", source_name, {
"Loan Application": {
"doctype": "Loan",
+ "field_map": {
+ "repayment_amount": "monthly_repayment_amount"
+ },
"validation": {
"docstatus": ["=", 1]
}
}
}, target_doc)
- return doclist
\ No newline at end of file
+ return doclist
diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.js b/erpnext/hr/doctype/payroll_entry/payroll_entry.js
index e4ab680..adc0671 100644
--- a/erpnext/hr/doctype/payroll_entry/payroll_entry.js
+++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.js
@@ -69,7 +69,7 @@
},
add_context_buttons: function(frm) {
- if(frm.doc.salary_slips_submitted) {
+ if(frm.doc.salary_slips_submitted || (frm.doc.__onload && frm.doc.__onload.submitted_ss)) {
frm.events.add_bank_entry_button(frm);
} else if(frm.doc.salary_slips_created) {
frm.add_custom_button(__("Submit Salary Slip"), function() {
diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.py b/erpnext/hr/doctype/payroll_entry/payroll_entry.py
index 8803a9a..97cfc84 100644
--- a/erpnext/hr/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.py
@@ -14,13 +14,12 @@
class PayrollEntry(Document):
def onload(self):
if not self.docstatus==1 or self.salary_slips_submitted:
- return
+ return
# check if salary slips were manually submitted
entries = frappe.db.count("Salary Slip", {'payroll_entry': self.name, 'docstatus': 1}, ['name'])
- if cint(entries) == len(self.employees) and not self.salary_slips_submitted:
- self.db_set("salary_slips_submitted", 1)
- self.reload()
+ if cint(entries) == len(self.employees):
+ self.set_onload("submitted_ss", True)
def on_submit(self):
self.create_salary_slips()
@@ -429,7 +428,6 @@
'start_date': start_date, 'end_date': end_date
})
-
def get_frequency_kwargs(frequency_name):
frequency_dict = {
'monthly': {'months': 1},
diff --git a/erpnext/hr/doctype/retention_bonus/retention_bonus.js b/erpnext/hr/doctype/retention_bonus/retention_bonus.js
index 58f6b53..64e726d 100644
--- a/erpnext/hr/doctype/retention_bonus/retention_bonus.js
+++ b/erpnext/hr/doctype/retention_bonus/retention_bonus.js
@@ -10,8 +10,13 @@
}
};
});
- },
- refresh: function(frm) {
+ frm.set_query("salary_component", function() {
+ return {
+ filters: {
+ "type": "Earning"
+ }
+ };
+ });
}
});
diff --git a/erpnext/hr/doctype/retention_bonus/retention_bonus.json b/erpnext/hr/doctype/retention_bonus/retention_bonus.json
index 5a92f07..7781053 100644
--- a/erpnext/hr/doctype/retention_bonus/retention_bonus.json
+++ b/erpnext/hr/doctype/retention_bonus/retention_bonus.json
@@ -1,415 +1,165 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "HR-RTB-.YYYY.-.#####",
- "beta": 0,
- "creation": "2018-05-13 14:59:42.038964",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "HR-RTB-.YYYY.-.#####",
+ "creation": "2018-05-13 14:59:42.038964",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "company",
+ "employee",
+ "bonus_payment_date",
+ "bonus_amount",
+ "salary_component",
+ "amended_from",
+ "column_break_6",
+ "employee_name",
+ "department",
+ "date_of_joining",
+ "additional_salary"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "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",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "options": "Company",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "employee",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Employee",
- "length": 0,
- "no_copy": 0,
- "options": "Employee",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "employee",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Employee",
+ "options": "Employee",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "bonus_payment_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_standard_filter": 0,
- "label": "Bonus Payment Date",
- "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "bonus_payment_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Bonus Payment Date",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "bonus_amount",
- "fieldtype": "Currency",
- "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": "Bonus Amount",
- "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
- },
+ "fieldname": "bonus_amount",
+ "fieldtype": "Currency",
+ "label": "Bonus Amount",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amended_from",
- "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",
- "length": 0,
- "no_copy": 1,
- "options": "Retention Bonus",
- "permlevel": 0,
- "print_hide": 1,
- "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
- },
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Retention Bonus",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_6",
- "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
- },
+ "fieldname": "column_break_6",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "employee.employee_name",
- "fieldname": "employee_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Employee Name",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
- },
+ "fetch_from": "employee.employee_name",
+ "fieldname": "employee_name",
+ "fieldtype": "Data",
+ "label": "Employee Name",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "employee.department",
- "fieldname": "department",
- "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",
- "length": 0,
- "no_copy": 0,
- "options": "Department",
- "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
- },
+ "fetch_from": "employee.department",
+ "fieldname": "department",
+ "fieldtype": "Link",
+ "label": "Department",
+ "options": "Department",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "employee.date_of_joining",
- "fieldname": "date_of_joining",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Date of Joining",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
+ "fetch_from": "employee.date_of_joining",
+ "fieldname": "date_of_joining",
+ "fieldtype": "Data",
+ "label": "Date of Joining",
+ "read_only": 1
+ },
+ {
+ "fieldname": "additional_salary",
+ "fieldtype": "Link",
+ "label": "Additional Salary",
+ "no_copy": 1,
+ "options": "Additional Salary",
+ "read_only": 1
+ },
+ {
+ "fieldname": "salary_component",
+ "fieldtype": "Link",
+ "label": "Salary Component",
+ "options": "Salary Component",
+ "reqd": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-08-21 16:15:38.710684",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Retention Bonus",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_submittable": 1,
+ "modified": "2019-09-03 16:47:24.210422",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Retention Bonus",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "HR Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR Manager",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "HR User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR User",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Employee",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 0
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Employee",
+ "share": 1
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/retention_bonus/retention_bonus.py b/erpnext/hr/doctype/retention_bonus/retention_bonus.py
index 20d4c13..48637a3 100644
--- a/erpnext/hr/doctype/retention_bonus/retention_bonus.py
+++ b/erpnext/hr/doctype/retention_bonus/retention_bonus.py
@@ -10,7 +10,42 @@
class RetentionBonus(Document):
def validate(self):
- if frappe.get_value("Employee", self.employee, "status") == "Left":
- frappe.throw(_("Cannot create Retention Bonus for left Employees"))
+ if frappe.get_value('Employee', self.employee, 'status') == 'Left':
+ frappe.throw(_('Cannot create Retention Bonus for left Employees'))
if getdate(self.bonus_payment_date) < getdate():
- frappe.throw(_("Bonus Payment Date cannot be a past date"))
+ frappe.throw(_('Bonus Payment Date cannot be a past date'))
+
+ def on_submit(self):
+ company = frappe.db.get_value('Employee', self.employee, 'company')
+ additional_salary = frappe.db.exists('Additional Salary', {
+ 'employee': self.employee,
+ 'salary_component': self.salary_component,
+ 'payroll_date': self.bonus_payment_date,
+ 'company': company,
+ 'docstatus': 1
+ })
+
+ if not additional_salary:
+ additional_salary = frappe.new_doc('Additional Salary')
+ additional_salary.employee = self.employee
+ additional_salary.salary_component = self.salary_component
+ additional_salary.amount = self.bonus_amount
+ additional_salary.payroll_date = self.bonus_payment_date
+ additional_salary.company = company
+ additional_salary.submit()
+ self.db_set('additional_salary', additional_salary.name)
+
+ else:
+ bonus_added = frappe.db.get_value('Additional Salary', additional_salary, 'amount') + self.bonus_amount
+ frappe.db.set_value('Additional Salary', additional_salary, 'amount', bonus_added)
+ self.db_set('additional_salary', additional_salary)
+
+ def on_cancel(self):
+ if self.additional_salary:
+ bonus_removed = frappe.db.get_value('Additional Salary', self.additional_salary, 'amount') - self.bonus_amount
+ if bonus_removed == 0:
+ frappe.get_doc('Additional Salary', self.additional_salary).cancel()
+ else:
+ frappe.db.set_value('Additional Salary', self.additional_salary, 'amount', bonus_removed)
+
+ self.db_set('additional_salary', '')
\ No newline at end of file
diff --git a/erpnext/hr/doctype/shift_type/shift_type.json b/erpnext/hr/doctype/shift_type/shift_type.json
index 86039de..61f3d2c 100644
--- a/erpnext/hr/doctype/shift_type/shift_type.json
+++ b/erpnext/hr/doctype/shift_type/shift_type.json
@@ -23,14 +23,9 @@
"grace_period_settings_auto_attendance_section",
"enable_entry_grace_period",
"late_entry_grace_period",
- "consequence_after",
- "consequence",
"column_break_18",
"enable_exit_grace_period",
- "enable_different_consequence_for_early_exit",
- "early_exit_grace_period",
- "early_exit_consequence_after",
- "early_exit_consequence"
+ "early_exit_grace_period"
],
"fields": [
{
@@ -108,21 +103,6 @@
"label": "Late Entry Grace Period"
},
{
- "depends_on": "enable_entry_grace_period",
- "description": "The number of occurrence after which the consequence is executed.",
- "fieldname": "consequence_after",
- "fieldtype": "Int",
- "label": "Consequence after"
- },
- {
- "default": "Half Day",
- "depends_on": "enable_entry_grace_period",
- "fieldname": "consequence",
- "fieldtype": "Select",
- "label": "Consequence",
- "options": "Half Day\nAbsent"
- },
- {
"fieldname": "column_break_18",
"fieldtype": "Column Break"
},
@@ -133,13 +113,6 @@
"label": "Enable Exit Grace Period"
},
{
- "default": "0",
- "depends_on": "enable_exit_grace_period",
- "fieldname": "enable_different_consequence_for_early_exit",
- "fieldtype": "Check",
- "label": "Enable Different Consequence for Early Exit"
- },
- {
"depends_on": "eval:doc.enable_exit_grace_period",
"description": "The time before the shift end time when check-out is considered as early (in minutes).",
"fieldname": "early_exit_grace_period",
@@ -147,21 +120,6 @@
"label": "Early Exit Grace Period"
},
{
- "depends_on": "eval:doc.enable_exit_grace_period && doc.enable_different_consequence_for_early_exit",
- "description": "The number of occurrence after which the consequence is executed.",
- "fieldname": "early_exit_consequence_after",
- "fieldtype": "Int",
- "label": "Early Exit Consequence after"
- },
- {
- "default": "Half Day",
- "depends_on": "eval:doc.enable_exit_grace_period && doc.enable_different_consequence_for_early_exit",
- "fieldname": "early_exit_consequence",
- "fieldtype": "Select",
- "label": "Early Exit Consequence",
- "options": "Half Day\nAbsent"
- },
- {
"default": "60",
"description": "Time after the end of shift during which check-out is considered for attendance.",
"fieldname": "allow_check_out_after_shift_end_time",
@@ -178,7 +136,6 @@
"depends_on": "enable_auto_attendance",
"fieldname": "grace_period_settings_auto_attendance_section",
"fieldtype": "Section Break",
- "hidden": 1,
"label": "Grace Period Settings For Auto Attendance"
},
{
@@ -201,7 +158,7 @@
"label": "Last Sync of Checkin"
}
],
- "modified": "2019-06-10 06:02:44.272036",
+ "modified": "2019-07-30 01:05:24.660666",
"modified_by": "Administrator",
"module": "HR",
"name": "Shift Type",
diff --git a/erpnext/hr/doctype/shift_type/shift_type.py b/erpnext/hr/doctype/shift_type/shift_type.py
index b98f445..8de92b2 100644
--- a/erpnext/hr/doctype/shift_type/shift_type.py
+++ b/erpnext/hr/doctype/shift_type/shift_type.py
@@ -28,8 +28,8 @@
logs = frappe.db.get_list('Employee Checkin', fields="*", filters=filters, order_by="employee,time")
for key, group in itertools.groupby(logs, key=lambda x: (x['employee'], x['shift_actual_start'])):
single_shift_logs = list(group)
- attendance_status, working_hours = self.get_attendance(single_shift_logs)
- mark_attendance_and_link_log(single_shift_logs, attendance_status, key[1].date(), working_hours, self.name)
+ attendance_status, working_hours, late_entry, early_exit = self.get_attendance(single_shift_logs)
+ mark_attendance_and_link_log(single_shift_logs, attendance_status, key[1].date(), working_hours, late_entry, early_exit, self.name)
for employee in self.get_assigned_employee(self.process_attendance_after, True):
self.mark_absent_for_dates_with_no_attendance(employee)
@@ -39,12 +39,19 @@
1. These logs belongs to an single shift, single employee and is not in a holiday date.
2. Logs are in chronological order
"""
- total_working_hours = calculate_working_hours(logs, self.determine_check_in_and_check_out, self.working_hours_calculation_based_on)
+ late_entry = early_exit = False
+ total_working_hours, in_time, out_time = calculate_working_hours(logs, self.determine_check_in_and_check_out, self.working_hours_calculation_based_on)
+ if cint(self.enable_entry_grace_period) and in_time and in_time > logs[0].shift_start + timedelta(minutes=cint(self.late_entry_grace_period)):
+ late_entry = True
+
+ if cint(self.enable_exit_grace_period) and out_time and out_time < logs[0].shift_end - timedelta(minutes=cint(self.early_exit_grace_period)):
+ early_exit = True
+
if self.working_hours_threshold_for_absent and total_working_hours < self.working_hours_threshold_for_absent:
- return 'Absent', total_working_hours
+ return 'Absent', total_working_hours, late_entry, early_exit
if self.working_hours_threshold_for_half_day and total_working_hours < self.working_hours_threshold_for_half_day:
- return 'Half Day', total_working_hours
- return 'Present', total_working_hours
+ return 'Half Day', total_working_hours, late_entry, early_exit
+ return 'Present', total_working_hours, late_entry, early_exit
def mark_absent_for_dates_with_no_attendance(self, employee):
"""Marks Absents for the given employee on working days in this shift which have no attendance marked.
diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.js b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.js
index 59c2560..05728a2 100644
--- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.js
+++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.js
@@ -24,6 +24,18 @@
"options": "Company",
"reqd": 1,
"default": frappe.defaults.get_user_default("Company")
+ },
+ {
+ "fieldname":"department",
+ "label": __("Department"),
+ "fieldtype": "Link",
+ "options": "Department",
+ },
+ {
+ "fieldname":"employee",
+ "label": __("Employee"),
+ "fieldtype": "Link",
+ "options": "Employee",
}
]
}
diff --git a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
index 1843176..7717ba0 100644
--- a/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
+++ b/erpnext/hr/report/employee_leave_balance/employee_leave_balance.py
@@ -4,9 +4,12 @@
from __future__ import unicode_literals
import frappe
from frappe import _
+from frappe.utils import flt
from erpnext.hr.doctype.leave_application.leave_application \
- import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period
+ import get_leave_balance_on, get_leaves_for_period
+from erpnext.hr.report.employee_leave_balance_summary.employee_leave_balance_summary \
+ import get_department_leave_approver_map
def execute(filters=None):
leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc")
@@ -18,7 +21,7 @@
def get_columns(leave_types):
columns = [
- _("Employee") + ":Link/Employee:150",
+ _("Employee") + ":Link.Employee:150",
_("Employee Name") + "::200",
_("Department") +"::150"
]
@@ -30,57 +33,50 @@
return columns
+def get_conditions(filters):
+ conditions = {
+ "status": "Active",
+ "company": filters.company,
+ }
+ if filters.get("department"):
+ conditions.update({"department": filters.get("department")})
+ if filters.get("employee"):
+ conditions.update({"employee": filters.get("employee")})
+
+ return conditions
+
def get_data(filters, leave_types):
user = frappe.session.user
- allocation_records_based_on_to_date = get_leave_allocation_records(filters.to_date)
- allocation_records_based_on_from_date = get_leave_allocation_records(filters.from_date)
+ conditions = get_conditions(filters)
if filters.to_date <= filters.from_date:
frappe.throw(_("From date can not be greater than than To date"))
active_employees = frappe.get_all("Employee",
- filters = { "status": "Active", "company": filters.company},
- fields = ["name", "employee_name", "department", "user_id"])
+ filters=conditions,
+ fields=["name", "employee_name", "department", "user_id", "leave_approver"])
+
+ department_approver_map = get_department_leave_approver_map(filters.get('department'))
data = []
for employee in active_employees:
- leave_approvers = get_approvers(employee.department)
+ leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver)
if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) or ("HR Manager" in frappe.get_roles(user)):
row = [employee.name, employee.employee_name, employee.department]
for leave_type in leave_types:
# leaves taken
- leaves_taken = get_approved_leaves_for_period(employee.name, leave_type,
- filters.from_date, filters.to_date)
+ leaves_taken = get_leaves_for_period(employee.name, leave_type,
+ filters.from_date, filters.to_date) * -1
# opening balance
- opening = get_leave_balance_on(employee.name, leave_type, filters.from_date,
- allocation_records_based_on_to_date.get(employee.name, frappe._dict()))
+ opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
# closing balance
- closing = get_leave_balance_on(employee.name, leave_type, filters.to_date,
- allocation_records_based_on_to_date.get(employee.name, frappe._dict()))
+ closing = get_leave_balance_on(employee.name, leave_type, filters.to_date)
row += [opening, leaves_taken, closing]
data.append(row)
- return data
-
-def get_approvers(department):
- if not department:
- return []
-
- approvers = []
- # get current department and all its child
- department_details = frappe.db.get_value("Department", {"name": department}, ["lft", "rgt"], as_dict=True)
- department_list = frappe.db.sql("""select name from `tabDepartment`
- where lft >= %s and rgt <= %s order by lft desc
- """, (department_details.lft, department_details.rgt), as_list = True)
-
- # retrieve approvers list from current department and from its subsequent child departments
- for d in department_list:
- approvers.extend([l.leave_approver for l in frappe.db.sql("""select approver from `tabDepartment Approver` \
- where parent = %s and parentfield = 'leave_approvers'""", (d), as_dict=True)])
-
- return approvers
+ return data
\ No newline at end of file
diff --git a/erpnext/hr/report/employee_leave_balance_summary/__init__.py b/erpnext/hr/report/employee_leave_balance_summary/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/hr/report/employee_leave_balance_summary/__init__.py
diff --git a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.js b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.js
new file mode 100644
index 0000000..3fb8f6e
--- /dev/null
+++ b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.js
@@ -0,0 +1,42 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports['Employee Leave Balance Summary'] = {
+ filters: [
+ {
+ fieldname:'from_date',
+ label: __('From Date'),
+ fieldtype: 'Date',
+ reqd: 1,
+ default: frappe.defaults.get_default('year_start_date')
+ },
+ {
+ fieldname:'to_date',
+ label: __('To Date'),
+ fieldtype: 'Date',
+ reqd: 1,
+ default: frappe.defaults.get_default('year_end_date')
+ },
+ {
+ fieldname:'company',
+ label: __('Company'),
+ fieldtype: 'Link',
+ options: 'Company',
+ reqd: 1,
+ default: frappe.defaults.get_user_default('Company')
+ },
+ {
+ fieldname:'employee',
+ label: __('Employee'),
+ fieldtype: 'Link',
+ options: 'Employee',
+ },
+ {
+ fieldname:'department',
+ label: __('Department'),
+ fieldtype: 'Link',
+ options: 'Department',
+ }
+ ]
+};
diff --git a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.json b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.json
new file mode 100644
index 0000000..60fe1ae
--- /dev/null
+++ b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.json
@@ -0,0 +1,34 @@
+{
+ "add_total_row": 0,
+ "creation": "2019-09-05 11:18:06.209397",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "letter_head": "sapcon-old",
+ "modified": "2019-09-05 11:18:06.209397",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Employee Leave Balance Summary",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Employee",
+ "report_name": "Employee Leave Balance Summary",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "Employee"
+ },
+ {
+ "role": "HR Manager"
+ },
+ {
+ "role": "HR User"
+ },
+ {
+ "role": "Leave Approver"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
new file mode 100644
index 0000000..15a5da0
--- /dev/null
+++ b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
@@ -0,0 +1,130 @@
+# 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.utils import flt
+from frappe import _
+from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period, get_leave_balance_on
+
+def execute(filters=None):
+ if filters.to_date <= filters.from_date:
+ frappe.throw(_('From date can not be greater than than To date'))
+
+ columns = get_columns()
+ data = get_data(filters)
+
+ return columns, data
+
+def get_columns():
+ columns = [{
+ 'label': _('Leave Type'),
+ 'fieldtype': 'Link',
+ 'fieldname': 'leave_type',
+ 'width': 300,
+ 'options': 'Leave Type'
+ }, {
+ 'label': _('Employee'),
+ 'fieldtype': 'Link',
+ 'fieldname': 'employee',
+ 'width': 100,
+ 'options': 'Employee'
+ }, {
+ 'label': _('Employee Name'),
+ 'fieldtype': 'Data',
+ 'fieldname': 'employee_name',
+ 'width': 100,
+ }, {
+ 'label': _('Opening Balance'),
+ 'fieldtype': 'float',
+ 'fieldname': 'opening_balance',
+ 'width': 160,
+ }, {
+ 'label': _('Leaves Taken'),
+ 'fieldtype': 'float',
+ 'fieldname': 'leaves_taken',
+ 'width': 160,
+ }, {
+ 'label': _('Closing Balance'),
+ 'fieldtype': 'float',
+ 'fieldname': 'closing_balance',
+ 'width': 160,
+ }]
+
+ return columns
+
+def get_data(filters):
+ leave_types = frappe.db.sql_list("SELECT `name` FROM `tabLeave Type` ORDER BY `name` ASC")
+
+ conditions = get_conditions(filters)
+
+ user = frappe.session.user
+ department_approver_map = get_department_leave_approver_map(filters.get('department'))
+
+ active_employees = frappe.get_list('Employee',
+ filters=conditions,
+ fields=['name', 'employee_name', 'department', 'user_id', 'leave_approver'])
+
+ data = []
+
+ for leave_type in leave_types:
+ data.append({
+ 'leave_type': leave_type
+ })
+ for employee in active_employees:
+
+ leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver)
+
+ if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) \
+ or ("HR Manager" in frappe.get_roles(user)):
+ row = frappe._dict({
+ 'employee': employee.name,
+ 'employee_name': employee.employee_name
+ })
+
+ leaves_taken = get_leaves_for_period(employee.name, leave_type,
+ filters.from_date, filters.to_date) * -1
+
+ opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
+ closing = get_leave_balance_on(employee.name, leave_type, filters.to_date)
+
+ row.opening_balance = opening
+ row.leaves_taken = leaves_taken
+ row.closing_balance = closing
+ row.indent = 1
+ data.append(row)
+
+ return data
+
+def get_conditions(filters):
+ conditions={
+ 'status': 'Active',
+ }
+ if filters.get('employee'):
+ conditions['name'] = filters.get('employee')
+
+ if filters.get('employee'):
+ conditions['name'] = filters.get('employee')
+
+ return conditions
+
+def get_department_leave_approver_map(department=None):
+ conditions=''
+ if department:
+ conditions='and department_name = %(department)s or parent_department = %(department)s'%{'department': department}
+
+ # get current department and all its child
+ department_list = frappe.db.sql_list(''' SELECT name FROM `tabDepartment` WHERE disabled=0 {0}'''.format(conditions)) #nosec
+
+ # retrieve approvers list from current department and from its subsequent child departments
+ approver_list = frappe.get_all('Department Approver', filters={
+ 'parentfield': 'leave_approvers',
+ 'parent': ('in', department_list)
+ }, fields=['parent', 'approver'], as_list=1)
+
+ approvers = {}
+
+ for k, v in approver_list:
+ approvers.setdefault(k, []).append(v)
+
+ return approvers
diff --git a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
index e9c7029..1e9c83b 100644
--- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
+++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
@@ -25,6 +25,7 @@
leave_types = frappe.db.sql("""select name from `tabLeave Type`""", as_list=True)
leave_list = [d[0] for d in leave_types]
columns.extend(leave_list)
+ columns.extend([_("Total Late Entries") + ":Float:120", _("Total Early Exits") + ":Float:120"])
for emp in sorted(att_map):
emp_det = emp_map.get(emp)
@@ -65,6 +66,10 @@
leave_details = frappe.db.sql("""select leave_type, status, count(*) as count from `tabAttendance`\
where leave_type is not NULL %s group by leave_type, status""" % conditions, filters, as_dict=1)
+
+ time_default_counts = frappe.db.sql("""select (select count(*) from `tabAttendance` where \
+ late_entry = 1 %s) as late_entry_count, (select count(*) from tabAttendance where \
+ early_exit = 1 %s) as early_exit_count""" % (conditions, conditions), filters)
leaves = {}
for d in leave_details:
@@ -80,7 +85,8 @@
row.append(leaves[d])
else:
row.append("0.0")
-
+
+ row.extend([time_default_counts[0][0],time_default_counts[0][1]])
data.append(row)
return columns, data
diff --git a/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py b/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py
index e2989e2..e5622b7 100644
--- a/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py
+++ b/erpnext/hr/report/vehicle_expenses/vehicle_expenses.py
@@ -23,7 +23,8 @@
_("Model") + ":data:50", _("Location") + ":data:100",
_("Log") + ":Link/Vehicle Log:100", _("Odometer") + ":Int:80",
_("Date") + ":Date:100", _("Fuel Qty") + ":Float:80",
- _("Fuel Price") + ":Float:100",_("Service Expense") + ":Float:100"
+ _("Fuel Price") + ":Float:100",_("Fuel Expense") + ":Float:100",
+ _("Service Expense") + ":Float:100"
]
return columns
@@ -32,7 +33,8 @@
data = frappe.db.sql("""select
vhcl.license_plate as "License", vhcl.make as "Make", vhcl.model as "Model",
vhcl.location as "Location", log.name as "Log", log.odometer as "Odometer",
- log.date as "Date", log.fuel_qty as "Fuel Qty", log.price as "Fuel Price"
+ log.date as "Date", log.fuel_qty as "Fuel Qty", log.price as "Fuel Price",
+ log.fuel_qty * log.price as "Fuel Expense"
from
`tabVehicle` vhcl,`tabVehicle Log` log
where
@@ -58,7 +60,7 @@
total_ser_exp=0
for row in data:
if row["Date"] <= period.to_date and row["Date"] >= period.from_date:
- total_fuel_exp+=flt(row["Fuel Price"])
+ total_fuel_exp+=flt(row["Fuel Expense"])
total_ser_exp+=flt(row["Service Expense"])
fueldata.append([period.key,total_fuel_exp])
servicedata.append([period.key,total_ser_exp])
@@ -84,4 +86,4 @@
}
}
chart["type"] = "line"
- return chart
\ No newline at end of file
+ return chart
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index de2b090..1464a77 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe, erpnext
from frappe import _
-from frappe.utils import formatdate, format_datetime, getdate, get_datetime, nowdate, flt, cstr
+from frappe.utils import formatdate, format_datetime, getdate, get_datetime, nowdate, flt, cstr, add_days, today
from frappe.model.document import Document
from frappe.desk.form import assign_to
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
@@ -270,6 +270,21 @@
if leave_period:
return leave_period
+def generate_leave_encashment():
+ ''' Generates a draft leave encashment on allocation expiry '''
+ from erpnext.hr.doctype.leave_encashment.leave_encashment import create_leave_encashment
+
+ if frappe.db.get_single_value('HR Settings', 'auto_leave_encashment'):
+ leave_type = frappe.get_all('Leave Type', filters={'allow_encashment': 1}, fields=['name'])
+ leave_type=[l['name'] for l in leave_type]
+
+ leave_allocation = frappe.get_all("Leave Allocation", filters={
+ 'to_date': add_days(today(), -1),
+ 'leave_type': ('in', leave_type)
+ }, fields=['employee', 'leave_period', 'leave_type', 'to_date', 'total_leaves_allocated', 'new_leaves_allocated'])
+
+ create_leave_encashment(leave_allocation=leave_allocation)
+
def allocate_earned_leaves():
'''Allocate earned leaves to Employees'''
e_leave_types = frappe.get_all("Leave Type",
@@ -277,31 +292,43 @@
filters={'is_earned_leave' : 1})
today = getdate()
divide_by_frequency = {"Yearly": 1, "Half-Yearly": 6, "Quarterly": 4, "Monthly": 12}
- if e_leave_types:
- for e_leave_type in e_leave_types:
- leave_allocations = frappe.db.sql("""select name, employee, from_date, to_date from `tabLeave Allocation` where '{0}'
- between from_date and to_date and docstatus=1 and leave_type='{1}'"""
- .format(today, e_leave_type.name), as_dict=1)
- for allocation in leave_allocations:
- leave_policy = get_employee_leave_policy(allocation.employee)
- if not leave_policy:
- continue
- if not e_leave_type.earned_leave_frequency == "Monthly":
- if not check_frequency_hit(allocation.from_date, today, e_leave_type.earned_leave_frequency):
- continue
- annual_allocation = frappe.db.sql("""select annual_allocation from `tabLeave Policy Detail`
- where parent=%s and leave_type=%s""", (leave_policy.name, e_leave_type.name))
- if annual_allocation and annual_allocation[0]:
- earned_leaves = flt(annual_allocation[0][0]) / divide_by_frequency[e_leave_type.earned_leave_frequency]
- if e_leave_type.rounding == "0.5":
- earned_leaves = round(earned_leaves * 2) / 2
- else:
- earned_leaves = round(earned_leaves)
- allocated_leaves = frappe.db.get_value('Leave Allocation', allocation.name, 'total_leaves_allocated')
- new_allocation = flt(allocated_leaves) + flt(earned_leaves)
- new_allocation = new_allocation if new_allocation <= e_leave_type.max_leaves_allowed else e_leave_type.max_leaves_allowed
- frappe.db.set_value('Leave Allocation', allocation.name, 'total_leaves_allocated', new_allocation)
+ for e_leave_type in e_leave_types:
+ leave_allocations = frappe.db.sql("""select name, employee, from_date, to_date from `tabLeave Allocation` where %s
+ between from_date and to_date and docstatus=1 and leave_type=%s""", (today, e_leave_type.name), as_dict=1)
+ for allocation in leave_allocations:
+ leave_policy = get_employee_leave_policy(allocation.employee)
+ if not leave_policy:
+ continue
+ if not e_leave_type.earned_leave_frequency == "Monthly":
+ if not check_frequency_hit(allocation.from_date, today, e_leave_type.earned_leave_frequency):
+ continue
+ annual_allocation = frappe.db.get_value("Leave Policy Detail", filters={
+ 'parent': leave_policy.name,
+ 'leave_type': e_leave_type.name
+ }, fieldname=['annual_allocation'])
+ if annual_allocation:
+ earned_leaves = flt(annual_allocation) / divide_by_frequency[e_leave_type.earned_leave_frequency]
+ if e_leave_type.rounding == "0.5":
+ earned_leaves = round(earned_leaves * 2) / 2
+ else:
+ earned_leaves = round(earned_leaves)
+
+ allocation = frappe.get_doc('Leave Allocation', allocation.name)
+ new_allocation = flt(allocation.total_leaves_allocated) + flt(earned_leaves)
+ new_allocation = new_allocation if new_allocation <= e_leave_type.max_leaves_allowed else e_leave_type.max_leaves_allowed
+
+ if new_allocation == allocation.total_leaves_allocated:
+ continue
+ allocation.db_set("total_leaves_allocated", new_allocation, update_modified=False)
+ create_earned_leave_ledger_entry(allocation, earned_leaves, today)
+
+def create_earned_leave_ledger_entry(allocation, earned_leaves, date):
+ ''' Create leave ledger entry based on the earned leave frequency '''
+ allocation.new_leaves_allocated = earned_leaves
+ allocation.from_date = date
+ allocation.unused_leaves = 0
+ allocation.create_leave_ledger_entry()
def check_frequency_hit(from_date, to_date, frequency):
'''Return True if current date matches frequency'''
diff --git a/erpnext/hub_node/legacy.py b/erpnext/hub_node/legacy.py
index 95ada76..85eb1b2 100644
--- a/erpnext/hub_node/legacy.py
+++ b/erpnext/hub_node/legacy.py
@@ -68,12 +68,13 @@
contact = frappe.get_doc({
'doctype': 'Contact',
'first_name': supplier.supplier_name,
- 'email_id': supplier.supplier_email,
'is_primary_contact': 1,
'links': [
{'link_doctype': 'Supplier', 'link_name': supplier.supplier_name}
]
- }).insert()
+ })
+ contact.add_email(supplier.supplier_email)
+ contact.insert()
else:
contact = frappe.get_doc('Contact', contact_name)
diff --git a/erpnext/manufacturing/doctype/bom/bom.json b/erpnext/manufacturing/doctype/bom/bom.json
index 7865a24..a0faeb5 100644
--- a/erpnext/manufacturing/doctype/bom/bom.json
+++ b/erpnext/manufacturing/doctype/bom/bom.json
@@ -1,2068 +1,528 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2013-01-22 15:11:38",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 0,
+ "allow_import": 1,
+ "creation": "2013-01-22 15:11:38",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "field_order": [
+ "item",
+ "item_name",
+ "image",
+ "uom",
+ "quantity",
+ "cb0",
+ "is_active",
+ "is_default",
+ "with_operations",
+ "inspection_required",
+ "allow_alternative_item",
+ "allow_same_item_multiple_times",
+ "set_rate_of_sub_assembly_item_based_on_bom",
+ "quality_inspection_template",
+ "currency_detail",
+ "company",
+ "transfer_material_against",
+ "conversion_rate",
+ "column_break_12",
+ "currency",
+ "rm_cost_as_per",
+ "buying_price_list",
+ "operations_section",
+ "routing",
+ "operations",
+ "materials_section",
+ "items",
+ "scrap_section",
+ "scrap_items",
+ "costing",
+ "operating_cost",
+ "raw_material_cost",
+ "scrap_material_cost",
+ "cb1",
+ "base_operating_cost",
+ "base_raw_material_cost",
+ "base_scrap_material_cost",
+ "total_cost_of_bom",
+ "total_cost",
+ "column_break_26",
+ "base_total_cost",
+ "more_info_section",
+ "project",
+ "amended_from",
+ "col_break23",
+ "section_break_25",
+ "description",
+ "column_break_27",
+ "section_break0",
+ "exploded_items",
+ "website_section",
+ "show_in_website",
+ "route",
+ "website_image",
+ "thumbnail",
+ "sb_web_spec",
+ "web_long_description",
+ "show_items",
+ "show_operations"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Item to be manufactured or repacked",
- "fetch_if_empty": 0,
- "fieldname": "item",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Item",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "item",
- "oldfieldtype": "Link",
- "options": "Item",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "description": "Item to be manufactured or repacked",
+ "fieldname": "item",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Item",
+ "oldfieldname": "item",
+ "oldfieldtype": "Link",
+ "options": "Item",
+ "reqd": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fetch_from": "item.item_name",
- "fetch_if_empty": 0,
- "fieldname": "item_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Item Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "item.item_name",
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "label": "Item Name",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "item.image",
- "fetch_if_empty": 0,
- "fieldname": "image",
- "fieldtype": "Attach Image",
- "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",
- "length": 0,
- "no_copy": 0,
- "options": "image",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fetch_from": "item.image",
+ "fieldname": "image",
+ "fieldtype": "Attach Image",
+ "hidden": 1,
+ "label": "Image",
+ "options": "image",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "item.stock_uom",
- "fetch_if_empty": 0,
- "fieldname": "uom",
- "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": "Item UOM",
- "length": 0,
- "no_copy": 0,
- "options": "UOM",
- "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
- },
+ "fetch_from": "item.stock_uom",
+ "fieldname": "uom",
+ "fieldtype": "Link",
+ "label": "Item UOM",
+ "options": "UOM",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "description": "Quantity of item obtained after manufacturing / repacking from given quantities of raw materials",
- "fetch_if_empty": 0,
- "fieldname": "quantity",
- "fieldtype": "Float",
- "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": "Quantity",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "quantity",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "1",
+ "description": "Quantity of item obtained after manufacturing / repacking from given quantities of raw materials",
+ "fieldname": "quantity",
+ "fieldtype": "Float",
+ "label": "Quantity",
+ "oldfieldname": "quantity",
+ "oldfieldtype": "Currency",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "cb0",
- "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,
- "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
- },
+ "fieldname": "cb0",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fetch_if_empty": 0,
- "fieldname": "is_active",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Is Active",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "is_active",
- "oldfieldtype": "Select",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "default": "1",
+ "fieldname": "is_active",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Is Active",
+ "no_copy": 1,
+ "oldfieldname": "is_active",
+ "oldfieldtype": "Select"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fetch_if_empty": 0,
- "fieldname": "is_default",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Is Default",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "is_default",
- "oldfieldtype": "Check",
- "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_on_submit": 1,
+ "default": "1",
+ "fieldname": "is_default",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Is Default",
+ "no_copy": 1,
+ "oldfieldname": "is_default",
+ "oldfieldtype": "Check"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Manage cost of operations",
- "fetch_if_empty": 0,
- "fieldname": "with_operations",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "With Operations",
- "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
- },
+ "default": "0",
+ "description": "Manage cost of operations",
+ "fieldname": "with_operations",
+ "fieldtype": "Check",
+ "ignore_user_permissions": 1,
+ "label": "With Operations"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "inspection_required",
- "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": "Inspection Required",
- "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
- },
+ "default": "0",
+ "fieldname": "inspection_required",
+ "fieldtype": "Check",
+ "label": "Inspection Required"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "allow_alternative_item",
- "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": "Allow Alternative Item",
- "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
- },
+ "default": "0",
+ "fieldname": "allow_alternative_item",
+ "fieldtype": "Check",
+ "label": "Allow Alternative Item"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "allow_same_item_multiple_times",
- "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": "Allow Same Item Multiple Times",
- "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
- },
+ "default": "0",
+ "fieldname": "allow_same_item_multiple_times",
+ "fieldtype": "Check",
+ "label": "Allow Same Item Multiple Times"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fetch_if_empty": 0,
- "fieldname": "set_rate_of_sub_assembly_item_based_on_bom",
- "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": "Set rate of sub-assembly item based on BOM",
- "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_on_submit": 1,
+ "default": "1",
+ "fieldname": "set_rate_of_sub_assembly_item_based_on_bom",
+ "fieldtype": "Check",
+ "label": "Set rate of sub-assembly item based on BOM"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "inspection_required",
- "fetch_if_empty": 0,
- "fieldname": "quality_inspection_template",
- "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": "Quality Inspection Template",
- "length": 0,
- "no_copy": 0,
- "options": "Quality Inspection Template",
- "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
- },
+ "depends_on": "inspection_required",
+ "fieldname": "quality_inspection_template",
+ "fieldtype": "Link",
+ "label": "Quality Inspection Template",
+ "options": "Quality Inspection Template"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "currency_detail",
- "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,
- "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
- },
+ "fieldname": "currency_detail",
+ "fieldtype": "Section Break"
+ },
{
- "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",
- "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",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 1,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "options": "Company",
+ "remember_last_selected_value": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fetch_if_empty": 0,
- "fieldname": "transfer_material_against",
- "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": "Transfer Material Against",
- "length": 0,
- "no_copy": 0,
- "options": "\nWork Order\nJob Card",
- "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
- },
+ "fieldname": "transfer_material_against",
+ "fieldtype": "Select",
+ "label": "Transfer Material Against",
+ "options": "\nWork Order\nJob Card"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "conversion_rate",
- "fieldtype": "Float",
- "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": "Conversion Rate",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "9",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "conversion_rate",
+ "fieldtype": "Float",
+ "label": "Conversion Rate",
+ "precision": "9",
+ "reqd": 1
+ },
{
- "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_12",
- "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
- },
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "currency",
- "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": "Currency",
- "length": 0,
- "no_copy": 0,
- "options": "Currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "currency",
+ "fieldtype": "Link",
+ "label": "Currency",
+ "options": "Currency",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Valuation Rate",
- "fetch_if_empty": 0,
- "fieldname": "rm_cost_as_per",
- "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": "Rate Of Materials Based On",
- "length": 0,
- "no_copy": 0,
- "options": "Valuation Rate\nLast Purchase Rate\nPrice List",
- "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_on_submit": 1,
+ "default": "Valuation Rate",
+ "fieldname": "rm_cost_as_per",
+ "fieldtype": "Select",
+ "label": "Rate Of Materials Based On",
+ "options": "Valuation Rate\nLast Purchase Rate\nPrice List"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.rm_cost_as_per===\"Price List\"",
- "fetch_if_empty": 0,
- "fieldname": "buying_price_list",
- "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": "Price List",
- "length": 0,
- "no_copy": 0,
- "options": "Price List",
- "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_on_submit": 1,
+ "depends_on": "eval:doc.rm_cost_as_per===\"Price List\"",
+ "fieldname": "buying_price_list",
+ "fieldtype": "Link",
+ "label": "Price List",
+ "options": "Price List"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "description": "",
- "fetch_if_empty": 0,
- "fieldname": "operations_section",
- "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": "Operations",
- "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
- },
+ "fieldname": "operations_section",
+ "fieldtype": "Section Break",
+ "label": "Operations",
+ "oldfieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "routing",
- "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": "Routing",
- "length": 0,
- "no_copy": 0,
- "options": "Routing",
- "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
- },
+ "fieldname": "routing",
+ "fieldtype": "Link",
+ "label": "Routing",
+ "options": "Routing"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "operations",
- "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": "Operations",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "bom_operations",
- "oldfieldtype": "Table",
- "options": "BOM Operation",
- "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
- },
+ "fieldname": "operations",
+ "fieldtype": "Table",
+ "label": "Operations",
+ "oldfieldname": "bom_operations",
+ "oldfieldtype": "Table",
+ "options": "BOM Operation"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "materials_section",
- "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": "Materials",
- "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
- },
+ "fieldname": "materials_section",
+ "fieldtype": "Section Break",
+ "label": "Materials",
+ "oldfieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "items",
- "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": "Items",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "bom_materials",
- "oldfieldtype": "Table",
- "options": "BOM Item",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "items",
+ "fieldtype": "Table",
+ "label": "Items",
+ "oldfieldname": "bom_materials",
+ "oldfieldtype": "Table",
+ "options": "BOM Item",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "scrap_section",
- "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": "Scrap",
- "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
- },
+ "collapsible": 1,
+ "fieldname": "scrap_section",
+ "fieldtype": "Section Break",
+ "label": "Scrap"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "scrap_items",
- "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": "Scrap Items",
- "length": 0,
- "no_copy": 0,
- "options": "BOM Scrap Item",
- "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
- },
+ "fieldname": "scrap_items",
+ "fieldtype": "Table",
+ "label": "Scrap Items",
+ "options": "BOM Scrap Item"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "costing",
- "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": "Costing",
- "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
- },
+ "fieldname": "costing",
+ "fieldtype": "Section Break",
+ "label": "Costing",
+ "oldfieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "operating_cost",
- "fieldtype": "Currency",
- "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": "Operating Cost",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "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
- },
+ "fieldname": "operating_cost",
+ "fieldtype": "Currency",
+ "label": "Operating Cost",
+ "options": "currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "raw_material_cost",
- "fieldtype": "Currency",
- "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": "Raw Material Cost",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "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
- },
+ "fieldname": "raw_material_cost",
+ "fieldtype": "Currency",
+ "label": "Raw Material Cost",
+ "options": "currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "scrap_material_cost",
- "fieldtype": "Currency",
- "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": "Scrap Material Cost",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fieldname": "scrap_material_cost",
+ "fieldtype": "Currency",
+ "label": "Scrap Material Cost",
+ "options": "currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "cb1",
- "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,
- "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
- },
+ "fieldname": "cb1",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "base_operating_cost",
- "fieldtype": "Currency",
- "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": "Operating Cost (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fieldname": "base_operating_cost",
+ "fieldtype": "Currency",
+ "label": "Operating Cost (Company Currency)",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "base_raw_material_cost",
- "fieldtype": "Currency",
- "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": "Raw Material Cost(Company Currency)",
- "length": 0,
- "no_copy": 0,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fieldname": "base_raw_material_cost",
+ "fieldtype": "Currency",
+ "label": "Raw Material Cost (Company Currency)",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "base_scrap_material_cost",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Scrap Material Cost(Company Currency)",
- "length": 0,
- "no_copy": 1,
- "options": "Company:company:default_currency",
- "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
- },
+ "fieldname": "base_scrap_material_cost",
+ "fieldtype": "Data",
+ "label": "Scrap Material Cost(Company Currency)",
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "total_cost_of_bom",
- "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
- },
+ "fieldname": "total_cost_of_bom",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "total_cost",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Total Cost",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "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
- },
+ "fieldname": "total_cost",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Total Cost",
+ "options": "currency",
+ "read_only": 1
+ },
{
- "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_26",
- "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
- },
+ "fieldname": "column_break_26",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "base_total_cost",
- "fieldtype": "Currency",
- "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": "Total Cost(Company Currency)",
- "length": 0,
- "no_copy": 0,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fieldname": "base_total_cost",
+ "fieldtype": "Currency",
+ "label": "Total Cost (Company Currency)",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "more_info_section",
- "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
- },
+ "fieldname": "more_info_section",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "project",
- "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": "Project",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "project",
- "oldfieldtype": "Link",
- "options": "Project",
- "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
- },
+ "fieldname": "project",
+ "fieldtype": "Link",
+ "label": "Project",
+ "oldfieldname": "project",
+ "oldfieldtype": "Link",
+ "options": "Project"
+ },
{
- "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",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Amended From",
- "length": 0,
- "no_copy": 1,
- "options": "BOM",
- "permlevel": 0,
- "print_hide": 1,
- "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
- },
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "BOM",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "col_break23",
- "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,
- "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
- },
+ "fieldname": "col_break23",
+ "fieldtype": "Column Break"
+ },
{
- "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_25",
- "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
- },
+ "fieldname": "section_break_25",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "item.description",
- "fetch_if_empty": 0,
- "fieldname": "description",
- "fieldtype": "Small Text",
- "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": "Item Description",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "item.description",
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Item Description",
+ "read_only": 1
+ },
{
- "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_27",
- "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
- },
+ "fieldname": "column_break_27",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:!doc.__islocal",
- "fetch_if_empty": 0,
- "fieldname": "section_break0",
- "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": "Materials Required (Exploded)",
- "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
- },
+ "depends_on": "eval:!doc.__islocal",
+ "fieldname": "section_break0",
+ "fieldtype": "Section Break",
+ "label": "Materials Required (Exploded)"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "exploded_items",
- "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": "Exploded_items",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "flat_bom_details",
- "oldfieldtype": "Table",
- "options": "BOM Explosion Item",
- "permlevel": 0,
- "print_hide": 1,
- "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
- },
+ "fieldname": "exploded_items",
+ "fieldtype": "Table",
+ "label": "Exploded Items",
+ "no_copy": 1,
+ "oldfieldname": "flat_bom_details",
+ "oldfieldtype": "Table",
+ "options": "BOM Explosion Item",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "website_section",
- "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": "Website",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
- },
+ "collapsible": 1,
+ "fieldname": "website_section",
+ "fieldtype": "Section Break",
+ "label": "Website"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fetch_if_empty": 0,
- "fieldname": "show_in_website",
- "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": "Show in Website",
- "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_on_submit": 1,
+ "default": "0",
+ "fieldname": "show_in_website",
+ "fieldtype": "Check",
+ "label": "Show in Website"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "route",
- "fieldtype": "Small Text",
- "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": "Route",
- "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_on_submit": 1,
+ "fieldname": "route",
+ "fieldtype": "Small Text",
+ "label": "Route"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "show_in_website",
- "description": "Item Image (if not slideshow)",
- "fetch_if_empty": 0,
- "fieldname": "website_image",
- "fieldtype": "Attach 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",
- "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_on_submit": 1,
+ "depends_on": "show_in_website",
+ "description": "Item Image (if not slideshow)",
+ "fieldname": "website_image",
+ "fieldtype": "Attach Image",
+ "label": "Image"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "thumbnail",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Thumbnail",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "fieldname": "thumbnail",
+ "fieldtype": "Data",
+ "label": "Thumbnail",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "collapsible_depends_on": "website_items",
- "columns": 0,
- "depends_on": "show_in_website",
- "fetch_if_empty": 0,
- "fieldname": "sb_web_spec",
- "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": "Website Specifications",
- "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
- },
+ "collapsible": 1,
+ "collapsible_depends_on": "website_items",
+ "depends_on": "show_in_website",
+ "fieldname": "sb_web_spec",
+ "fieldtype": "Section Break",
+ "label": "Website Specifications"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "show_in_website",
- "fetch_if_empty": 0,
- "fieldname": "web_long_description",
- "fieldtype": "Text Editor",
- "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": "Website Description",
- "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_on_submit": 1,
+ "depends_on": "show_in_website",
+ "fieldname": "web_long_description",
+ "fieldtype": "Text Editor",
+ "label": "Website Description"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "show_in_website",
- "fetch_if_empty": 0,
- "fieldname": "show_items",
- "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": "Show Items",
- "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_on_submit": 1,
+ "default": "0",
+ "depends_on": "show_in_website",
+ "fieldname": "show_items",
+ "fieldtype": "Check",
+ "label": "Show Items"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:(doc.show_in_website && doc.with_operations)",
- "fetch_if_empty": 0,
- "fieldname": "show_operations",
- "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": "Show Operations",
- "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_on_submit": 1,
+ "default": "0",
+ "depends_on": "eval:(doc.show_in_website && doc.with_operations)",
+ "fieldname": "show_operations",
+ "fieldtype": "Check",
+ "label": "Show Operations"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-sitemap",
- "idx": 1,
- "image_field": "image",
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-05-01 16:36:05.197126",
- "modified_by": "Administrator",
- "module": "Manufacturing",
- "name": "BOM",
- "owner": "Administrator",
+ ],
+ "icon": "fa fa-sitemap",
+ "idx": 1,
+ "image_field": "image",
+ "is_submittable": 1,
+ "modified": "2019-07-30 17:00:09.665068",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "BOM",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Manufacturing Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Manufacturing Manager",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Manufacturing User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Manufacturing User",
+ "share": 1,
+ "submit": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "search_fields": "item, item_name",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "search_fields": "item, item_name",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index a716293..8eb4c9c 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -9,6 +9,7 @@
from frappe.website.website_generator import WebsiteGenerator
from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.stock.get_item_details import get_price_list_rate
+from frappe.core.doctype.version.version import get_diff
import functools
@@ -715,6 +716,8 @@
next(item for item in items if item.get('name')
== bom_item.get('item_code'))
)
+
+ bom_item.parent_bom_qty = bom_doc.quantity
bom_item.expandable = 0 if bom_item.value in ('', None) else 1
return bom_items
@@ -763,3 +766,52 @@
'description': name[0],
'amount': items.get(name[0])
})
+
+@frappe.whitelist()
+def get_bom_diff(bom1, bom2):
+ from frappe.model import table_fields
+
+ doc1 = frappe.get_doc('BOM', bom1)
+ doc2 = frappe.get_doc('BOM', bom2)
+
+ out = get_diff(doc1, doc2)
+ out.row_changed = []
+ out.added = []
+ out.removed = []
+
+ meta = doc1.meta
+
+ identifiers = {
+ 'operations': 'operation',
+ 'items': 'item_code',
+ 'scrap_items': 'item_code',
+ 'exploded_items': 'item_code'
+ }
+
+ for df in meta.fields:
+ old_value, new_value = doc1.get(df.fieldname), doc2.get(df.fieldname)
+
+ if df.fieldtype in table_fields:
+ identifier = identifiers[df.fieldname]
+ # make maps
+ old_row_by_identifier, new_row_by_identifier = {}, {}
+ for d in old_value:
+ old_row_by_identifier[d.get(identifier)] = d
+ for d in new_value:
+ new_row_by_identifier[d.get(identifier)] = d
+
+ # check rows for additions, changes
+ for i, d in enumerate(new_value):
+ if d.get(identifier) in old_row_by_identifier:
+ diff = get_diff(old_row_by_identifier[d.get(identifier)], d, for_child=True)
+ if diff and diff.changed:
+ out.row_changed.append((df.fieldname, i, d.get(identifier), diff.changed))
+ else:
+ out.added.append([df.fieldname, d.as_dict()])
+
+ # check for deletions
+ for d in old_value:
+ if not d.get(identifier) in new_row_by_identifier:
+ out.removed.append([df.fieldname, d.as_dict()])
+
+ return out
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py
deleted file mode 100644
index 6793062..0000000
--- a/erpnext/manufacturing/doctype/production_order/production_order.py
+++ /dev/null
@@ -1,648 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import json
-from six import text_type
-from frappe import _
-from frappe.utils import flt, get_datetime, getdate, date_diff, cint, nowdate
-from frappe.model.document import Document
-from erpnext.manufacturing.doctype.bom.bom import validate_bom_no, get_bom_items_as_dict
-from dateutil.relativedelta import relativedelta
-from erpnext.stock.doctype.item.item import validate_end_of_life
-from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError
-from erpnext.projects.doctype.timesheet.timesheet import OverlapError
-from erpnext.stock.doctype.stock_entry.stock_entry import get_additional_costs
-from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
-from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty
-from frappe.utils.csvutils import getlink
-from erpnext.stock.utils import get_bin, validate_warehouse_company, get_latest_stock_qty
-from erpnext.utilities.transaction_base import validate_uom_is_integer
-
-class OverProductionError(frappe.ValidationError): pass
-class StockOverProductionError(frappe.ValidationError): pass
-class OperationTooLongError(frappe.ValidationError): pass
-class ItemHasVariantError(frappe.ValidationError): pass
-
-form_grid_templates = {
- "operations": "templates/form_grid/production_order_grid.html"
-}
-
-class ProductionOrder(Document):
- def validate(self):
- self.validate_production_item()
- if self.bom_no:
- validate_bom_no(self.production_item, self.bom_no)
-
- self.validate_sales_order()
- self.set_default_warehouse()
- self.validate_warehouse_belongs_to_company()
- self.calculate_operating_cost()
- self.validate_qty()
- self.validate_operation_time()
- self.status = self.get_status()
-
- validate_uom_is_integer(self, "stock_uom", ["qty", "produced_qty"])
-
- self.set_required_items(reset_only_qty = len(self.get("required_items")))
-
- def validate_sales_order(self):
- if self.sales_order:
- so = frappe.db.sql("""
- select so.name, so_item.delivery_date, so.project
- from `tabSales Order` so
- inner join `tabSales Order Item` so_item on so_item.parent = so.name
- left join `tabProduct Bundle Item` pk_item on so_item.item_code = pk_item.parent
- where so.name=%s and so.docstatus = 1 and (
- so_item.item_code=%s or
- pk_item.item_code=%s )
- """, (self.sales_order, self.production_item, self.production_item), as_dict=1)
-
- if not so:
- so = frappe.db.sql("""
- select
- so.name, so_item.delivery_date, so.project
- from
- `tabSales Order` so, `tabSales Order Item` so_item, `tabPacked Item` packed_item
- where so.name=%s
- and so.name=so_item.parent
- and so.name=packed_item.parent
- and so_item.item_code = packed_item.parent_item
- and so.docstatus = 1 and packed_item.item_code=%s
- """, (self.sales_order, self.production_item), as_dict=1)
-
- if len(so):
- if not self.expected_delivery_date:
- self.expected_delivery_date = so[0].delivery_date
-
- if so[0].project:
- self.project = so[0].project
-
- if not self.material_request:
- self.validate_production_order_against_so()
- else:
- frappe.throw(_("Sales Order {0} is not valid").format(self.sales_order))
-
- def set_default_warehouse(self):
- if not self.wip_warehouse:
- self.wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
- if not self.fg_warehouse:
- self.fg_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_fg_warehouse")
-
- def validate_warehouse_belongs_to_company(self):
- warehouses = [self.fg_warehouse, self.wip_warehouse]
- for d in self.get("required_items"):
- if d.source_warehouse not in warehouses:
- warehouses.append(d.source_warehouse)
-
- for wh in warehouses:
- validate_warehouse_company(wh, self.company)
-
- def calculate_operating_cost(self):
- self.planned_operating_cost, self.actual_operating_cost = 0.0, 0.0
- for d in self.get("operations"):
- d.planned_operating_cost = flt(d.hour_rate) * (flt(d.time_in_mins) / 60.0)
- d.actual_operating_cost = flt(d.hour_rate) * (flt(d.actual_operation_time) / 60.0)
-
- self.planned_operating_cost += flt(d.planned_operating_cost)
- self.actual_operating_cost += flt(d.actual_operating_cost)
-
- variable_cost = self.actual_operating_cost if self.actual_operating_cost \
- else self.planned_operating_cost
- self.total_operating_cost = flt(self.additional_operating_cost) + flt(variable_cost)
-
- def validate_production_order_against_so(self):
- # already ordered qty
- ordered_qty_against_so = frappe.db.sql("""select sum(qty) from `tabProduction Order`
- where production_item = %s and sales_order = %s and docstatus < 2 and name != %s""",
- (self.production_item, self.sales_order, self.name))[0][0]
-
- total_qty = flt(ordered_qty_against_so) + flt(self.qty)
-
- # get qty from Sales Order Item table
- so_item_qty = frappe.db.sql("""select sum(stock_qty) from `tabSales Order Item`
- where parent = %s and item_code = %s""",
- (self.sales_order, self.production_item))[0][0]
- # get qty from Packing Item table
- dnpi_qty = frappe.db.sql("""select sum(qty) from `tabPacked Item`
- where parent = %s and parenttype = 'Sales Order' and item_code = %s""",
- (self.sales_order, self.production_item))[0][0]
- # total qty in SO
- so_qty = flt(so_item_qty) + flt(dnpi_qty)
-
- allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings",
- "over_production_allowance_percentage"))
-
- if total_qty > so_qty + (allowance_percentage/100 * so_qty):
- frappe.throw(_("Cannot produce more Item {0} than Sales Order quantity {1}")
- .format(self.production_item, so_qty), OverProductionError)
-
- def update_status(self, status=None):
- '''Update status of production order if unknown'''
- if status != "Stopped":
- status = self.get_status(status)
-
- if status != self.status:
- self.db_set("status", status)
-
- self.update_required_items()
-
- return status
-
- def get_status(self, status=None):
- '''Return the status based on stock entries against this production order'''
- if not status:
- status = self.status
-
- if self.docstatus==0:
- status = 'Draft'
- elif self.docstatus==1:
- if status != 'Stopped':
- stock_entries = frappe._dict(frappe.db.sql("""select purpose, sum(fg_completed_qty)
- from `tabStock Entry` where production_order=%s and docstatus=1
- group by purpose""", self.name))
-
- status = "Not Started"
- if stock_entries:
- status = "In Process"
- produced_qty = stock_entries.get("Manufacture")
- if flt(produced_qty) == flt(self.qty):
- status = "Completed"
- else:
- status = 'Cancelled'
-
- return status
-
- def update_production_order_qty(self):
- """Update **Manufactured Qty** and **Material Transferred for Qty** in Production Order
- based on Stock Entry"""
-
- for purpose, fieldname in (("Manufacture", "produced_qty"),
- ("Material Transfer for Manufacture", "material_transferred_for_manufacturing")):
- qty = flt(frappe.db.sql("""select sum(fg_completed_qty)
- from `tabStock Entry` where production_order=%s and docstatus=1
- and purpose=%s""", (self.name, purpose))[0][0])
-
- if qty > self.qty:
- frappe.throw(_("{0} ({1}) cannot be greater than planned quanitity ({2}) in Production Order {3}").format(\
- self.meta.get_label(fieldname), qty, self.qty, self.name), StockOverProductionError)
-
- self.db_set(fieldname, qty)
-
- def before_submit(self):
- self.make_time_logs()
-
- def on_submit(self):
- if not self.wip_warehouse:
- frappe.throw(_("Work-in-Progress Warehouse is required before Submit"))
- if not self.fg_warehouse:
- frappe.throw(_("For Warehouse is required before Submit"))
-
- self.update_reserved_qty_for_production()
- self.update_completed_qty_in_material_request()
- self.update_planned_qty()
-
- def on_cancel(self):
- self.validate_cancel()
-
- frappe.db.set(self,'status', 'Cancelled')
- self.delete_timesheet()
- self.update_completed_qty_in_material_request()
- self.update_planned_qty()
- self.update_reserved_qty_for_production()
-
- def validate_cancel(self):
- if self.status == "Stopped":
- frappe.throw(_("Stopped Production Order cannot be cancelled, Unstop it first to cancel"))
-
- # Check whether any stock entry exists against this Production Order
- stock_entry = frappe.db.sql("""select name from `tabStock Entry`
- where production_order = %s and docstatus = 1""", self.name)
- if stock_entry:
- frappe.throw(_("Cannot cancel because submitted Stock Entry {0} exists").format(stock_entry[0][0]))
-
- def update_planned_qty(self):
- update_bin_qty(self.production_item, self.fg_warehouse, {
- "planned_qty": get_planned_qty(self.production_item, self.fg_warehouse)
- })
-
- if self.material_request:
- mr_obj = frappe.get_doc("Material Request", self.material_request)
- mr_obj.update_requested_qty([self.material_request_item])
-
- def update_completed_qty_in_material_request(self):
- if self.material_request:
- frappe.get_doc("Material Request", self.material_request).update_completed_qty([self.material_request_item])
-
- def set_production_order_operations(self):
- """Fetch operations from BOM and set in 'Production Order'"""
- self.set('operations', [])
-
- if not self.bom_no \
- or cint(frappe.db.get_single_value("Manufacturing Settings", "disable_capacity_planning")):
- return
-
- if self.use_multi_level_bom:
- bom_list = frappe.get_doc("BOM", self.bom_no).traverse_tree()
- else:
- bom_list = [self.bom_no]
-
- operations = frappe.db.sql("""
- select
- operation, description, workstation, idx,
- base_hour_rate as hour_rate, time_in_mins,
- "Pending" as status, parent as bom
- from
- `tabBOM Operation`
- where
- parent in (%s) order by idx
- """ % ", ".join(["%s"]*len(bom_list)), tuple(bom_list), as_dict=1)
-
- self.set('operations', operations)
- self.calculate_time()
-
- def calculate_time(self):
- bom_qty = frappe.db.get_value("BOM", self.bom_no, "quantity")
-
- for d in self.get("operations"):
- d.time_in_mins = flt(d.time_in_mins) / flt(bom_qty) * flt(self.qty)
-
- self.calculate_operating_cost()
-
- def get_holidays(self, workstation):
- holiday_list = frappe.db.get_value("Workstation", workstation, "holiday_list")
-
- holidays = {}
-
- if holiday_list not in holidays:
- holiday_list_days = [getdate(d[0]) for d in frappe.get_all("Holiday", fields=["holiday_date"],
- filters={"parent": holiday_list}, order_by="holiday_date", limit_page_length=0, as_list=1)]
-
- holidays[holiday_list] = holiday_list_days
-
- return holidays[holiday_list]
-
- def make_time_logs(self, open_new=False):
- """Capacity Planning. Plan time logs based on earliest availablity of workstation after
- Planned Start Date. Time logs will be created and remain in Draft mode and must be submitted
- before manufacturing entry can be made."""
-
- if not self.operations:
- return
-
- timesheets = []
- plan_days = frappe.db.get_single_value("Manufacturing Settings", "capacity_planning_for_days") or 30
-
- timesheet = make_timesheet(self.name, self.company)
- timesheet.set('time_logs', [])
-
- for i, d in enumerate(self.operations):
-
- if d.status != 'Completed':
- self.set_start_end_time_for_workstation(d, i)
-
- args = self.get_operations_data(d)
-
- add_timesheet_detail(timesheet, args)
- original_start_time = d.planned_start_time
-
- # validate operating hours if workstation [not mandatory] is specified
- try:
- timesheet.validate_time_logs()
- except OverlapError:
- if frappe.message_log: frappe.message_log.pop()
- timesheet.schedule_for_production_order(d.idx)
- except WorkstationHolidayError:
- if frappe.message_log: frappe.message_log.pop()
- timesheet.schedule_for_production_order(d.idx)
-
- from_time, to_time = self.get_start_end_time(timesheet, d.name)
-
- if date_diff(from_time, original_start_time) > cint(plan_days):
- frappe.throw(_("Unable to find Time Slot in the next {0} days for Operation {1}").format(plan_days, d.operation))
- break
-
- d.planned_start_time = from_time
- d.planned_end_time = to_time
- d.db_update()
-
- if timesheet and open_new:
- return timesheet
-
- if timesheet and timesheet.get("time_logs"):
- timesheet.save()
- timesheets.append(getlink("Timesheet", timesheet.name))
-
- self.planned_end_date = self.operations[-1].planned_end_time
- if timesheets:
- frappe.local.message_log = []
- frappe.msgprint(_("Timesheet created:") + "\n" + "\n".join(timesheets))
-
- def get_operations_data(self, data):
- return {
- 'from_time': get_datetime(data.planned_start_time),
- 'hours': data.time_in_mins / 60.0,
- 'to_time': get_datetime(data.planned_end_time),
- 'project': self.project,
- 'operation': data.operation,
- 'operation_id': data.name,
- 'workstation': data.workstation,
- 'completed_qty': flt(self.qty) - flt(data.completed_qty)
- }
-
- def set_start_end_time_for_workstation(self, data, index):
- """Set start and end time for given operation. If first operation, set start as
- `planned_start_date`, else add time diff to end time of earlier operation."""
-
- if index == 0:
- data.planned_start_time = self.planned_start_date
- else:
- data.planned_start_time = get_datetime(self.operations[index-1].planned_end_time)\
- + get_mins_between_operations()
-
- data.planned_end_time = get_datetime(data.planned_start_time) + relativedelta(minutes = data.time_in_mins)
-
- if data.planned_start_time == data.planned_end_time:
- frappe.throw(_("Capacity Planning Error"))
-
- def get_start_end_time(self, timesheet, operation_id):
- for data in timesheet.time_logs:
- if data.operation_id == operation_id:
- return data.from_time, data.to_time
-
- def check_operation_fits_in_working_hours(self, d):
- """Raises expection if operation is longer than working hours in the given workstation."""
- from erpnext.manufacturing.doctype.workstation.workstation import check_if_within_operating_hours
- check_if_within_operating_hours(d.workstation, d.operation, d.planned_start_time, d.planned_end_time)
-
- def update_operation_status(self):
- for d in self.get("operations"):
- if not d.completed_qty:
- d.status = "Pending"
- elif flt(d.completed_qty) < flt(self.qty):
- d.status = "Work in Progress"
- elif flt(d.completed_qty) == flt(self.qty):
- d.status = "Completed"
- else:
- frappe.throw(_("Completed Qty can not be greater than 'Qty to Manufacture'"))
-
- def set_actual_dates(self):
- self.actual_start_date = None
- self.actual_end_date = None
- if self.get("operations"):
- actual_start_dates = [d.actual_start_time for d in self.get("operations") if d.actual_start_time]
- if actual_start_dates:
- self.actual_start_date = min(actual_start_dates)
-
- actual_end_dates = [d.actual_end_time for d in self.get("operations") if d.actual_end_time]
- if actual_end_dates:
- self.actual_end_date = max(actual_end_dates)
-
- def delete_timesheet(self):
- for timesheet in frappe.get_all("Timesheet", ["name"], {"production_order": self.name}):
- frappe.delete_doc("Timesheet", timesheet.name)
-
- def validate_production_item(self):
- if frappe.db.get_value("Item", self.production_item, "has_variants"):
- frappe.throw(_("Production Order cannot be raised against a Item Template"), ItemHasVariantError)
-
- if self.production_item:
- validate_end_of_life(self.production_item)
-
- def validate_qty(self):
- if not self.qty > 0:
- frappe.throw(_("Quantity to Manufacture must be greater than 0."))
-
- def validate_operation_time(self):
- for d in self.operations:
- if not d.time_in_mins > 0:
- frappe.throw(_("Operation Time must be greater than 0 for Operation {0}".format(d.operation)))
-
- def update_required_items(self):
- '''
- update bin reserved_qty_for_production
- called from Stock Entry for production, after submit, cancel
- '''
- if self.docstatus==1:
- # calculate transferred qty based on submitted stock entries
- self.update_transaferred_qty_for_required_items()
-
- # update in bin
- self.update_reserved_qty_for_production()
-
- def update_reserved_qty_for_production(self, items=None):
- '''update reserved_qty_for_production in bins'''
- for d in self.required_items:
- if d.source_warehouse:
- stock_bin = get_bin(d.item_code, d.source_warehouse)
- stock_bin.update_reserved_qty_for_production()
-
- def get_items_and_operations_from_bom(self):
- self.set_required_items()
- self.set_production_order_operations()
-
- return check_if_scrap_warehouse_mandatory(self.bom_no)
-
- def set_available_qty(self):
- for d in self.get("required_items"):
- if d.source_warehouse:
- d.available_qty_at_source_warehouse = get_latest_stock_qty(d.item_code, d.source_warehouse)
-
- if self.wip_warehouse:
- d.available_qty_at_wip_warehouse = get_latest_stock_qty(d.item_code, self.wip_warehouse)
-
- def set_required_items(self, reset_only_qty=False):
- '''set required_items for production to keep track of reserved qty'''
- if not reset_only_qty:
- self.required_items = []
-
- if self.bom_no and self.qty:
- item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=self.qty,
- fetch_exploded = self.use_multi_level_bom)
-
- if reset_only_qty:
- for d in self.get("required_items"):
- if item_dict.get(d.item_code):
- d.required_qty = item_dict.get(d.item_code).get("qty")
- else:
- for item in sorted(item_dict.values(), key=lambda d: d['idx']):
- self.append('required_items', {
- 'item_code': item.item_code,
- 'item_name': item.item_name,
- 'description': item.description,
- 'required_qty': item.qty,
- 'source_warehouse': item.source_warehouse or item.default_warehouse
- })
-
- self.set_available_qty()
-
- def update_transaferred_qty_for_required_items(self):
- '''update transferred qty from submitted stock entries for that item against
- the production order'''
-
- for d in self.required_items:
- transferred_qty = frappe.db.sql('''select sum(qty)
- from `tabStock Entry` entry, `tabStock Entry Detail` detail
- where
- entry.production_order = %s
- and entry.purpose = "Material Transfer for Manufacture"
- and entry.docstatus = 1
- and detail.parent = entry.name
- and detail.item_code = %s''', (self.name, d.item_code))[0][0]
-
- d.db_set('transferred_qty', flt(transferred_qty), update_modified = False)
-
-
-@frappe.whitelist()
-def get_item_details(item, project = None):
- res = frappe.db.sql("""
- select stock_uom, description
- from `tabItem`
- where disabled=0
- and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %s)
- and name=%s
- """, (nowdate(), item), as_dict=1)
-
- if not res:
- return {}
-
- res = res[0]
-
- filters = {"item": item, "is_default": 1}
-
- if project:
- filters = {"item": item, "project": project}
-
- res["bom_no"] = frappe.db.get_value("BOM", filters = filters)
-
- if not res["bom_no"]:
- variant_of= frappe.db.get_value("Item", item, "variant_of")
-
- if variant_of:
- res["bom_no"] = frappe.db.get_value("BOM", filters={"item": variant_of, "is_default": 1})
-
- if not res["bom_no"]:
- if project:
- res = get_item_details(item)
- frappe.msgprint(_("Default BOM not found for Item {0} and Project {1}").format(item, project), alert=1)
- else:
- frappe.throw(_("Default BOM for {0} not found").format(item))
-
- res['project'] = project or frappe.db.get_value('BOM', res['bom_no'], 'project')
- res.update(check_if_scrap_warehouse_mandatory(res["bom_no"]))
-
- return res
-
-@frappe.whitelist()
-def check_if_scrap_warehouse_mandatory(bom_no):
- res = {"set_scrap_wh_mandatory": False }
- if bom_no:
- bom = frappe.get_doc("BOM", bom_no)
-
- if len(bom.scrap_items) > 0:
- res["set_scrap_wh_mandatory"] = True
-
- return res
-
-@frappe.whitelist()
-def set_production_order_ops(name):
- po = frappe.get_doc('Production Order', name)
- po.set_production_order_operations()
- po.save()
-
-@frappe.whitelist()
-def make_stock_entry(production_order_id, purpose, qty=None):
- production_order = frappe.get_doc("Production Order", production_order_id)
- if not frappe.db.get_value("Warehouse", production_order.wip_warehouse, "is_group") \
- and not production_order.skip_transfer:
- wip_warehouse = production_order.wip_warehouse
- else:
- wip_warehouse = None
-
- stock_entry = frappe.new_doc("Stock Entry")
- stock_entry.purpose = purpose
- stock_entry.production_order = production_order_id
- stock_entry.company = production_order.company
- stock_entry.from_bom = 1
- stock_entry.bom_no = production_order.bom_no
- stock_entry.use_multi_level_bom = production_order.use_multi_level_bom
- stock_entry.fg_completed_qty = qty or (flt(production_order.qty) - flt(production_order.produced_qty))
- stock_entry.set_stock_entry_type()
-
- if purpose=="Material Transfer for Manufacture":
- stock_entry.to_warehouse = wip_warehouse
- stock_entry.project = production_order.project
- else:
- stock_entry.from_warehouse = wip_warehouse
- stock_entry.to_warehouse = production_order.fg_warehouse
- additional_costs = get_additional_costs(production_order, fg_qty=stock_entry.fg_completed_qty)
- stock_entry.project = production_order.project
- stock_entry.set("additional_costs", additional_costs)
-
- stock_entry.get_items()
- return stock_entry.as_dict()
-
-@frappe.whitelist()
-def make_timesheet(production_order, company):
- timesheet = frappe.new_doc("Timesheet")
- timesheet.employee = ""
- timesheet.production_order = production_order
- timesheet.company = company
- return timesheet
-
-@frappe.whitelist()
-def add_timesheet_detail(timesheet, args):
- if isinstance(timesheet, text_type):
- timesheet = frappe.get_doc('Timesheet', timesheet)
-
- if isinstance(args, text_type):
- args = json.loads(args)
-
- timesheet.append('time_logs', args)
- return timesheet
-
-@frappe.whitelist()
-def get_default_warehouse():
- wip_warehouse = frappe.db.get_single_value("Manufacturing Settings",
- "default_wip_warehouse")
- fg_warehouse = frappe.db.get_single_value("Manufacturing Settings",
- "default_fg_warehouse")
- return {"wip_warehouse": wip_warehouse, "fg_warehouse": fg_warehouse}
-
-@frappe.whitelist()
-def make_new_timesheet(source_name, target_doc=None):
- po = frappe.get_doc('Production Order', source_name)
- ts = po.make_time_logs(open_new=True)
-
- if not ts or not ts.get('time_logs'):
- frappe.throw(_("Already completed"))
-
- return ts
-
-@frappe.whitelist()
-def stop_unstop(production_order, status):
- """ Called from client side on Stop/Unstop event"""
-
- if not frappe.has_permission("Production Order", "write"):
- frappe.throw(_("Not permitted"), frappe.PermissionError)
-
- pro_order = frappe.get_doc("Production Order", production_order)
- pro_order.update_status(status)
- pro_order.update_planned_qty()
- frappe.msgprint(_("Production Order has been {0}").format(status))
- pro_order.notify_update()
-
- return pro_order.status
-
-@frappe.whitelist()
-def query_sales_order(production_item):
- out = frappe.db.sql_list("""
- select distinct so.name from `tabSales Order` so, `tabSales Order Item` so_item
- where so_item.parent=so.name and so_item.item_code=%s and so.docstatus=1
- union
- select distinct so.name from `tabSales Order` so, `tabPacked Item` pi_item
- where pi_item.parent=so.name and pi_item.item_code=%s and so.docstatus=1
- """, (production_item, production_item))
-
- return out
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 8334f6b..b51420f 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -99,7 +99,7 @@
self.get_mr_items()
def get_so_items(self):
- so_list = [d.sales_order for d in self.sales_orders if d.sales_order]
+ so_list = [d.sales_order for d in self.get("sales_orders", []) if d.sales_order]
if not so_list:
msgprint(_("Please enter Sales Orders in the above table"))
return []
@@ -134,7 +134,7 @@
self.calculate_total_planned_qty()
def get_mr_items(self):
- mr_list = [d.material_request for d in self.material_requests if d.material_request]
+ mr_list = [d.material_request for d in self.get("material_requests", []) if d.material_request]
if not mr_list:
msgprint(_("Please enter Material Requests in the above table"))
return []
@@ -301,7 +301,6 @@
wo_list.extend(work_orders)
frappe.flags.mute_messages = False
-
if wo_list:
wo_list = ["""<a href="#Form/Work Order/%s" target="_blank">%s</a>""" % \
(p, p) for p in wo_list]
@@ -309,18 +308,20 @@
else :
msgprint(_("No Work Orders created"))
+
def make_work_order_for_sub_assembly_items(self, item):
work_orders = []
bom_data = {}
- get_sub_assembly_items(item.get("bom_no"), bom_data)
+ get_sub_assembly_items(item.get("bom_no"), bom_data, item.get("qty"))
for key, data in bom_data.items():
data.update({
- 'qty': data.get("stock_qty") * item.get("qty"),
+ 'qty': data.get("stock_qty"),
'production_plan': self.name,
'company': self.company,
- 'fg_warehouse': item.get("fg_warehouse")
+ 'fg_warehouse': item.get("fg_warehouse"),
+ 'update_consumed_material_cost_in_project': 0
})
work_order = self.create_work_order(data)
@@ -707,7 +708,7 @@
"description": item_details.get("description")
}
-def get_sub_assembly_items(bom_no, bom_data):
+def get_sub_assembly_items(bom_no, bom_data, qty):
data = get_children('BOM', parent = bom_no)
for d in data:
if d.expandable:
@@ -724,6 +725,6 @@
})
bom_item = bom_data.get(key)
- bom_item["stock_qty"] += d.stock_qty
+ bom_item["stock_qty"] += ((d.stock_qty * qty) / d.parent_bom_qty)
- get_sub_assembly_items(bom_item.get("bom_no"), bom_data)
+ get_sub_assembly_items(bom_item.get("bom_no"), bom_data, bom_item["stock_qty"])
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index 22613cc..ce7b4f9 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -4,16 +4,17 @@
frappe.ui.form.on("Work Order", {
setup: function(frm) {
frm.custom_make_buttons = {
- 'Stock Entry': 'Make Stock Entry',
- }
+ 'Stock Entry': 'Start',
+ 'Pick List': 'Create Pick List',
+ };
// Set query for warehouses
- frm.set_query("wip_warehouse", function(doc) {
+ frm.set_query("wip_warehouse", function() {
return {
filters: {
'company': frm.doc.company,
}
- }
+ };
});
frm.set_query("source_warehouse", function() {
@@ -21,7 +22,7 @@
filters: {
'company': frm.doc.company,
}
- }
+ };
});
frm.set_query("source_warehouse", "required_items", function() {
@@ -29,7 +30,7 @@
filters: {
'company': frm.doc.company,
}
- }
+ };
});
frm.set_query("sales_order", function() {
@@ -37,7 +38,7 @@
filters: {
"status": ["not in", ["Closed", "On Hold"]]
}
- }
+ };
});
frm.set_query("fg_warehouse", function() {
@@ -46,7 +47,7 @@
'company': frm.doc.company,
'is_group': 0
}
- }
+ };
});
frm.set_query("scrap_warehouse", function() {
@@ -55,17 +56,19 @@
'company': frm.doc.company,
'is_group': 0
}
- }
+ };
});
// Set query for BOM
frm.set_query("bom_no", function() {
if (frm.doc.production_item) {
- return{
+ return {
query: "erpnext.controllers.queries.bom",
filters: {item: cstr(frm.doc.production_item)}
- }
- } else msgprint(__("Please enter Production Item first"));
+ };
+ } else {
+ frappe.msgprint(__("Please enter Production Item first"));
+ }
});
// Set query for FG Item
@@ -76,7 +79,7 @@
['is_stock_item', '=',1],
['default_bom', '!=', '']
]
- }
+ };
});
// Set query for FG Item
@@ -85,12 +88,12 @@
filters:[
['Project', 'status', 'not in', 'Completed, Cancelled']
]
- }
+ };
});
// formatter for work order operation
frm.set_indicator_formatter('operation',
- function(doc) { return (frm.doc.qty==doc.completed_qty) ? "green" : "orange" });
+ function(doc) { return (frm.doc.qty==doc.completed_qty) ? "green" : "orange"; });
},
onload: function(frm) {
@@ -133,7 +136,7 @@
if(not_completed && not_completed.length) {
frm.add_custom_button(__('Create Job Card'), () => {
- frm.trigger("make_job_card")
+ frm.trigger("make_job_card");
}).addClass('btn-primary');
}
}
@@ -151,7 +154,7 @@
condition: (d) => {
if (d.allow_alternative_item) {return true;}
}
- })
+ });
});
}
}
@@ -285,13 +288,13 @@
if(!frm.doc.skip_transfer){
var pending_complete = frm.doc.material_transferred_for_manufacturing - frm.doc.produced_qty;
if(pending_complete) {
- var title = __('{0} items in progress', [pending_complete]);
var width = ((pending_complete / frm.doc.qty * 100) - added_min);
+ title = __('{0} items in progress', [pending_complete]);
bars.push({
'title': title,
'width': (width > 100 ? "99.5" : width) + '%',
'progress_class': 'progress-bar-warning'
- })
+ });
message = message + '. ' + title;
}
}
@@ -377,7 +380,7 @@
filters: [
["Sales Order","name", "in", r.message]
]
- }
+ };
});
}
});
@@ -401,10 +404,10 @@
frappe.model.set_value(row.doctype, row.name,
"available_qty_at_source_warehouse", r.message);
}
- })
+ });
}
}
-})
+});
frappe.ui.form.on("Work Order Operation", {
workstation: function(frm, cdt, cdn) {
@@ -421,7 +424,7 @@
erpnext.work_order.calculate_cost(frm.doc);
erpnext.work_order.calculate_total_cost(frm);
}
- })
+ });
}
},
time_in_mins: function(frm, cdt, cdn) {
@@ -447,10 +450,13 @@
const show_start_btn = (frm.doc.skip_transfer
|| frm.doc.transfer_material_against == 'Job Card') ? 0 : 1;
- if (show_start_btn){
+ if (show_start_btn) {
if ((flt(doc.material_transferred_for_manufacturing) < flt(doc.qty))
&& frm.doc.status != 'Stopped') {
frm.has_start_btn = true;
+ frm.add_custom_button(__('Create Pick List'), function() {
+ erpnext.work_order.create_pick_list(frm);
+ });
var start_btn = frm.add_custom_button(__('Start'), function() {
erpnext.work_order.make_se(frm, 'Material Transfer for Manufacture');
});
@@ -519,8 +525,8 @@
calculate_total_cost: function(frm) {
var variable_cost = frm.doc.actual_operating_cost ?
- flt(frm.doc.actual_operating_cost) : flt(frm.doc.planned_operating_cost)
- frm.set_value("total_operating_cost", (flt(frm.doc.additional_operating_cost) + variable_cost))
+ flt(frm.doc.actual_operating_cost) : flt(frm.doc.planned_operating_cost);
+ frm.set_value("total_operating_cost", (flt(frm.doc.additional_operating_cost) + variable_cost));
},
set_default_warehouse: function(frm) {
@@ -528,45 +534,72 @@
frappe.call({
method: "erpnext.manufacturing.doctype.work_order.work_order.get_default_warehouse",
callback: function(r) {
- if(!r.exe) {
+ if (!r.exe) {
frm.set_value("wip_warehouse", r.message.wip_warehouse);
- frm.set_value("fg_warehouse", r.message.fg_warehouse)
+ frm.set_value("fg_warehouse", r.message.fg_warehouse);
}
}
});
}
},
- make_se: function(frm, purpose) {
- if(!frm.doc.skip_transfer){
- var max = (purpose === "Manufacture") ?
- flt(frm.doc.material_transferred_for_manufacturing) - flt(frm.doc.produced_qty) :
- flt(frm.doc.qty) - flt(frm.doc.material_transferred_for_manufacturing);
+ get_max_transferable_qty: (frm, purpose) => {
+ let max = 0;
+ if (frm.doc.skip_transfer) return max;
+ if (purpose === 'Manufacture') {
+ max = flt(frm.doc.material_transferred_for_manufacturing) - flt(frm.doc.produced_qty);
} else {
- var max = flt(frm.doc.qty) - flt(frm.doc.produced_qty);
+ max = flt(frm.doc.qty) - flt(frm.doc.material_transferred_for_manufacturing);
}
+ return flt(max, precision('qty'));
+ },
- max = flt(max, precision("qty"));
- frappe.prompt({fieldtype:"Float", label: __("Qty for {0}", [purpose]), fieldname:"qty",
- description: __("Max: {0}", [max]), 'default': max }, function(data)
- {
- if(data.qty > max) {
- frappe.msgprint(__("Quantity must not be more than {0}", [max]));
- return;
- }
- frappe.call({
- method:"erpnext.manufacturing.doctype.work_order.work_order.make_stock_entry",
- args: {
- "work_order_id": frm.doc.name,
- "purpose": purpose,
- "qty": data.qty
- },
- callback: function(r) {
- var doclist = frappe.model.sync(r.message);
- frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
+ show_prompt_for_qty_input: function(frm, purpose) {
+ let max = this.get_max_transferable_qty(frm, purpose);
+ return new Promise((resolve, reject) => {
+ frappe.prompt({
+ fieldtype: 'Float',
+ label: __('Qty for {0}', [purpose]),
+ fieldname: 'qty',
+ description: __('Max: {0}', [max]),
+ default: max
+ }, data => {
+ if (data.qty > max) {
+ frappe.msgprint(__('Quantity must not be more than {0}', [max]));
+ reject();
}
+ data.purpose = purpose;
+ resolve(data);
+ }, __('Select Quantity'), __('Create'));
+ });
+ },
+
+ make_se: function(frm, purpose) {
+ this.show_prompt_for_qty_input(frm, purpose)
+ .then(data => {
+ return frappe.xcall('erpnext.manufacturing.doctype.work_order.work_order.make_stock_entry', {
+ 'work_order_id': frm.doc.name,
+ 'purpose': purpose,
+ 'qty': data.qty
+ });
+ }).then(stock_entry => {
+ frappe.model.sync(stock_entry);
+ frappe.set_route('Form', stock_entry.doctype, stock_entry.name);
});
- }, __("Select Quantity"), __('Create'));
+
+ },
+
+ create_pick_list: function(frm, purpose='Material Transfer for Manufacture') {
+ this.show_prompt_for_qty_input(frm, purpose)
+ .then(data => {
+ return frappe.xcall('erpnext.manufacturing.doctype.work_order.work_order.create_pick_list', {
+ 'source_name': frm.doc.name,
+ 'for_qty': data.qty
+ });
+ }).then(pick_list => {
+ frappe.model.sync(pick_list);
+ frappe.set_route('Form', pick_list.doctype, pick_list.name);
+ });
},
make_consumption_se: function(frm, backflush_raw_materials_based_on) {
@@ -606,6 +639,6 @@
frm.reload_doc();
}
}
- })
+ });
}
-}
+};
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.json b/erpnext/manufacturing/doctype/work_order/work_order.json
index 1534b59..0d073a2 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.json
+++ b/erpnext/manufacturing/doctype/work_order/work_order.json
@@ -1,484 +1,505 @@
{
- "allow_import": 1,
- "autoname": "naming_series:",
- "creation": "2013-01-10 16:34:16",
- "doctype": "DocType",
- "document_type": "Setup",
- "field_order": [
- "item",
- "naming_series",
- "status",
- "production_item",
- "item_name",
- "image",
- "bom_no",
- "allow_alternative_item",
- "use_multi_level_bom",
- "skip_transfer",
- "column_break1",
- "company",
- "qty",
- "material_transferred_for_manufacturing",
- "produced_qty",
- "sales_order",
- "project",
- "from_wip_warehouse",
- "warehouses",
- "wip_warehouse",
- "fg_warehouse",
- "column_break_12",
- "scrap_warehouse",
- "required_items_section",
- "required_items",
- "time",
- "planned_start_date",
- "actual_start_date",
- "column_break_13",
- "planned_end_date",
- "actual_end_date",
- "expected_delivery_date",
- "operations_section",
- "transfer_material_against",
- "operations",
- "section_break_22",
- "planned_operating_cost",
- "actual_operating_cost",
- "additional_operating_cost",
- "column_break_24",
- "total_operating_cost",
- "more_info",
- "description",
- "stock_uom",
- "column_break2",
- "material_request",
- "material_request_item",
- "sales_order_item",
- "production_plan",
- "production_plan_item",
- "product_bundle_item",
- "amended_from"
- ],
- "fields": [
- {
- "fieldname": "item",
- "fieldtype": "Section Break",
- "options": "fa fa-gift"
- },
- {
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "label": "Series",
- "options": "MFG-WO-.YYYY.-",
- "print_hide": 1,
- "reqd": 1,
- "set_only_once": 1
- },
- {
- "default": "Draft",
- "depends_on": "eval:!doc.__islocal",
- "fieldname": "status",
- "fieldtype": "Select",
- "label": "Status",
- "no_copy": 1,
- "oldfieldname": "status",
- "oldfieldtype": "Select",
- "options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nStopped\nCancelled",
- "read_only": 1,
- "reqd": 1,
- "search_index": 1
- },
- {
- "fieldname": "production_item",
- "fieldtype": "Link",
- "in_global_search": 1,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Item To Manufacture",
- "oldfieldname": "production_item",
- "oldfieldtype": "Link",
- "options": "Item",
- "reqd": 1
- },
- {
- "depends_on": "eval:doc.production_item",
- "fieldname": "item_name",
- "fieldtype": "Data",
- "label": "Item Name",
- "read_only": 1
- },
- {
- "fetch_from": "production_item.image",
- "fieldname": "image",
- "fieldtype": "Attach Image",
- "hidden": 1,
- "label": "Image",
- "options": "image",
- "print_hide": 1,
- "read_only": 1
- },
- {
- "fieldname": "bom_no",
- "fieldtype": "Link",
- "label": "BOM No",
- "oldfieldname": "bom_no",
- "oldfieldtype": "Link",
- "options": "BOM",
- "reqd": 1
- },
- {
- "default": "0",
- "fieldname": "allow_alternative_item",
- "fieldtype": "Check",
- "label": "Allow Alternative Item"
- },
- {
- "default": "1",
- "description": "Plan material for sub-assemblies",
- "fieldname": "use_multi_level_bom",
- "fieldtype": "Check",
- "label": "Use Multi-Level BOM",
- "print_hide": 1
- },
- {
- "default": "0",
- "description": "Check if material transfer entry is not required",
- "fieldname": "skip_transfer",
- "fieldtype": "Check",
- "label": "Skip Material Transfer to WIP Warehouse"
- },
- {
- "fieldname": "column_break1",
- "fieldtype": "Column Break",
- "oldfieldtype": "Column Break",
- "width": "50%"
- },
- {
- "fieldname": "company",
- "fieldtype": "Link",
- "label": "Company",
- "oldfieldname": "company",
- "oldfieldtype": "Link",
- "options": "Company",
- "remember_last_selected_value": 1,
- "reqd": 1
- },
- {
- "fieldname": "qty",
- "fieldtype": "Float",
- "label": "Qty To Manufacture",
- "oldfieldname": "qty",
- "oldfieldtype": "Currency",
- "reqd": 1
- },
- {
- "default": "0",
- "depends_on": "eval:doc.docstatus==1 && doc.skip_transfer==0",
- "fieldname": "material_transferred_for_manufacturing",
- "fieldtype": "Float",
- "label": "Material Transferred for Manufacturing",
- "no_copy": 1,
- "read_only": 1
- },
- {
- "default": "0",
- "depends_on": "eval:doc.docstatus==1",
- "fieldname": "produced_qty",
- "fieldtype": "Float",
- "label": "Manufactured Qty",
- "no_copy": 1,
- "oldfieldname": "produced_qty",
- "oldfieldtype": "Currency",
- "read_only": 1
- },
- {
- "allow_on_submit": 1,
- "fieldname": "sales_order",
- "fieldtype": "Link",
- "in_global_search": 1,
- "label": "Sales Order",
- "options": "Sales Order"
- },
- {
- "fieldname": "project",
- "fieldtype": "Link",
- "label": "Project",
- "oldfieldname": "project",
- "oldfieldtype": "Link",
- "options": "Project"
- },
- {
- "default": "0",
- "depends_on": "skip_transfer",
- "fieldname": "from_wip_warehouse",
- "fieldtype": "Check",
- "label": "Backflush Raw Materials From Work-in-Progress Warehouse"
- },
- {
- "fieldname": "warehouses",
- "fieldtype": "Section Break",
- "label": "Warehouses",
- "options": "fa fa-building"
- },
- {
- "fieldname": "wip_warehouse",
- "fieldtype": "Link",
- "label": "Work-in-Progress Warehouse",
- "options": "Warehouse"
- },
- {
- "fieldname": "fg_warehouse",
- "fieldtype": "Link",
- "label": "Target Warehouse",
- "options": "Warehouse"
- },
- {
- "fieldname": "column_break_12",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "scrap_warehouse",
- "fieldtype": "Link",
- "label": "Scrap Warehouse",
- "options": "Warehouse"
- },
- {
- "fieldname": "required_items_section",
- "fieldtype": "Section Break",
- "label": "Required Items"
- },
- {
- "fieldname": "required_items",
- "fieldtype": "Table",
- "label": "Required Items",
- "no_copy": 1,
- "options": "Work Order Item",
- "print_hide": 1
- },
- {
- "fieldname": "time",
- "fieldtype": "Section Break",
- "label": "Time",
- "options": "fa fa-time"
- },
- {
- "allow_on_submit": 1,
- "default": "now",
- "fieldname": "planned_start_date",
- "fieldtype": "Datetime",
- "label": "Planned Start Date",
- "reqd": 1
- },
- {
- "fieldname": "actual_start_date",
- "fieldtype": "Datetime",
- "label": "Actual Start Date",
- "read_only": 1
- },
- {
- "fieldname": "column_break_13",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "planned_end_date",
- "fieldtype": "Datetime",
- "label": "Planned End Date",
- "no_copy": 1,
- "read_only": 1
- },
- {
- "fieldname": "actual_end_date",
- "fieldtype": "Datetime",
- "label": "Actual End Date",
- "read_only": 1
- },
- {
- "allow_on_submit": 1,
- "fieldname": "expected_delivery_date",
- "fieldtype": "Date",
- "label": "Expected Delivery Date"
- },
- {
- "fieldname": "operations_section",
- "fieldtype": "Section Break",
- "label": "Operations",
- "options": "fa fa-wrench"
- },
- {
- "default": "Work Order",
- "depends_on": "operations",
- "fieldname": "transfer_material_against",
- "fieldtype": "Select",
- "label": "Transfer Material Against",
- "options": "\nWork Order\nJob Card"
- },
- {
- "fieldname": "operations",
- "fieldtype": "Table",
- "label": "Operations",
- "options": "Work Order Operation",
- "read_only": 1
- },
- {
- "depends_on": "operations",
- "fieldname": "section_break_22",
- "fieldtype": "Section Break",
- "label": "Operation Cost"
- },
- {
- "fieldname": "planned_operating_cost",
- "fieldtype": "Currency",
- "label": "Planned Operating Cost",
- "options": "Company:company:default_currency",
- "read_only": 1
- },
- {
- "fieldname": "actual_operating_cost",
- "fieldtype": "Currency",
- "label": "Actual Operating Cost",
- "no_copy": 1,
- "options": "Company:company:default_currency",
- "read_only": 1
- },
- {
- "fieldname": "additional_operating_cost",
- "fieldtype": "Currency",
- "label": "Additional Operating Cost",
- "no_copy": 1,
- "options": "Company:company:default_currency"
- },
- {
- "fieldname": "column_break_24",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "total_operating_cost",
- "fieldtype": "Currency",
- "label": "Total Operating Cost",
- "no_copy": 1,
- "options": "Company:company:default_currency",
- "read_only": 1
- },
- {
- "collapsible": 1,
- "fieldname": "more_info",
- "fieldtype": "Section Break",
- "label": "More Information",
- "options": "fa fa-file-text"
- },
- {
- "fieldname": "description",
- "fieldtype": "Small Text",
- "label": "Item Description",
- "read_only": 1
- },
- {
- "fieldname": "stock_uom",
- "fieldtype": "Link",
- "label": "Stock UOM",
- "oldfieldname": "stock_uom",
- "oldfieldtype": "Data",
- "options": "UOM",
- "read_only": 1
- },
- {
- "fieldname": "column_break2",
- "fieldtype": "Column Break",
- "width": "50%"
- },
- {
- "description": "Manufacture against Material Request",
- "fieldname": "material_request",
- "fieldtype": "Link",
- "label": "Material Request",
- "options": "Material Request"
- },
- {
- "fieldname": "material_request_item",
- "fieldtype": "Data",
- "hidden": 1,
- "label": "Material Request Item",
- "read_only": 1
- },
- {
- "fieldname": "sales_order_item",
- "fieldtype": "Data",
- "hidden": 1,
- "label": "Sales Order Item",
- "read_only": 1
- },
- {
- "fieldname": "production_plan",
- "fieldtype": "Link",
- "label": "Production Plan",
- "no_copy": 1,
- "options": "Production Plan",
- "print_hide": 1,
- "read_only": 1
- },
- {
- "fieldname": "production_plan_item",
- "fieldtype": "Data",
- "label": "Production Plan Item",
- "no_copy": 1,
- "print_hide": 1,
- "read_only": 1
- },
- {
- "fieldname": "product_bundle_item",
- "fieldtype": "Link",
- "label": "Product Bundle Item",
- "no_copy": 1,
- "options": "Item",
- "print_hide": 1,
- "read_only": 1
- },
- {
- "fieldname": "amended_from",
- "fieldtype": "Link",
- "ignore_user_permissions": 1,
- "label": "Amended From",
- "no_copy": 1,
- "oldfieldname": "amended_from",
- "oldfieldtype": "Data",
- "options": "Work Order",
- "read_only": 1
- }
- ],
- "icon": "fa fa-cogs",
- "idx": 1,
- "image_field": "image",
- "is_submittable": 1,
- "modified": "2019-05-27 09:36:16.707719",
- "modified_by": "Administrator",
- "module": "Manufacturing",
- "name": "Work Order",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "import": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Manufacturing User",
- "set_user_permissions": 1,
- "share": 1,
- "submit": 1,
- "write": 1
- },
- {
- "read": 1,
- "report": 1,
- "role": "Stock User"
- }
- ],
- "sort_order": "ASC",
- "title_field": "production_item",
- "track_changes": 1,
- "track_seen": 1
- }
\ No newline at end of file
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "creation": "2013-01-10 16:34:16",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+ "item",
+ "naming_series",
+ "status",
+ "production_item",
+ "item_name",
+ "image",
+ "bom_no",
+ "column_break1",
+ "company",
+ "qty",
+ "material_transferred_for_manufacturing",
+ "produced_qty",
+ "sales_order",
+ "project",
+ "settings_section",
+ "allow_alternative_item",
+ "use_multi_level_bom",
+ "column_break_18",
+ "skip_transfer",
+ "from_wip_warehouse",
+ "update_consumed_material_cost_in_project",
+ "warehouses",
+ "wip_warehouse",
+ "fg_warehouse",
+ "column_break_12",
+ "scrap_warehouse",
+ "required_items_section",
+ "required_items",
+ "time",
+ "planned_start_date",
+ "actual_start_date",
+ "column_break_13",
+ "planned_end_date",
+ "actual_end_date",
+ "expected_delivery_date",
+ "operations_section",
+ "transfer_material_against",
+ "operations",
+ "section_break_22",
+ "planned_operating_cost",
+ "actual_operating_cost",
+ "additional_operating_cost",
+ "column_break_24",
+ "total_operating_cost",
+ "more_info",
+ "description",
+ "stock_uom",
+ "column_break2",
+ "material_request",
+ "material_request_item",
+ "sales_order_item",
+ "production_plan",
+ "production_plan_item",
+ "product_bundle_item",
+ "amended_from"
+ ],
+ "fields": [
+ {
+ "fieldname": "item",
+ "fieldtype": "Section Break",
+ "options": "fa fa-gift"
+ },
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "no_copy": 1,
+ "options": "MFG-WO-.YYYY.-",
+ "print_hide": 1,
+ "reqd": 1,
+ "set_only_once": 1
+ },
+ {
+ "default": "Draft",
+ "depends_on": "eval:!doc.__islocal",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "label": "Status",
+ "no_copy": 1,
+ "oldfieldname": "status",
+ "oldfieldtype": "Select",
+ "options": "\nDraft\nSubmitted\nNot Started\nIn Process\nCompleted\nStopped\nCancelled",
+ "read_only": 1,
+ "reqd": 1,
+ "search_index": 1
+ },
+ {
+ "fieldname": "production_item",
+ "fieldtype": "Link",
+ "in_global_search": 1,
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Item To Manufacture",
+ "oldfieldname": "production_item",
+ "oldfieldtype": "Link",
+ "options": "Item",
+ "reqd": 1
+ },
+ {
+ "depends_on": "eval:doc.production_item",
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "label": "Item Name",
+ "read_only": 1
+ },
+ {
+ "fetch_from": "production_item.image",
+ "fieldname": "image",
+ "fieldtype": "Attach Image",
+ "hidden": 1,
+ "label": "Image",
+ "options": "image",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "bom_no",
+ "fieldtype": "Link",
+ "label": "BOM No",
+ "oldfieldname": "bom_no",
+ "oldfieldtype": "Link",
+ "options": "BOM",
+ "reqd": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "allow_alternative_item",
+ "fieldtype": "Check",
+ "label": "Allow Alternative Item"
+ },
+ {
+ "default": "1",
+ "description": "Plan material for sub-assemblies",
+ "fieldname": "use_multi_level_bom",
+ "fieldtype": "Check",
+ "label": "Use Multi-Level BOM",
+ "print_hide": 1
+ },
+ {
+ "default": "0",
+ "description": "Check if material transfer entry is not required",
+ "fieldname": "skip_transfer",
+ "fieldtype": "Check",
+ "label": "Skip Material Transfer to WIP Warehouse"
+ },
+ {
+ "fieldname": "column_break1",
+ "fieldtype": "Column Break",
+ "oldfieldtype": "Column Break",
+ "width": "50%"
+ },
+ {
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "oldfieldname": "company",
+ "oldfieldtype": "Link",
+ "options": "Company",
+ "remember_last_selected_value": 1,
+ "reqd": 1
+ },
+ {
+ "fieldname": "qty",
+ "fieldtype": "Float",
+ "label": "Qty To Manufacture",
+ "oldfieldname": "qty",
+ "oldfieldtype": "Currency",
+ "reqd": 1
+ },
+ {
+ "default": "0",
+ "depends_on": "eval:doc.docstatus==1 && doc.skip_transfer==0",
+ "fieldname": "material_transferred_for_manufacturing",
+ "fieldtype": "Float",
+ "label": "Material Transferred for Manufacturing",
+ "no_copy": 1,
+ "read_only": 1
+ },
+ {
+ "default": "0",
+ "depends_on": "eval:doc.docstatus==1",
+ "fieldname": "produced_qty",
+ "fieldtype": "Float",
+ "label": "Manufactured Qty",
+ "no_copy": 1,
+ "oldfieldname": "produced_qty",
+ "oldfieldtype": "Currency",
+ "read_only": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "sales_order",
+ "fieldtype": "Link",
+ "in_global_search": 1,
+ "label": "Sales Order",
+ "options": "Sales Order"
+ },
+ {
+ "fieldname": "project",
+ "fieldtype": "Link",
+ "label": "Project",
+ "oldfieldname": "project",
+ "oldfieldtype": "Link",
+ "options": "Project"
+ },
+ {
+ "default": "0",
+ "depends_on": "skip_transfer",
+ "fieldname": "from_wip_warehouse",
+ "fieldtype": "Check",
+ "label": "Backflush Raw Materials From Work-in-Progress Warehouse"
+ },
+ {
+ "fieldname": "warehouses",
+ "fieldtype": "Section Break",
+ "label": "Warehouses",
+ "options": "fa fa-building"
+ },
+ {
+ "fieldname": "wip_warehouse",
+ "fieldtype": "Link",
+ "label": "Work-in-Progress Warehouse",
+ "options": "Warehouse"
+ },
+ {
+ "fieldname": "fg_warehouse",
+ "fieldtype": "Link",
+ "label": "Target Warehouse",
+ "options": "Warehouse"
+ },
+ {
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "scrap_warehouse",
+ "fieldtype": "Link",
+ "label": "Scrap Warehouse",
+ "options": "Warehouse"
+ },
+ {
+ "fieldname": "required_items_section",
+ "fieldtype": "Section Break",
+ "label": "Required Items"
+ },
+ {
+ "fieldname": "required_items",
+ "fieldtype": "Table",
+ "label": "Required Items",
+ "no_copy": 1,
+ "options": "Work Order Item",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "time",
+ "fieldtype": "Section Break",
+ "label": "Time",
+ "options": "fa fa-time"
+ },
+ {
+ "allow_on_submit": 1,
+ "default": "now",
+ "fieldname": "planned_start_date",
+ "fieldtype": "Datetime",
+ "label": "Planned Start Date",
+ "reqd": 1
+ },
+ {
+ "fieldname": "actual_start_date",
+ "fieldtype": "Datetime",
+ "label": "Actual Start Date",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_13",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "planned_end_date",
+ "fieldtype": "Datetime",
+ "label": "Planned End Date",
+ "no_copy": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "actual_end_date",
+ "fieldtype": "Datetime",
+ "label": "Actual End Date",
+ "read_only": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "expected_delivery_date",
+ "fieldtype": "Date",
+ "label": "Expected Delivery Date"
+ },
+ {
+ "fieldname": "operations_section",
+ "fieldtype": "Section Break",
+ "label": "Operations",
+ "options": "fa fa-wrench"
+ },
+ {
+ "default": "Work Order",
+ "depends_on": "operations",
+ "fieldname": "transfer_material_against",
+ "fieldtype": "Select",
+ "label": "Transfer Material Against",
+ "options": "\nWork Order\nJob Card"
+ },
+ {
+ "fieldname": "operations",
+ "fieldtype": "Table",
+ "label": "Operations",
+ "options": "Work Order Operation",
+ "read_only": 1
+ },
+ {
+ "depends_on": "operations",
+ "fieldname": "section_break_22",
+ "fieldtype": "Section Break",
+ "label": "Operation Cost"
+ },
+ {
+ "fieldname": "planned_operating_cost",
+ "fieldtype": "Currency",
+ "label": "Planned Operating Cost",
+ "options": "Company:company:default_currency",
+ "read_only": 1
+ },
+ {
+ "fieldname": "actual_operating_cost",
+ "fieldtype": "Currency",
+ "label": "Actual Operating Cost",
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "read_only": 1
+ },
+ {
+ "fieldname": "additional_operating_cost",
+ "fieldtype": "Currency",
+ "label": "Additional Operating Cost",
+ "no_copy": 1,
+ "options": "Company:company:default_currency"
+ },
+ {
+ "fieldname": "column_break_24",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "total_operating_cost",
+ "fieldtype": "Currency",
+ "label": "Total Operating Cost",
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "read_only": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "more_info",
+ "fieldtype": "Section Break",
+ "label": "More Information",
+ "options": "fa fa-file-text"
+ },
+ {
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Item Description",
+ "read_only": 1
+ },
+ {
+ "fieldname": "stock_uom",
+ "fieldtype": "Link",
+ "label": "Stock UOM",
+ "oldfieldname": "stock_uom",
+ "oldfieldtype": "Data",
+ "options": "UOM",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break2",
+ "fieldtype": "Column Break",
+ "width": "50%"
+ },
+ {
+ "description": "Manufacture against Material Request",
+ "fieldname": "material_request",
+ "fieldtype": "Link",
+ "label": "Material Request",
+ "options": "Material Request"
+ },
+ {
+ "fieldname": "material_request_item",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Material Request Item",
+ "read_only": 1
+ },
+ {
+ "fieldname": "sales_order_item",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Sales Order Item",
+ "read_only": 1
+ },
+ {
+ "fieldname": "production_plan",
+ "fieldtype": "Link",
+ "label": "Production Plan",
+ "no_copy": 1,
+ "options": "Production Plan",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "production_plan_item",
+ "fieldtype": "Data",
+ "label": "Production Plan Item",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "product_bundle_item",
+ "fieldtype": "Link",
+ "label": "Product Bundle Item",
+ "no_copy": 1,
+ "options": "Item",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Amended From",
+ "no_copy": 1,
+ "oldfieldname": "amended_from",
+ "oldfieldtype": "Data",
+ "options": "Work Order",
+ "read_only": 1
+ },
+ {
+ "fieldname": "settings_section",
+ "fieldtype": "Section Break",
+ "label": "Settings"
+ },
+ {
+ "fieldname": "column_break_18",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "1",
+ "fieldname": "update_consumed_material_cost_in_project",
+ "fieldtype": "Check",
+ "label": "Update Consumed Material Cost In Project"
+ }
+ ],
+ "icon": "fa fa-cogs",
+ "idx": 1,
+ "image_field": "image",
+ "is_submittable": 1,
+ "modified": "2019-08-28 12:29:35.315239",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "Work Order",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "import": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Manufacturing User",
+ "set_user_permissions": 1,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "read": 1,
+ "report": 1,
+ "role": "Stock User"
+ }
+ ],
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "title_field": "production_item",
+ "track_changes": 1,
+ "track_seen": 1
+}
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index 2b70325..a636b87 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -19,6 +19,7 @@
from frappe.utils.csvutils import getlink
from erpnext.stock.utils import get_bin, validate_warehouse_company, get_latest_stock_qty
from erpnext.utilities.transaction_base import validate_uom_is_integer
+from frappe.model.mapper import get_mapped_doc
class OverProductionError(frappe.ValidationError): pass
class StockOverProductionError(frappe.ValidationError): pass
@@ -707,3 +708,46 @@
for d in work_order.operations:
if d.operation == operation and d.workstation == workstation:
return d
+
+@frappe.whitelist()
+def create_pick_list(source_name, target_doc=None, for_qty=None):
+ for_qty = for_qty or json.loads(target_doc).get('for_qty')
+ max_finished_goods_qty = frappe.db.get_value('Work Order', source_name, 'qty')
+ def update_item_quantity(source, target, source_parent):
+ pending_to_issue = flt(source.required_qty) - flt(source.transferred_qty)
+ desire_to_transfer = flt(source.required_qty) / max_finished_goods_qty * flt(for_qty)
+
+ qty = 0
+ if desire_to_transfer <= pending_to_issue:
+ qty = desire_to_transfer
+ elif pending_to_issue > 0:
+ qty = pending_to_issue
+
+ if qty:
+ target.qty = qty
+ target.stock_qty = qty
+ target.uom = frappe.get_value('Item', source.item_code, 'stock_uom')
+ target.stock_uom = target.uom
+ target.conversion_factor = 1
+ else:
+ target.delete()
+
+ doc = get_mapped_doc('Work Order', source_name, {
+ 'Work Order': {
+ 'doctype': 'Pick List',
+ 'validation': {
+ 'docstatus': ['=', 1]
+ }
+ },
+ 'Work Order Item': {
+ 'doctype': 'Pick List Item',
+ 'postprocess': update_item_quantity,
+ 'condition': lambda doc: abs(doc.transferred_qty) < abs(doc.required_qty)
+ },
+ }, target_doc)
+
+ doc.for_qty = for_qty
+
+ doc.set_item_locations()
+
+ return doc
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/work_order/work_order_dashboard.py b/erpnext/manufacturing/doctype/work_order/work_order_dashboard.py
index 3fe5282..0d3c30e 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order_dashboard.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order_dashboard.py
@@ -6,7 +6,7 @@
'fieldname': 'work_order',
'transactions': [
{
- 'items': ['Stock Entry', 'Job Card']
+ 'items': ['Pick List', 'Stock Entry', 'Job Card']
}
]
}
\ No newline at end of file
diff --git a/erpnext/manufacturing/page/bom_comparison_tool/__init__.py b/erpnext/manufacturing/page/bom_comparison_tool/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/manufacturing/page/bom_comparison_tool/__init__.py
diff --git a/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js
new file mode 100644
index 0000000..7152d3d
--- /dev/null
+++ b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.js
@@ -0,0 +1,213 @@
+frappe.pages['bom-comparison-tool'].on_page_load = function(wrapper) {
+ var page = frappe.ui.make_app_page({
+ parent: wrapper,
+ title: __('BOM Comparison Tool'),
+ single_column: true
+ });
+
+ new erpnext.BOMComparisonTool(page);
+}
+
+erpnext.BOMComparisonTool = class BOMComparisonTool {
+ constructor(page) {
+ this.page = page;
+ this.make_form();
+ }
+
+ make_form() {
+ this.form = new frappe.ui.FieldGroup({
+ fields: [
+ {
+ label: __('BOM 1'),
+ fieldname: 'name1',
+ fieldtype: 'Link',
+ options: 'BOM',
+ change: () => this.fetch_and_render()
+ },
+ {
+ fieldtype: 'Column Break'
+ },
+ {
+ label: __('BOM 2'),
+ fieldname: 'name2',
+ fieldtype: 'Link',
+ options: 'BOM',
+ change: () => this.fetch_and_render()
+ },
+ {
+ fieldtype: 'Section Break'
+ },
+ {
+ fieldtype: 'HTML',
+ fieldname: 'preview'
+ }
+ ],
+ body: this.page.body
+ });
+ this.form.make();
+ }
+
+ fetch_and_render() {
+ let { name1, name2 } = this.form.get_values();
+ if (!(name1 && name2)) {
+ this.form.get_field('preview').html('');
+ return;
+ }
+
+ // set working state
+ this.form.get_field('preview').html(`
+ <div class="text-muted margin-top">
+ ${__("Fetching...")}
+ </div>
+ `);
+
+ frappe.call('erpnext.manufacturing.doctype.bom.bom.get_bom_diff', {
+ bom1: name1,
+ bom2: name2
+ }).then(r => {
+ let diff = r.message;
+ frappe.model.with_doctype('BOM', () => {
+ this.render('BOM', name1, name2, diff);
+ });
+ });
+ }
+
+ render(doctype, name1, name2, diff) {
+
+ let change_html = (title, doctype, changed) => {
+ let values_changed = this.get_changed_values(doctype, changed)
+ .map(change => {
+ let [fieldname, value1, value2] = change;
+ return `
+ <tr>
+ <td>${frappe.meta.get_label(doctype, fieldname)}</td>
+ <td>${value1}</td>
+ <td>${value2}</td>
+ </tr>
+ `;
+ })
+ .join('');
+
+ return `
+ <h4 class="margin-top">${title}</h4>
+ <div>
+ <table class="table table-bordered">
+ <tr>
+ <th width="33%">${__('Field')}</th>
+ <th width="33%">${name1}</th>
+ <th width="33%">${name2}</th>
+ </tr>
+ ${values_changed}
+ </table>
+ </div>
+ `;
+ }
+
+ let value_changes = change_html(__('Values Changed'), doctype, diff.changed);
+
+ let row_changes_by_fieldname = group_items(diff.row_changed, change => change[0]);
+
+ let table_changes = Object.keys(row_changes_by_fieldname).map(fieldname => {
+ let changes = row_changes_by_fieldname[fieldname];
+ let df = frappe.meta.get_docfield(doctype, fieldname);
+
+ let html = changes.map(change => {
+ let [fieldname,, item_code, changes] = change;
+ let df = frappe.meta.get_docfield(doctype, fieldname);
+ let child_doctype = df.options;
+ let values_changed = this.get_changed_values(child_doctype, changes);
+
+ return values_changed.map((change, i) => {
+ let [fieldname, value1, value2] = change;
+ let th = i === 0
+ ? `<th rowspan="${values_changed.length}">${item_code}</th>`
+ : '';
+ return `
+ <tr>
+ ${th}
+ <td>${frappe.meta.get_label(child_doctype, fieldname)}</td>
+ <td>${value1}</td>
+ <td>${value2}</td>
+ </tr>
+ `;
+ }).join('');
+ }).join('');
+
+ return `
+ <h4 class="margin-top">${__('Changes in {0}', [df.label])}</h4>
+ <table class="table table-bordered">
+ <tr>
+ <th width="25%">${__('Item Code')}</th>
+ <th width="25%">${__('Field')}</th>
+ <th width="25%">${name1}</th>
+ <th width="25%">${name2}</th>
+ </tr>
+ ${html}
+ </table>
+ `;
+ }).join('');
+
+ let get_added_removed_html = (title, grouped_items) => {
+ return Object.keys(grouped_items).map(fieldname => {
+ let rows = grouped_items[fieldname];
+ let df = frappe.meta.get_docfield(doctype, fieldname);
+ let fields = frappe.meta.get_docfields(df.options)
+ .filter(df => df.in_list_view);
+
+ let html = rows.map(row => {
+ let [, doc] = row;
+ let cells = fields
+ .map(df => `<td>${doc[df.fieldname]}</td>`)
+ .join('');
+ return `<tr>${cells}</tr>`;
+ }).join('');
+
+ let header = fields.map(df => `<th>${df.label}</th>`).join('');
+ return `
+ <h4 class="margin-top">${$.format(title, [df.label])}</h4>
+ <table class="table table-bordered">
+ <tr>${header}</tr>
+ ${html}
+ </table>
+ `;
+ }).join('');
+ };
+
+ let added_by_fieldname = group_items(diff.added, change => change[0]);
+ let removed_by_fieldname = group_items(diff.removed, change => change[0]);
+
+ let added_html = get_added_removed_html(__('Rows Added in {0}'), added_by_fieldname);
+ let removed_html = get_added_removed_html(__('Rows Removed in {0}'), removed_by_fieldname);
+
+ let html = `
+ ${value_changes}
+ ${table_changes}
+ ${added_html}
+ ${removed_html}
+ `;
+
+ this.form.get_field('preview').html(html);
+ }
+
+ get_changed_values(doctype, changed) {
+ return changed.filter(change => {
+ let [fieldname, value1, value2] = change;
+ if (!value1) value1 = '';
+ if (!value2) value2 = '';
+ if (value1 === value2) return false;
+ let df = frappe.meta.get_docfield(doctype, fieldname);
+ if (!df) return false;
+ if (df.hidden) return false;
+ return true;
+ });
+ }
+};
+
+function group_items(array, fn) {
+ return array.reduce((acc, item) => {
+ let key = fn(item);
+ acc[key] = acc[key] || [];
+ acc[key].push(item);
+ return acc;
+ }, {});
+}
diff --git a/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.json b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.json
new file mode 100644
index 0000000..067a106
--- /dev/null
+++ b/erpnext/manufacturing/page/bom_comparison_tool/bom_comparison_tool.json
@@ -0,0 +1,30 @@
+{
+ "content": null,
+ "creation": "2019-07-29 13:24:38.201981",
+ "docstatus": 0,
+ "doctype": "Page",
+ "idx": 0,
+ "modified": "2019-07-29 13:24:38.201981",
+ "modified_by": "Administrator",
+ "module": "Manufacturing",
+ "name": "bom-comparison-tool",
+ "owner": "Administrator",
+ "page_name": "BOM Comparison Tool",
+ "restrict_to_domain": "Manufacturing",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "Manufacturing User"
+ },
+ {
+ "role": "Manufacturing Manager"
+ }
+ ],
+ "script": null,
+ "standard": "Yes",
+ "style": null,
+ "system_page": 0,
+ "title": "BOM Comparison Tool"
+}
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index b6ea542..7c1d8a0 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -605,7 +605,6 @@
execute:frappe.delete_doc("Report", "Inactive Items")
erpnext.patches.v11_1.delete_scheduling_tool
erpnext.patches.v12_0.rename_tolerance_fields
-erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019
execute:frappe.delete_doc_if_exists("Page", "support-analytics")
erpnext.patches.v12_0.remove_patient_medical_record_page
erpnext.patches.v11_1.move_customer_lead_to_dynamic_column
@@ -626,3 +625,13 @@
erpnext.patches.v12_0.update_ewaybill_field_position
erpnext.patches.v12_0.create_accounting_dimensions_in_missing_doctypes
erpnext.patches.v11_1.set_status_for_material_request_type_manufacture
+erpnext.patches.v12_0.move_plaid_settings_to_doctype
+execute:frappe.reload_doc('desk', 'doctype','dashboard_chart_link')
+execute:frappe.reload_doc('desk', 'doctype','dashboard')
+execute:frappe.reload_doc('desk', 'doctype','dashboard_chart_source')
+execute:frappe.reload_doc('desk', 'doctype','dashboard_chart')
+erpnext.patches.v12_0.add_default_dashboards
+erpnext.patches.v12_0.remove_bank_remittance_custom_fields
+erpnext.patches.v12_0.generate_leave_ledger_entries
+erpnext.patches.v12_0.move_credit_limit_to_customer_credit_limit
+erpnext.patches.v12_0.add_variant_of_in_item_attribute_table
diff --git a/erpnext/patches/v12_0/add_default_dashboards.py b/erpnext/patches/v12_0/add_default_dashboards.py
new file mode 100644
index 0000000..ab92fba
--- /dev/null
+++ b/erpnext/patches/v12_0/add_default_dashboards.py
@@ -0,0 +1,8 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+import frappe
+from erpnext.setup.setup_wizard.operations.install_fixtures import add_dashboards
+
+def execute():
+ add_dashboards()
diff --git a/erpnext/patches/v12_0/add_variant_of_in_item_attribute_table.py b/erpnext/patches/v12_0/add_variant_of_in_item_attribute_table.py
index bc61190..893f7a4 100644
--- a/erpnext/patches/v12_0/add_variant_of_in_item_attribute_table.py
+++ b/erpnext/patches/v12_0/add_variant_of_in_item_attribute_table.py
@@ -1,8 +1,9 @@
import frappe
def execute():
- frappe.db.sql('''
- UPDATE `tabItem Variant Attribute` t1
- INNER JOIN `tabItem` t2 ON t2.name = t1.parent
- SET t1.variant_of = t2.variant_of
- ''')
+ frappe.reload_doc('stock', 'doctype', 'item_variant_attribute')
+ frappe.db.sql('''
+ UPDATE `tabItem Variant Attribute` t1
+ INNER JOIN `tabItem` t2 ON t2.name = t1.parent
+ SET t1.variant_of = t2.variant_of
+ ''')
diff --git a/erpnext/patches/v12_0/generate_leave_ledger_entries.py b/erpnext/patches/v12_0/generate_leave_ledger_entries.py
new file mode 100644
index 0000000..5e91449
--- /dev/null
+++ b/erpnext/patches/v12_0/generate_leave_ledger_entries.py
@@ -0,0 +1,87 @@
+# Copyright (c) 2018, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.utils import getdate, today
+
+def execute():
+ """ Generates leave ledger entries for leave allocation/application/encashment
+ for last allocation """
+ frappe.reload_doc("HR", "doctype", "Leave Ledger Entry")
+ frappe.reload_doc("HR", "doctype", "Leave Encashment")
+ if frappe.db.a_row_exists("Leave Ledger Entry"):
+ return
+
+ if not frappe.get_meta("Leave Allocation").has_field("unused_leaves"):
+ frappe.reload_doc("HR", "doctype", "Leave Allocation")
+ update_leave_allocation_fieldname()
+
+ generate_allocation_ledger_entries()
+ generate_application_leave_ledger_entries()
+ generate_encashment_leave_ledger_entries()
+ generate_expiry_allocation_ledger_entries()
+
+def update_leave_allocation_fieldname():
+ ''' maps data from old field to the new field '''
+ frappe.db.sql("""
+ UPDATE `tabLeave Allocation`
+ SET `unused_leaves` = `carry_forwarded_leaves`
+ """)
+
+def generate_allocation_ledger_entries():
+ ''' fix ledger entries for missing leave allocation transaction '''
+ allocation_list = get_allocation_records()
+
+ for allocation in allocation_list:
+ if not frappe.db.exists("Leave Ledger Entry", {'transaction_type': 'Leave Allocation', 'transaction_name': allocation.name}):
+ allocation.update(dict(doctype="Leave Allocation"))
+ allocation_obj = frappe.get_doc(allocation)
+ allocation_obj.create_leave_ledger_entry()
+
+def generate_application_leave_ledger_entries():
+ ''' fix ledger entries for missing leave application transaction '''
+ leave_applications = get_leaves_application_records()
+
+ for application in leave_applications:
+ if not frappe.db.exists("Leave Ledger Entry", {'transaction_type': 'Leave Application', 'transaction_name': application.name}):
+ application.update(dict(doctype="Leave Application"))
+ frappe.get_doc(application).create_leave_ledger_entry()
+
+def generate_encashment_leave_ledger_entries():
+ ''' fix ledger entries for missing leave encashment transaction '''
+ leave_encashments = get_leave_encashment_records()
+
+ for encashment in leave_encashments:
+ if not frappe.db.exists("Leave Ledger Entry", {'transaction_type': 'Leave Encashment', 'transaction_name': encashment.name}):
+ encashment.update(dict(doctype="Leave Encashment"))
+ frappe.get_doc(encashment).create_leave_ledger_entry()
+
+def generate_expiry_allocation_ledger_entries():
+ ''' fix ledger entries for missing leave allocation transaction '''
+ from erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry import expire_allocation
+ allocation_list = get_allocation_records()
+
+ for allocation in allocation_list:
+ if not frappe.db.exists("Leave Ledger Entry", {'transaction_type': 'Leave Allocation', 'transaction_name': allocation.name, 'is_expired': 1}):
+ allocation.update(dict(doctype="Leave Allocation"))
+ allocation_obj = frappe.get_doc(allocation)
+ if allocation_obj.to_date <= getdate(today()):
+ expire_allocation(allocation_obj)
+
+def get_allocation_records():
+ return frappe.get_all("Leave Allocation", filters={
+ "docstatus": 1
+ }, fields=['name', 'employee', 'leave_type', 'new_leaves_allocated',
+ 'unused_leaves', 'from_date', 'to_date', 'carry_forward'
+ ], order_by='to_date ASC')
+
+def get_leaves_application_records():
+ return frappe.get_all("Leave Application", filters={
+ "docstatus": 1
+ }, fields=['name', 'employee', 'leave_type', 'total_leave_days', 'from_date', 'to_date'])
+
+def get_leave_encashment_records():
+ return frappe.get_all("Leave Encashment", filters={
+ "docstatus": 1
+ }, fields=['name', 'employee', 'leave_type', 'encashable_days', 'encashment_date'])
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/make_custom_fields_for_bank_remittance.py b/erpnext/patches/v12_0/make_custom_fields_for_bank_remittance.py
deleted file mode 100644
index 3d4a995..0000000
--- a/erpnext/patches/v12_0/make_custom_fields_for_bank_remittance.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.regional.india.setup import make_custom_fields
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "tax_category")
- frappe.reload_doc("stock", "doctype", "item_manufacturer")
- company = frappe.get_all('Company', filters = {'country': 'India'})
- if not company:
- return
-
- make_custom_fields()
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/move_credit_limit_to_customer_credit_limit.py b/erpnext/patches/v12_0/move_credit_limit_to_customer_credit_limit.py
new file mode 100644
index 0000000..c9293b9
--- /dev/null
+++ b/erpnext/patches/v12_0/move_credit_limit_to_customer_credit_limit.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ ''' Move credit limit and bypass credit limit to the child table of customer credit limit '''
+ frappe.reload_doc("Selling", "doctype", "Customer Credit Limit")
+ frappe.reload_doc("Selling", "doctype", "Customer")
+ frappe.reload_doc("Setup", "doctype", "Customer Group")
+
+ if frappe.db.a_row_exists("Customer Credit Limit"):
+ return
+
+ move_credit_limit_to_child_table()
+
+def move_credit_limit_to_child_table():
+ ''' maps data from old field to the new field in the child table '''
+
+ companies = frappe.get_all("Company", 'name')
+ for doctype in ("Customer", "Customer Group"):
+ fields = ""
+ if doctype == "Customer" \
+ and frappe.db.has_column('Customer', 'bypass_credit_limit_check_at_sales_order'):
+ fields = ", bypass_credit_limit_check_at_sales_order"
+
+ credit_limit_records = frappe.db.sql('''
+ SELECT name, credit_limit {0}
+ FROM `tab{1}` where credit_limit > 0
+ '''.format(fields, doctype), as_dict=1) #nosec
+
+ for record in credit_limit_records:
+ doc = frappe.get_doc(doctype, record.name)
+ for company in companies:
+ row = frappe._dict({
+ 'credit_limit': record.credit_limit,
+ 'company': company.name
+ })
+ if doctype == "Customer":
+ row.bypass_credit_limit_check = record.bypass_credit_limit_check_at_sales_order
+
+ doc.append("credit_limits", row)
+
+ for row in doc.credit_limits:
+ row.db_insert()
diff --git a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py
index 02203d2..9f4c445 100644
--- a/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py
+++ b/erpnext/patches/v12_0/move_item_tax_to_item_tax_template.py
@@ -82,7 +82,7 @@
account_name = " - ".join(parts[:-1])
company = frappe.db.get_value("Company", filters={"abbr": parts[-1]})
parent_account = frappe.db.get_value("Account",
- filters={"account_type": "Tax", "root_type": "Liability", "is_group": 0}, fieldname="parent_account")
+ filters={"account_type": "Tax", "root_type": "Liability", "is_group": 0, "company": company}, fieldname="parent_account")
frappe.get_doc({
"doctype": "Account",
diff --git a/erpnext/patches/v12_0/move_plaid_settings_to_doctype.py b/erpnext/patches/v12_0/move_plaid_settings_to_doctype.py
new file mode 100644
index 0000000..8e60d33
--- /dev/null
+++ b/erpnext/patches/v12_0/move_plaid_settings_to_doctype.py
@@ -0,0 +1,22 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ frappe.reload_doc("erpnext_integrations", "doctype", "plaid_settings")
+ plaid_settings = frappe.get_single("Plaid Settings")
+ if plaid_settings.enabled:
+ if not (frappe.conf.plaid_client_id and frappe.conf.plaid_env \
+ and frappe.conf.plaid_public_key and frappe.conf.plaid_secret):
+ plaid_settings.enabled = 0
+ else:
+ plaid_settings.update({
+ "plaid_client_id": frappe.conf.plaid_client_id,
+ "plaid_public_key": frappe.conf.plaid_public_key,
+ "plaid_env": frappe.conf.plaid_env,
+ "plaid_secret": frappe.conf.plaid_secret
+ })
+ plaid_settings.flags.ignore_mandatory = True
+ plaid_settings.save()
diff --git a/erpnext/patches/v12_0/remove_bank_remittance_custom_fields.py b/erpnext/patches/v12_0/remove_bank_remittance_custom_fields.py
new file mode 100644
index 0000000..d1446b3
--- /dev/null
+++ b/erpnext/patches/v12_0/remove_bank_remittance_custom_fields.py
@@ -0,0 +1,14 @@
+from __future__ import unicode_literals
+import frappe
+from erpnext.regional.india.setup import make_custom_fields
+
+def execute():
+ frappe.reload_doc("accounts", "doctype", "tax_category")
+ frappe.reload_doc("stock", "doctype", "item_manufacturer")
+ company = frappe.get_all('Company', filters = {'country': 'India'})
+ if not company:
+ return
+ if frappe.db.exists("Custom Field", "Company-bank_remittance_section"):
+ deprecated_fields = ['bank_remittance_section', 'client_code', 'remittance_column_break', 'product_code']
+ for i in range(len(deprecated_fields)):
+ frappe.delete_doc("Custom Field", 'Company-'+deprecated_fields[i])
\ No newline at end of file
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index 101d903..3eea390 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -147,6 +147,15 @@
calculate_time_and_amount(frm);
},
+ task: (frm, cdt, cdn) => {
+ let row = frm.selected_doc;
+ if (row.task) {
+ frappe.db.get_value("Task", row.task, "project", (r) => {
+ frappe.model.set_value(cdt, cdn, "project", r.project);
+ });
+ }
+ },
+
from_time: function(frm, cdt, cdn) {
calculate_end_time(frm, cdt, cdn);
},
@@ -200,9 +209,6 @@
},
activity_type: function(frm, cdt, cdn) {
- frm.script_manager.copy_from_first_row('time_logs', frm.selected_doc,
- 'project');
-
frappe.call({
method: "erpnext.projects.doctype.timesheet.timesheet.get_activity_cost",
args: {
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index df9a6ba..9ee2927 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -96,7 +96,7 @@
for time in self.time_logs:
if time.from_time and time.to_time:
- if flt(std_working_hours) > 0:
+ if flt(std_working_hours) and date_diff(time.to_time, time.from_time):
time.hours = flt(std_working_hours) * date_diff(time.to_time, time.from_time)
else:
if not time.hours:
@@ -145,12 +145,17 @@
def validate_time_logs(self):
for data in self.get('time_logs'):
self.validate_overlap(data)
+ self.validate_task_project()
def validate_overlap(self, data):
settings = frappe.get_single('Projects Settings')
self.validate_overlap_for("user", data, self.user, settings.ignore_user_time_overlap)
self.validate_overlap_for("employee", data, self.employee, settings.ignore_employee_time_overlap)
+ def validate_task_project(self):
+ for log in self.time_logs:
+ log.project = log.project or frappe.db.get_value("Task", log.task, "project")
+
def validate_overlap_for(self, fieldname, args, value, ignore_validation=False):
if not value or ignore_validation:
return
diff --git a/erpnext/public/js/call_popup/call_popup.js b/erpnext/public/js/call_popup/call_popup.js
index 5278b32..5e4d4a5 100644
--- a/erpnext/public/js/call_popup/call_popup.js
+++ b/erpnext/public/js/call_popup/call_popup.js
@@ -28,12 +28,12 @@
'depends_on': () => this.call_log.lead
}, {
'fieldtype': 'Button',
- 'label': __('Make New Contact'),
+ 'label': __('Create New Contact'),
'click': () => frappe.new_doc('Contact', { 'mobile_no': this.caller_number }),
'depends_on': () => !this.get_caller_name()
}, {
'fieldtype': 'Button',
- 'label': __('Make New Lead'),
+ 'label': __('Create New Lead'),
'click': () => frappe.new_doc('Lead', { 'mobile_no': this.caller_number }),
'depends_on': () => !this.get_caller_name()
}, {
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 7cf2181..2ece711 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -44,6 +44,12 @@
this.calculate_contribution();
}
+ // Update paid amount on return/debit note creation
+ if(this.frm.doc.doctype === "Purchase Invoice" && this.frm.doc.is_return
+ && (this.frm.doc.grand_total > this.frm.doc.paid_amount)) {
+ this.frm.doc.paid_amount = flt(this.frm.doc.grand_total, precision("grand_total"));
+ }
+
this.frm.refresh_fields();
},
diff --git a/erpnext/public/js/purchase_trends_filters.js b/erpnext/public/js/purchase_trends_filters.js
index 595a138..cd767f5 100644
--- a/erpnext/public/js/purchase_trends_filters.js
+++ b/erpnext/public/js/purchase_trends_filters.js
@@ -4,6 +4,14 @@
erpnext.get_purchase_trends_filters = function() {
return [
{
+ "fieldname":"company",
+ "label": __("Company"),
+ "fieldtype": "Link",
+ "options": "Company",
+ "reqd": 1,
+ "default": frappe.defaults.get_user_default("Company")
+ },
+ {
"fieldname":"period",
"label": __("Period"),
"fieldtype": "Select",
@@ -16,6 +24,23 @@
"default": "Monthly"
},
{
+ "fieldname":"fiscal_year",
+ "label": __("Fiscal Year"),
+ "fieldtype": "Link",
+ "options":'Fiscal Year',
+ "default": frappe.sys_defaults.fiscal_year
+ },
+ {
+ "fieldname":"period_based_on",
+ "label": __("Period based On"),
+ "fieldtype": "Select",
+ "options": [
+ { "value": "posting_date", "label": __("Posting Date") },
+ { "value": "bill_date", "label": __("Billing Date") },
+ ],
+ "default": "posting_date"
+ },
+ {
"fieldname":"based_on",
"label": __("Based On"),
"fieldtype": "Select",
@@ -39,19 +64,5 @@
],
"default": ""
},
- {
- "fieldname":"fiscal_year",
- "label": __("Fiscal Year"),
- "fieldtype": "Link",
- "options":'Fiscal Year',
- "default": frappe.sys_defaults.fiscal_year
- },
- {
- "fieldname":"company",
- "label": __("Company"),
- "fieldtype": "Link",
- "options": "Company",
- "default": frappe.defaults.get_user_default("Company")
- },
];
}
diff --git a/erpnext/public/js/templates/contact_list.html b/erpnext/public/js/templates/contact_list.html
index 893b4e0..50fbfd9 100644
--- a/erpnext/public/js/templates/contact_list.html
+++ b/erpnext/public/js/templates/contact_list.html
@@ -14,20 +14,33 @@
style="margin-top:-3px; margin-right: -5px;">
{%= __("Edit") %}</a>
</p>
- {% if (contact_list[i].phone || contact_list[i].mobile_no ||
- contact_list[i].email_id) { %}
+ {% if (contact_list[i].phones || contact_list[i].email_ids) { %}
<p>
- {% if(contact_list[i].phone) { %}
- {%= __("Phone") %}: {%= contact_list[i].phone %}<br>
- {% } %}
- {% if(contact_list[i].mobile_no) { %}
- {%= __("Mobile No.") %}: {%= contact_list[i].mobile_no %}<br>
- {% } %}
- {% if(contact_list[i].email_id) { %}
- {%= __("Email Address") %}: {%= contact_list[i].email_id %}
- {% } %}
+ {% if(contact_list[i].phone) { %}
+ {%= __("Phone") %}: {%= contact_list[i].phone %}<span class="text-muted"> ({%= __("Primary") %})</span><br>
+ {% endif %}
+ {% if(contact_list[i].phone_nos) { %}
+ {% for(var j=0, k=contact_list[i].phone_nos.length; j<k; j++) { %}
+ {%= __("Phone") %}: {%= contact_list[i].phone_nos[j].phone %}<br>
+ {% } %}
+ {% endif %}
+ </p>
+ <p>
+ {% if(contact_list[i].email_id) { %}
+ {%= __("Email") %}: {%= contact_list[i].email_id %}<span class="text-muted"> ({%= __("Primary") %})</span><br>
+ {% endif %}
+ {% if(contact_list[i].email_ids) { %}
+ {% for(var j=0, k=contact_list[i].email_ids.length; j<k; j++) { %}
+ {%= __("Email") %}: {%= contact_list[i].email_ids[j].email_id %}<br>
+ {% } %}
+ {% endif %}
</p>
{% endif %}
+ <p>
+ {% if (contact_list[i].address) { %}
+ {%= __("Address") %}: {%= contact_list[i].address %}<br>
+ {% endif %}
+ </p>
</div>
{% } %}
{% if(!contact_list.length) { %}
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 0a363a0..ffc5e6a 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -60,7 +60,15 @@
var me = this;
$btn.on("click", function() {
- me.show_serial_batch_selector(grid_row.frm, grid_row.doc);
+ let callback = '';
+ let on_close = '';
+
+ if (grid_row.doc.serial_no) {
+ grid_row.doc.has_serial_no = true;
+ }
+
+ me.show_serial_batch_selector(grid_row.frm, grid_row.doc,
+ callback, on_close, true);
});
},
});
diff --git a/erpnext/public/js/utils/customer_quick_entry.js b/erpnext/public/js/utils/customer_quick_entry.js
index f454ba0..ac9a782 100644
--- a/erpnext/public/js/utils/customer_quick_entry.js
+++ b/erpnext/public/js/utils/customer_quick_entry.js
@@ -37,7 +37,8 @@
{
label: __("Address Line 1"),
fieldname: "address_line1",
- fieldtype: "Data"
+ fieldtype: "Data",
+ reqd: 1
},
{
label: __("Address Line 2"),
@@ -55,7 +56,8 @@
{
label: __("City"),
fieldname: "city",
- fieldtype: "Data"
+ fieldtype: "Data",
+ reqd: 1,
},
{
label: __("State"),
@@ -66,7 +68,8 @@
label: __("Country"),
fieldname: "country",
fieldtype: "Link",
- options: "Country"
+ options: "Country",
+ reqd: 1
},
{
label: __("Customer POS Id"),
diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js
index f1c9209..7abe4a7 100644
--- a/erpnext/public/js/utils/dimension_tree_filter.js
+++ b/erpnext/public/js/utils/dimension_tree_filter.js
@@ -1,12 +1,13 @@
frappe.provide('frappe.ui.form');
erpnext.doctypes_with_dimensions = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset",
- "Expense Claim", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note", "Sales Invoice Item", "Purchase Invoice Item",
- "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item", "Purchase Receipt Item",
- "Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule",
- "Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation",
- "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item", "Subscription",
- "Subscription Plan"];
+ "Expense Claim", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note", "Shipping Rule", "Loyalty Program",
+ "Fee Schedule", "Fee Structure", "Stock Reconciliation", "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool",
+ "Subscription", "Purchase Order", "Journal Entry", "Material Request", "Purchase Receipt", "Landed Cost Item", "Asset"];
+
+erpnext.child_docs = ["Sales Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account",
+ "Material Request Item", "Delivery Note Item", "Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction",
+ "Landed Cost Item", "Asset Value Adjustment", "Opening Invoice Creation Tool Item", "Subscription Plan"];
frappe.call({
method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters",
@@ -26,10 +27,51 @@
"is_group": 0
});
}
- if (frm.is_new() && frappe.meta.has_field(doctype, 'company') && frm.doc.company) {
+
+ if (Object.keys(erpnext.default_dimensions).length > 0) {
+ if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
+ if (frm.is_new() && frappe.meta.has_field(doctype, 'company') && frm.doc.company) {
+ frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
+ }
+ }
+
+ if (frm.doc.items && frm.doc.items.length) {
+ frm.doc.items[0][dimension['fieldname']] = erpnext.default_dimensions[frm.doc.company][dimension['document_type']];
+ }
+
+ if (frm.doc.accounts && frm.doc.accounts.length) {
+ frm.doc.accounts[0][dimension['fieldname']] = erpnext.default_dimensions[frm.doc.company][dimension['document_type']];
+ }
+ }
+ });
+ });
+ },
+
+ company: function(frm) {
+ if(frm.doc.company && (Object.keys(erpnext.default_dimensions).length > 0)) {
+ erpnext.dimension_filters.forEach((dimension) => {
+ if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
}
});
+ }
+ },
+ });
+});
+
+erpnext.child_docs.forEach((doctype) => {
+ frappe.ui.form.on(doctype, {
+ items_add: function(frm, cdt, cdn) {
+ erpnext.dimension_filters.forEach((dimension) => {
+ var row = frappe.get_doc(cdt, cdn);
+ frm.script_manager.copy_from_first_row("items", row, [dimension['fieldname']]);
+ });
+ },
+
+ accounts_add: function(frm, cdt, cdn) {
+ erpnext.dimension_filters.forEach((dimension) => {
+ var row = frappe.get_doc(cdt, cdn);
+ frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]);
});
},
diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py
index 4d3c522..b4de03e 100644
--- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py
+++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure.py
@@ -52,7 +52,19 @@
def get_children(doctype, parent=None, parent_quality_procedure=None, is_root=False):
if parent is None or parent == "All Quality Procedures":
parent = ""
- return frappe.get_all(doctype, fields=["name as value", "is_group as expandable"], filters={"parent_quality_procedure": parent})
+
+ return frappe.db.sql("""
+ select
+ name as value,
+ is_group as expandable
+ from
+ `tab{doctype}`
+ where
+ ifnull(parent_quality_procedure, "")={parent}
+ """.format(
+ doctype = doctype,
+ parent=frappe.db.escape(parent)
+ ), as_dict=1)
@frappe.whitelist()
def add_node():
diff --git a/erpnext/quality_management/doctype/quality_procedure/quality_procedure_tree.js b/erpnext/quality_management/doctype/quality_procedure/quality_procedure_tree.js
index 8fd785f..dbdbbab 100644
--- a/erpnext/quality_management/doctype/quality_procedure/quality_procedure_tree.js
+++ b/erpnext/quality_management/doctype/quality_procedure/quality_procedure_tree.js
@@ -1,5 +1,3 @@
-frappe.provide("frappe.treeview_settings");
-
frappe.treeview_settings["Quality Procedure"] = {
ignore_fields:["parent_quality_procedure"],
get_tree_nodes: 'erpnext.quality_management.doctype.quality_procedure.quality_procedure.get_children',
@@ -19,7 +17,7 @@
],
breadcrumb: "Setup",
root_label: "All Quality Procedures",
- get_tree_root: true,
+ get_tree_root: false,
menu_items: [
{
label: __("New Quality Procedure"),
diff --git a/erpnext/regional/india/bank_remittance.py b/erpnext/regional/india/bank_remittance.py
deleted file mode 100644
index 85c9564..0000000
--- a/erpnext/regional/india/bank_remittance.py
+++ /dev/null
@@ -1,190 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (c) 2018, Frappe and contributors
-# For license information, please see license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.document import Document
-from frappe.utils import cint,cstr, today
-from frappe import _
-import re
-import datetime
-from collections import OrderedDict
-
-def create_bank_remittance_txt(name):
- payment_order = frappe.get_cached_doc("Payment Order", name)
-
- no_of_records = len(payment_order.get("references"))
- total_amount = sum(entry.get("amount") for entry in payment_order.get("references"))
-
- product_code, client_code, company_email = frappe.db.get_value("Company",
- filters={'name' : payment_order.company},
- fieldname=['product_code', 'client_code', 'email'])
-
- header, file_name = get_header_row(payment_order, client_code)
- batch = get_batch_row(payment_order, no_of_records, total_amount, product_code)
-
- detail = []
- for ref_doc in payment_order.get("references"):
- detail += get_detail_row(ref_doc, payment_order, company_email)
-
- trailer = get_trailer_row(no_of_records, total_amount)
- detail_records = "\n".join(detail)
-
- return "\n".join([header, batch, detail_records, trailer]), file_name
-
-@frappe.whitelist()
-def generate_report(name):
- data, file_name = create_bank_remittance_txt(name)
-
- f = frappe.get_doc({
- 'doctype': 'File',
- 'file_name': file_name,
- 'content': data,
- "attached_to_doctype": 'Payment Order',
- "attached_to_name": name,
- 'is_private': True
- })
- f.save()
- return {
- 'file_url': f.file_url,
- 'file_name': file_name
- }
-
-def generate_file_name(name, company_account, date):
- ''' generate file name with format (account_code)_mmdd_(payment_order_no) '''
- bank, acc_no = frappe.db.get_value("Bank Account", {"name": company_account}, ['bank', 'bank_account_no'])
- return bank[:1]+str(acc_no)[-4:]+'_'+date.strftime("%m%d")+sanitize_data(name, '')[4:]+'.txt'
-
-def get_header_row(doc, client_code):
- ''' Returns header row and generated file name '''
- file_name = generate_file_name(doc.name, doc.company_bank_account, doc.posting_date)
- header = ["H"]
- header.append(validate_field_size(client_code, "Client Code", 20))
- header += [''] * 3
- header.append(validate_field_size(file_name, "File Name", 20))
- return "~".join(header), file_name
-
-def get_batch_row(doc, no_of_records, total_amount, product_code):
- batch = ["B"]
- batch.append(validate_field_size(no_of_records, "No Of Records", 5))
- batch.append(validate_amount(format(total_amount, '0.2f'), 17))
- batch.append(sanitize_data(doc.name, '_')[:20])
- batch.append(format_date(doc.posting_date))
- batch.append(validate_field_size(product_code,"Product Code", 20))
- return "~".join(batch)
-
-def get_detail_row(ref_doc, payment_entry, company_email):
-
- payment_date = format_date(payment_entry.posting_date)
- payment_entry = frappe.get_cached_doc('Payment Entry', ref_doc.payment_entry)
- supplier_bank_details = frappe.get_cached_doc('Bank Account', ref_doc.bank_account)
- company_bank_acc_no = frappe.db.get_value("Bank Account", {'name': payment_entry.bank_account}, ['bank_account_no'])
-
- addr_link = frappe.db.get_value('Dynamic Link',
- {
- 'link_doctype': 'Supplier',
- 'link_name': 'Sample Supplier',
- 'parenttype':'Address',
- 'parent': ('like', '%-Billing')
- }, 'parent')
-
- supplier_billing_address = frappe.get_cached_doc('Address', addr_link)
- email = ','.join(filter(None, [supplier_billing_address.email_id, company_email]))
-
- detail = OrderedDict(
- record_identifier='D',
- payment_ref_no=sanitize_data(ref_doc.payment_entry),
- payment_type=cstr(payment_entry.mode_of_payment)[:10],
- amount=str(validate_amount(format(ref_doc.amount, '.2f'),13)),
- payment_date=payment_date,
- instrument_date=payment_date,
- instrument_number='',
- dr_account_no_client=str(validate_field_size(company_bank_acc_no, "Company Bank Account", 20)),
- dr_description='',
- dr_ref_no='',
- cr_ref_no='',
- bank_code_indicator='M',
- beneficiary_code='',
- beneficiary_name=sanitize_data(validate_information(payment_entry, "party", 160), ' '),
- beneficiary_bank=sanitize_data(validate_information(supplier_bank_details, "bank", 10)),
- beneficiary_branch_code=cstr(validate_information(supplier_bank_details, "branch_code", 11)),
- beneficiary_acc_no=validate_information(supplier_bank_details, "bank_account_no", 20),
- location='',
- print_location='',
- beneficiary_address_1=validate_field_size(sanitize_data(cstr(supplier_billing_address.address_line1), ' '), " Beneficiary Address 1", 50),
- beneficiary_address_2=validate_field_size(sanitize_data(cstr(supplier_billing_address.address_line2), ' '), " Beneficiary Address 2", 50),
- beneficiary_address_3='',
- beneficiary_address_4='',
- beneficiary_address_5='',
- beneficiary_city=validate_field_size(cstr(supplier_billing_address.city), "Beneficiary City", 20),
- beneficiary_zipcode=validate_field_size(cstr(supplier_billing_address.pincode), "Pin Code", 6),
- beneficiary_state=validate_field_size(cstr(supplier_billing_address.state), "Beneficiary State", 20),
- beneficiary_email=cstr(email)[:255],
- beneficiary_mobile=validate_field_size(cstr(supplier_billing_address.phone), "Beneficiary Mobile", 10),
- payment_details_1='',
- payment_details_2='',
- payment_details_3='',
- payment_details_4='',
- delivery_mode=''
- )
- detail_record = ["~".join(list(detail.values()))]
-
- detail_record += get_advice_rows(payment_entry)
- return detail_record
-
-def get_advice_rows(payment_entry):
- ''' Returns multiple advice rows for a single detail entry '''
- payment_entry_date = payment_entry.posting_date.strftime("%b%y%d%m").upper()
- mode_of_payment = payment_entry.mode_of_payment
- advice_rows = []
- for record in payment_entry.references:
- advice = ['E']
- advice.append(cstr(mode_of_payment))
- advice.append(cstr(record.total_amount))
- advice.append('')
- advice.append(cstr(record.outstanding_amount))
- advice.append(record.reference_name)
- advice.append(format_date(record.due_date))
- advice.append(payment_entry_date)
- advice_rows.append("~".join(advice))
- return advice_rows
-
-def get_trailer_row(no_of_records, total_amount):
- ''' Returns trailer row '''
- trailer = ["T"]
- trailer.append(validate_field_size(no_of_records, "No of Records", 5))
- trailer.append(validate_amount(format(total_amount, "0.2f"), 17))
- return "~".join(trailer)
-
-def sanitize_data(val, replace_str=''):
- ''' Remove all the non-alphanumeric characters from string '''
- pattern = re.compile('[\W_]+')
- return pattern.sub(replace_str, val)
-
-def format_date(val):
- ''' Convert a datetime object to DD/MM/YYYY format '''
- return val.strftime("%d/%m/%Y")
-
-def validate_amount(val, max_int_size):
- ''' Validate amount to be within the allowed limits '''
- int_size = len(str(val).split('.')[0])
-
- if int_size > max_int_size:
- frappe.throw(_("Amount for a single transaction exceeds maximum allowed amount, create a separate payment order by splitting the transactions"))
-
- return val
-
-def validate_information(obj, attr, max_size):
- ''' Checks if the information is not set in the system and is within the size '''
- if hasattr(obj, attr):
- return validate_field_size(getattr(obj, attr), frappe.unscrub(attr), max_size)
-
- else:
- frappe.throw(_("{0} is mandatory for generating remittance payments, set the field and try again".format(frappe.unscrub(attr))))
-
-def validate_field_size(val, label, max_size):
- ''' check the size of the val '''
- if len(cstr(val)) > max_size:
- frappe.throw(_("{0} field is limited to size {1}".format(label, max_size)))
- return cstr(val)
\ No newline at end of file
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index 40b98ed..756c17d 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -407,14 +407,6 @@
fieldtype='Link', options='Salary Component', insert_after='basic_component'),
dict(fieldname='arrear_component', label='Arrear Component',
fieldtype='Link', options='Salary Component', insert_after='hra_component'),
- dict(fieldname='bank_remittance_section', label='Bank Remittance Settings',
- fieldtype='Section Break', collapsible=1, insert_after='arrear_component'),
- dict(fieldname='client_code', label='Client Code', fieldtype='Data',
- insert_after='bank_remittance_section'),
- dict(fieldname='remittance_column_break', fieldtype='Column Break',
- insert_after='client_code'),
- dict(fieldname='product_code', label='Product Code', fieldtype='Data',
- insert_after='remittance_column_break'),
],
'Employee Tax Exemption Declaration':[
dict(fieldname='hra_section', label='HRA Exemption',
diff --git a/erpnext/regional/italy/e-invoice.xml b/erpnext/regional/italy/e-invoice.xml
index 9a588d1..9978dc0 100644
--- a/erpnext/regional/italy/e-invoice.xml
+++ b/erpnext/regional/italy/e-invoice.xml
@@ -1,5 +1,5 @@
-{%- macro format_float(value) -%}
-{{ "%.2f" % value|abs }}
+{%- macro format_float(value, precision=2) -%}
+{{ value|round(frappe.utils.cint(precision)) }}
{%- endmacro -%}
{%- macro render_address(address) %}
@@ -182,10 +182,10 @@
<Descrizione>{{ html2text(item.description or '') or item.item_name }}</Descrizione>
<Quantita>{{ format_float(item.qty) }}</Quantita>
<UnitaMisura>{{ item.stock_uom }}</UnitaMisura>
- <PrezzoUnitario>{{ format_float(item.price_list_rate or item.rate) }}</PrezzoUnitario>
+ <PrezzoUnitario>{{ format_float(item.price_list_rate or item.rate, item_meta.get_field("rate").precision) }}</PrezzoUnitario>
{{ render_discount_or_margin(item) }}
- <PrezzoTotale>{{ format_float(item.amount) }}</PrezzoTotale>
- <AliquotaIVA>{{ format_float(item.tax_rate) }}</AliquotaIVA>
+ <PrezzoTotale>{{ format_float(item.amount, item_meta.get_field("amount").precision) }}</PrezzoTotale>
+ <AliquotaIVA>{{ format_float(item.tax_rate, item_meta.get_field("tax_rate").precision) }}</AliquotaIVA>
{%- if item.tax_exemption_reason %}
<Natura>{{ item.tax_exemption_reason.split("-")[0] }}</Natura>
{%- endif %}
@@ -197,8 +197,8 @@
{%- if data.tax_exemption_reason %}
<Natura>{{ data.tax_exemption_reason.split("-")[0] }}</Natura>
{%- endif %}
- <ImponibileImporto>{{ format_float(data.taxable_amount) }}</ImponibileImporto>
- <Imposta>{{ format_float(data.tax_amount) }}</Imposta>
+ <ImponibileImporto>{{ format_float(data.taxable_amount, item_meta.get_field("tax_amount").precision) }}</ImponibileImporto>
+ <Imposta>{{ format_float(data.tax_amount, item_meta.get_field("tax_amount").precision) }}</Imposta>
<EsigibilitaIVA>{{ doc.vat_collectability.split("-")[0] }}</EsigibilitaIVA>
{%- if data.tax_exemption_law %}
<RiferimentoNormativo>{{ data.tax_exemption_law }}</RiferimentoNormativo>
diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py
index 407677f..12f5762 100644
--- a/erpnext/regional/italy/utils.py
+++ b/erpnext/regional/italy/utils.py
@@ -151,7 +151,8 @@
tax_rate=tax.rate,
tax_amount=(reference_row.tax_amount * tax.rate) / 100,
net_amount=reference_row.tax_amount,
- taxable_amount=reference_row.tax_amount,
+ taxable_amount=(reference_row.tax_amount if tax.charge_type == 'On Previous Row Amount'
+ else reference_row.total),
item_tax_rate={tax.account_head: tax.rate},
charges=True
)
@@ -278,7 +279,11 @@
progressive_name, progressive_number = get_progressive_name_and_number(doc, replace)
invoice = prepare_invoice(doc, progressive_number)
- invoice_xml = frappe.render_template('erpnext/regional/italy/e-invoice.xml', context={"doc": invoice}, is_path=True)
+ item_meta = frappe.get_meta("Sales Invoice Item")
+
+ invoice_xml = frappe.render_template('erpnext/regional/italy/e-invoice.xml',
+ context={"doc": invoice, "item_meta": item_meta}, is_path=True)
+
invoice_xml = invoice_xml.replace("&", "&")
xml_filename = progressive_name + ".xml"
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 2da1085..922619c 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -156,34 +156,21 @@
if self.filters.get("type_of_business") == "B2B":
- customers = frappe.get_all("Customer",
- filters={
- "gst_category": ["in", ["Registered Regular", "Deemed Export", "SEZ"]]
- })
-
- if customers:
- conditions += """ and ifnull(gst_category, '') != 'Overseas' and is_return != 1
- and customer in ({0})""".format(", ".join([frappe.db.escape(c.name) for c in customers]))
+ conditions += "and ifnull(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ') and is_return != 1"
if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"):
b2c_limit = frappe.db.get_single_value('GST Settings', 'b2c_limit')
if not b2c_limit:
frappe.throw(_("Please set B2C Limit in GST Settings."))
- customers = frappe.get_all("Customer",
- filters={
- "gst_category": ["in", ["Unregistered"]]
- })
-
- if self.filters.get("type_of_business") == "B2C Large" and customers:
+ if self.filters.get("type_of_business") == "B2C Large":
conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2)
- and grand_total > {0} and is_return != 1 and customer in ({1})""".\
- format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers]))
- elif self.filters.get("type_of_business") == "B2C Small" and customers:
+ and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit))
+
+ elif self.filters.get("type_of_business") == "B2C Small":
conditions += """ and (
SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2)
- or grand_total <= {0}) and is_return != 1 and customer in ({1})""".\
- format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers]))
+ or grand_total <= {0}) and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit))
elif self.filters.get("type_of_business") == "CDNR":
conditions += """ and is_return = 1 """
@@ -735,7 +722,7 @@
if gstin:
return gstin[0]["gstin"]
else:
- frappe.throw(_("No GST No. found for the Company."))
+ frappe.throw(_("Please set valid GSTIN No. in Company Address"))
def download_json_file(filename, report_type, data):
''' download json content in a file '''
diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json
index 8c30528..c2c8c19 100644
--- a/erpnext/selling/doctype/customer/customer.json
+++ b/erpnext/selling/doctype/customer/customer.json
@@ -1,2036 +1,475 @@
{
- "allow_copy": 0,
"allow_events_in_timeline": 1,
- "allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "naming_series:",
- "beta": 0,
"creation": "2013-06-11 14:26:44",
- "custom": 0,
"description": "Buyer of Goods and Services.",
- "docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
- "editable_grid": 0,
"engine": "InnoDB",
+ "field_order": [
+ "basic_info",
+ "naming_series",
+ "salutation",
+ "customer_name",
+ "gender",
+ "customer_type",
+ "default_bank_account",
+ "lead_name",
+ "image",
+ "column_break0",
+ "account_manager",
+ "customer_group",
+ "territory",
+ "tax_id",
+ "tax_category",
+ "disabled",
+ "is_internal_customer",
+ "represents_company",
+ "allowed_to_transact_section",
+ "companies",
+ "currency_and_price_list",
+ "default_currency",
+ "default_price_list",
+ "column_break_14",
+ "language",
+ "address_contacts",
+ "address_html",
+ "website",
+ "column_break1",
+ "contact_html",
+ "primary_address_and_contact_detail",
+ "customer_primary_contact",
+ "mobile_no",
+ "email_id",
+ "column_break_26",
+ "customer_primary_address",
+ "primary_address",
+ "default_receivable_accounts",
+ "accounts",
+ "credit_limit_section",
+ "payment_terms",
+ "credit_limits",
+ "more_info",
+ "customer_details",
+ "column_break_45",
+ "market_segment",
+ "industry",
+ "is_frozen",
+ "column_break_38",
+ "loyalty_program",
+ "loyalty_program_tier",
+ "sales_team_section_break",
+ "default_sales_partner",
+ "default_commission_rate",
+ "sales_team_section",
+ "sales_team",
+ "customer_pos_id"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "basic_info",
"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": "Name and Type",
- "length": 0,
- "no_copy": 0,
"oldfieldtype": "Section Break",
- "options": "fa fa-user",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "fa fa-user"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fetch_if_empty": 0,
"fieldname": "naming_series",
"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",
- "length": 0,
"no_copy": 1,
"options": "CUST-.YYYY.-",
- "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": 1,
- "translatable": 0,
- "unique": 0
+ "set_only_once": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "eval:doc.customer_type!='Company'",
- "fetch_if_empty": 0,
"fieldname": "salutation",
"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": "Salutation",
- "length": 0,
- "no_copy": 0,
- "options": "Salutation",
- "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
+ "options": "Salutation"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
"bold": 1,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "customer_name",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
"in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Full Name",
- "length": 0,
"no_copy": 1,
"oldfieldname": "customer_name",
"oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
"reqd": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "eval:doc.customer_type != 'Company'",
- "fetch_if_empty": 0,
"fieldname": "gender",
"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": "Gender",
- "length": 0,
- "no_copy": 0,
- "options": "Gender",
- "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
+ "options": "Gender"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "Company",
- "fetch_if_empty": 0,
"fieldname": "customer_type",
"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": "Type",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "customer_type",
"oldfieldtype": "Select",
"options": "Company\nIndividual",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "default_bank_account",
"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": "Default Bank Account",
- "length": 0,
- "no_copy": 0,
- "options": "Bank Account",
- "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
+ "options": "Bank Account"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "lead_name",
"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": "From Lead",
- "length": 0,
"no_copy": 1,
"oldfieldname": "lead_name",
"oldfieldtype": "Link",
"options": "Lead",
- "permlevel": 0,
"print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "report_hide": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "image",
"fieldtype": "Attach Image",
"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",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "print_hide": 1
},
{
- "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_break0",
"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,
- "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%"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "account_manager",
"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": "Account Manager",
- "length": 0,
- "no_copy": 0,
- "options": "User",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "User"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
- "fetch_if_empty": 0,
"fieldname": "customer_group",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Customer Group",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "customer_group",
"oldfieldtype": "Link",
"options": "Customer Group",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
"reqd": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
- "fetch_if_empty": 0,
"fieldname": "territory",
"fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Territory",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "territory",
"oldfieldtype": "Link",
"options": "Territory",
- "permlevel": 0,
"print_hide": 1,
- "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
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "tax_id",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Tax ID",
- "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
+ "label": "Tax ID"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "tax_category",
"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": "Tax Category",
- "length": 0,
- "no_copy": 0,
- "options": "Tax Category",
- "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
+ "options": "Tax Category"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "0",
- "fetch_if_empty": 0,
"fieldname": "disabled",
"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": "Disabled",
- "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
+ "label": "Disabled"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"default": "0",
- "fetch_if_empty": 0,
"fieldname": "is_internal_customer",
"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": "Is Internal Customer",
- "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
+ "label": "Is Internal Customer"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "is_internal_customer",
- "fetch_if_empty": 0,
"fieldname": "represents_company",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Represents Company",
- "length": 0,
- "no_copy": 0,
"options": "Company",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
"unique": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "represents_company",
- "fetch_if_empty": 0,
"fieldname": "allowed_to_transact_section",
"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": "Allowed To Transact With",
- "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
+ "label": "Allowed To Transact With"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "represents_company",
- "fetch_if_empty": 0,
"fieldname": "companies",
"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": "Allowed To Transact With",
- "length": 0,
- "no_copy": 0,
- "options": "Allowed To Transact With",
- "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
+ "options": "Allowed To Transact With"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "currency_and_price_list",
"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": "Currency and Price List",
- "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
+ "label": "Currency and Price List"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "default_currency",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Billing Currency",
- "length": 0,
"no_copy": 1,
- "options": "Currency",
- "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
+ "options": "Currency"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "default_price_list",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Default Price List",
- "length": 0,
- "no_copy": 0,
- "options": "Price List",
- "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
+ "options": "Price List"
},
{
- "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_14",
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "language",
"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": "Print Language",
- "length": 0,
- "no_copy": 0,
- "options": "Language",
- "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
+ "options": "Language"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "eval:!doc.__islocal",
- "fetch_if_empty": 0,
"fieldname": "address_contacts",
"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": "Address and Contact",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-map-marker",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "fa fa-map-marker"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "address_html",
"fieldtype": "HTML",
- "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": "Address HTML",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "website",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Website",
- "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
+ "label": "Website"
},
{
- "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_break1",
"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,
- "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%"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "contact_html",
"fieldtype": "HTML",
- "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": "Contact HTML",
- "length": 0,
- "no_copy": 0,
"oldfieldtype": "HTML",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "Select, to make the customer searchable with these fields",
- "fetch_if_empty": 0,
"fieldname": "primary_address_and_contact_detail",
"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": "Primary Address and Contact Detail",
- "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
+ "label": "Primary Address and Contact Detail"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "Reselect, if the chosen contact is edited after save",
- "fetch_if_empty": 0,
"fieldname": "customer_primary_contact",
"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": "Customer Primary Contact",
- "length": 0,
- "no_copy": 0,
- "options": "Contact",
- "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
+ "options": "Contact"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "customer_primary_contact.mobile_no",
- "fetch_if_empty": 0,
"fieldname": "mobile_no",
"fieldtype": "Read Only",
- "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": "Mobile No",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
+ "label": "Mobile No"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fetch_from": "customer_primary_contact.email_id",
- "fetch_if_empty": 0,
"fieldname": "email_id",
"fieldtype": "Read Only",
- "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": "Email Id",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
+ "label": "Email Id"
},
{
- "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_26",
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "Reselect, if the chosen address is edited after save",
- "fetch_if_empty": 0,
"fieldname": "customer_primary_address",
"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": "Customer Primary Address",
- "length": 0,
- "no_copy": 0,
- "options": "Address",
- "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
+ "options": "Address"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fetch_if_empty": 0,
"fieldname": "primary_address",
"fieldtype": "Read Only",
- "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": "Primary Address",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
+ "label": "Primary Address"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
- "collapsible_depends_on": "",
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "default_receivable_accounts",
"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": "Accounting",
- "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
+ "label": "Accounting"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
"description": "Mention if non-standard receivable account",
- "fetch_if_empty": 0,
"fieldname": "accounts",
"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": "Accounts",
- "length": 0,
- "no_copy": 0,
- "options": "Party Account",
- "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
+ "options": "Party Account"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
- "collapsible_depends_on": "",
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "credit_limit_section",
"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": "Credit Limit and Payment Terms",
- "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,
- "width": ""
+ "label": "Credit Limit and Payment Terms"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "credit_limit",
- "fieldtype": "Currency",
- "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": "Credit Limit",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "credit_limit",
- "oldfieldtype": "Currency",
- "options": "",
- "permlevel": 1,
- "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": "0",
- "fetch_if_empty": 0,
- "fieldname": "bypass_credit_limit_check_at_sales_order",
- "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": "Bypass credit limit check at Sales 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": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "column_break_34",
- "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": "",
- "fetch_if_empty": 0,
"fieldname": "payment_terms",
"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": "Default Payment Terms Template",
- "length": 0,
- "no_copy": 0,
- "options": "Payment Terms Template",
- "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
+ "options": "Payment Terms Template"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
"collapsible_depends_on": "customer_details",
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "more_info",
"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": "More Information",
- "length": 0,
- "no_copy": 0,
"oldfieldtype": "Section Break",
- "options": "fa fa-file-text",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "fa fa-file-text"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"description": "Additional information regarding the customer.",
- "fetch_if_empty": 0,
"fieldname": "customer_details",
"fieldtype": "Text",
- "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": "Customer Details",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "customer_details",
- "oldfieldtype": "Code",
- "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
+ "oldfieldtype": "Code"
},
{
- "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_45",
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "market_segment",
"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": "Market Segment",
- "length": 0,
- "no_copy": 0,
- "options": "Market Segment",
- "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
+ "options": "Market Segment"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "industry",
"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": "Industry",
- "length": 0,
- "no_copy": 0,
- "options": "Industry Type",
- "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
+ "options": "Industry Type"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
+ "default": "0",
"fieldname": "is_frozen",
"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": "Is Frozen",
- "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
+ "label": "Is Frozen"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "column_break_38",
"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": "Loyalty Points",
- "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
+ "label": "Loyalty Points"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "loyalty_program",
"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": "Loyalty Program",
- "length": 0,
"no_copy": 1,
- "options": "Loyalty Program",
- "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
+ "options": "Loyalty Program"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "loyalty_program_tier",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Loyalty Program Tier",
- "length": 0,
"no_copy": 1,
- "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
+ "read_only": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
"collapsible_depends_on": "default_sales_partner",
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "sales_team_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": "Sales Partner and Commission",
- "length": 0,
- "no_copy": 0,
"oldfieldtype": "Section Break",
- "options": "fa fa-group",
- "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
+ "options": "fa fa-group"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "default_sales_partner",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Sales Partner",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "default_sales_partner",
"oldfieldtype": "Link",
- "options": "Sales Partner",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "options": "Sales Partner"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "default_commission_rate",
"fieldtype": "Float",
- "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": "Commission Rate",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "default_commission_rate",
- "oldfieldtype": "Currency",
- "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
+ "oldfieldtype": "Currency"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
"collapsible_depends_on": "sales_team",
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "sales_team_section",
"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": "Sales Team",
- "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
+ "label": "Sales Team"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "sales_team",
"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": "Sales Team Details",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "sales_team",
"oldfieldtype": "Table",
- "options": "Sales Team",
- "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
+ "options": "Sales Team"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
"fieldname": "customer_pos_id",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Customer POS id",
- "length": 0,
"no_copy": 1,
- "permlevel": 0,
- "precision": "",
"print_hide": 1,
- "print_hide_if_no_value": 0,
"read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "report_hide": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "credit_limits",
+ "fieldtype": "Table",
+ "label": "Credit Limit",
+ "options": "Customer Credit Limit"
}
],
- "has_web_view": 0,
- "hide_toolbar": 0,
"icon": "fa fa-user",
"idx": 363,
"image_field": "image",
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "menu_index": 0,
- "modified": "2019-04-12 08:45:39.357491",
+ "modified": "2019-09-06 12:40:31.801424",
"modified_by": "Administrator",
"module": "Selling",
"name": "Customer",
@@ -2038,184 +477,81 @@
"owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
"create": 1,
- "delete": 0,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User",
- "set_user_permissions": 0,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
"permlevel": 1,
- "print": 0,
"read": 1,
- "report": 0,
- "role": "Sales User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Sales User"
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
- "role": "Sales Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Sales Manager"
},
{
- "amend": 0,
- "cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
- "if_owner": 0,
"import": 1,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Master Manager",
"set_user_permissions": 1,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
"permlevel": 1,
- "print": 0,
"read": 1,
- "report": 0,
"role": "Sales Master Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
"write": 1
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
- "role": "Stock User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Stock User"
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
- "role": "Stock Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Stock Manager"
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
- "role": "Accounts User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Accounts User"
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
- "role": "Accounts Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Accounts Manager"
}
],
"quick_entry": 1,
- "read_only": 0,
"search_fields": "customer_name,customer_group,territory, mobile_no,primary_address",
"show_name_in_global_search": 1,
+ "sort_field": "modified",
"sort_order": "ASC",
"title_field": "customer_name",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index c946c47..4ca5af5 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -167,13 +167,18 @@
frappe.throw(_("A Customer Group exists with same name please change the Customer name or rename the Customer Group"), frappe.NameError)
def validate_credit_limit_on_change(self):
- if self.get("__islocal") or not self.credit_limit \
- or self.credit_limit == frappe.db.get_value("Customer", self.name, "credit_limit"):
+ if self.get("__islocal") or not self.credit_limits:
return
- for company in frappe.get_all("Company"):
- outstanding_amt = get_customer_outstanding(self.name, company.name)
- if flt(self.credit_limit) < outstanding_amt:
+ company_record = []
+ for limit in self.credit_limits:
+ if limit.company in company_record:
+ frappe.throw(_("Credit limit is already defined for the Company {0}").format(limit.company, self.name))
+ else:
+ company_record.append(limit.company)
+
+ outstanding_amt = get_customer_outstanding(self.name, limit.company)
+ if flt(limit.credit_limit) < outstanding_amt:
frappe.throw(_("""New credit limit is less than current outstanding amount for the customer. Credit limit has to be atleast {0}""").format(outstanding_amt))
def on_trash(self):
@@ -322,11 +327,13 @@
credit_limit = None
if customer:
- credit_limit, customer_group = frappe.get_cached_value("Customer",
- customer, ["credit_limit", "customer_group"])
+ credit_limit = frappe.db.get_value("Customer Credit Limit",
+ {'parent': customer, 'parenttype': 'Customer', 'company': company}, 'credit_limit')
if not credit_limit:
- credit_limit = frappe.get_cached_value("Customer Group", customer_group, "credit_limit")
+ customer_group = frappe.get_cached_value("Customer", customer, 'customer_group')
+ credit_limit = frappe.db.get_value("Customer Credit Limit",
+ {'parent': customer_group, 'parenttype': 'Customer Group', 'company': company}, 'credit_limit')
if not credit_limit:
credit_limit = frappe.get_cached_value('Company', company, "credit_limit")
@@ -337,14 +344,15 @@
contact = frappe.get_doc({
'doctype': 'Contact',
'first_name': args.get('name'),
- 'mobile_no': args.get('mobile_no'),
- 'email_id': args.get('email_id'),
'is_primary_contact': is_primary_contact,
'links': [{
'link_doctype': args.get('doctype'),
'link_name': args.get('name')
}]
- }).insert()
+ })
+ contact.add_email(args.get('email_id'))
+ contact.add_phone(args.get('mobile_no'))
+ contact.insert()
return contact
@@ -371,7 +379,7 @@
return frappe.db.sql("""
select `tabContact`.name from `tabContact`, `tabDynamic Link`
where `tabContact`.name = `tabDynamic Link`.parent and `tabDynamic Link`.link_name = %(customer)s
- and `tabDynamic Link`.link_doctype = 'Customer' and `tabContact`.is_primary_contact = 1
+ and `tabDynamic Link`.link_doctype = 'Customer'
and `tabContact`.name like %(txt)s
""", {
'customer': customer,
@@ -383,7 +391,7 @@
return frappe.db.sql("""
select `tabAddress`.name from `tabAddress`, `tabDynamic Link`
where `tabAddress`.name = `tabDynamic Link`.parent and `tabDynamic Link`.link_name = %(customer)s
- and `tabDynamic Link`.link_doctype = 'Customer' and `tabAddress`.is_primary_address = 1
+ and `tabDynamic Link`.link_doctype = 'Customer'
and `tabAddress`.name like %(txt)s
""", {
'customer': customer,
diff --git a/erpnext/selling/doctype/customer/customer_dashboard.py b/erpnext/selling/doctype/customer/customer_dashboard.py
index 8e790bf..654dd48 100644
--- a/erpnext/selling/doctype/customer/customer_dashboard.py
+++ b/erpnext/selling/doctype/customer/customer_dashboard.py
@@ -9,7 +9,7 @@
'heatmap_message': _('This is based on transactions against this Customer. See timeline below for details'),
'fieldname': 'customer',
'non_standard_fieldnames': {
- 'Payment Entry': 'party_name',
+ 'Payment Entry': 'party',
'Quotation': 'party_name',
'Opportunity': 'party_name'
},
diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py
index f261ef3..87fdaa3 100644
--- a/erpnext/selling/doctype/customer/test_customer.py
+++ b/erpnext/selling/doctype/customer/test_customer.py
@@ -25,7 +25,7 @@
make_test_records('Item')
def tearDown(self):
- frappe.db.set_value("Customer", '_Test Customer', 'credit_limit', 0.0)
+ set_credit_limit('_Test Customer', '_Test Company', 0)
def test_party_details(self):
from erpnext.accounts.party import get_party_details
@@ -225,8 +225,8 @@
item_qty = int((abs(outstanding_amt) + 200)/100)
make_sales_order(qty=item_qty)
- if credit_limit == 0.0:
- frappe.db.set_value("Customer", '_Test Customer', 'credit_limit', outstanding_amt - 50.0)
+ if not credit_limit:
+ set_credit_limit('_Test Customer', '_Test Company', outstanding_amt - 50)
# Sales Order
so = make_sales_order(do_not_submit=True)
@@ -241,7 +241,7 @@
self.assertRaises(frappe.ValidationError, si.submit)
if credit_limit > outstanding_amt:
- frappe.db.set_value("Customer", '_Test Customer', 'credit_limit', credit_limit)
+ set_credit_limit('_Test Customer', '_Test Company', credit_limit)
# Makes Sales invoice from Sales Order
so.save(ignore_permissions=True)
@@ -252,7 +252,10 @@
def test_customer_credit_limit_on_change(self):
outstanding_amt = self.get_customer_outstanding_amount()
customer = frappe.get_doc("Customer", '_Test Customer')
- customer.credit_limit = flt(outstanding_amt - 100)
+ customer.append('credit_limits', {'credit_limit': flt(outstanding_amt - 100), 'company': '_Test Company'})
+
+ ''' define new credit limit for same company '''
+ customer.append('credit_limits', {'credit_limit': flt(outstanding_amt - 100), 'company': '_Test Company'})
self.assertRaises(frappe.ValidationError, customer.save)
def test_customer_payment_terms(self):
@@ -292,3 +295,20 @@
"doctype": "Customer",
"territory": "_Test Territory"
}
+
+def set_credit_limit(customer, company, credit_limit):
+ customer = frappe.get_doc("Customer", customer)
+ existing_row = None
+ for d in customer.credit_limits:
+ if d.company == company:
+ existing_row = d
+ d.credit_limit = credit_limit
+ d.db_update()
+ break
+
+ if not existing_row:
+ customer.append('credit_limits', {
+ 'company': company,
+ 'credit_limit': credit_limit
+ })
+ customer.credit_limits[-1].db_insert()
diff --git a/erpnext/selling/doctype/customer_credit_limit/__init__.py b/erpnext/selling/doctype/customer_credit_limit/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/selling/doctype/customer_credit_limit/__init__.py
diff --git a/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.json b/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.json
new file mode 100644
index 0000000..e26f798
--- /dev/null
+++ b/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.json
@@ -0,0 +1,50 @@
+{
+ "creation": "2019-08-28 17:29:42.115592",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "company",
+ "column_break_2",
+ "credit_limit",
+ "bypass_credit_limit_check"
+ ],
+ "fields": [
+ {
+ "columns": 4,
+ "fieldname": "credit_limit",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Credit Limit"
+ },
+ {
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break"
+ },
+ {
+ "columns": 4,
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Company",
+ "options": "Company"
+ },
+ {
+ "default": "0",
+ "fieldname": "bypass_credit_limit_check",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Bypass credit limit_check"
+ }
+ ],
+ "istable": 1,
+ "modified": "2019-08-29 20:46:36.073953",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Customer Credit Limit",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC"
+}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.py b/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.py
new file mode 100644
index 0000000..60a4a9a
--- /dev/null
+++ b/erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class CustomerCreditLimit(Document):
+ pass
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index cc73e76..46009f4 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -34,7 +34,7 @@
self.with_items = 1
def validate_valid_till(self):
- if self.valid_till and self.valid_till < self.transaction_date:
+ if self.valid_till and getdate(self.valid_till) < getdate(self.transaction_date):
frappe.throw(_("Valid till date cannot be before transaction date"))
def has_sales_order(self):
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 2e5f255..e86cadd 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -7,6 +7,7 @@
setup: function(frm) {
frm.custom_make_buttons = {
'Delivery Note': 'Delivery',
+ 'Pick List': 'Pick List',
'Sales Invoice': 'Invoice',
'Material Request': 'Material Request',
'Purchase Order': 'Purchase Order',
@@ -109,7 +110,9 @@
this._super();
let allow_delivery = false;
- if(doc.docstatus==1) {
+ if (doc.docstatus==1) {
+ this.frm.add_custom_button(__('Pick List'), () => this.create_pick_list(), __('Create'));
+
if(this.frm.has_perm("submit")) {
if(doc.status === 'On Hold') {
// un-hold
@@ -233,6 +236,13 @@
this.order_type(doc);
},
+ create_pick_list() {
+ frappe.model.open_mapped_doc({
+ method: "erpnext.selling.doctype.sales_order.sales_order.create_pick_list",
+ frm: this.frm
+ })
+ },
+
make_work_order() {
var me = this;
this.frm.call({
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index 2481f31..e537495 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -1,4472 +1,1256 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 0,
- "creation": "2013-06-18 12:39:59",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "customer_section",
- "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,
- "options": "fa fa-user",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "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_break0",
- "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",
- "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%"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "{customer_name}",
- "fetch_if_empty": 0,
- "fieldname": "title",
- "fieldtype": "Data",
- "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": "Title",
- "length": 0,
- "no_copy": 1,
- "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,
- "default": "",
- "fetch_if_empty": 0,
- "fieldname": "naming_series",
- "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",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "naming_series",
- "oldfieldtype": "Select",
- "options": "SAL-ORD-.YYYY.-",
- "permlevel": 0,
- "print_hide": 1,
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "customer",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 1,
- "label": "Customer",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "customer",
- "oldfieldtype": "Link",
- "options": "Customer",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "customer.customer_name",
- "fetch_if_empty": 0,
- "fieldname": "customer_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Customer Name",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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,
- "default": "Sales",
- "depends_on": "",
- "fetch_if_empty": 0,
- "fieldname": "order_type",
- "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": "Order Type",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "order_type",
- "oldfieldtype": "Select",
- "options": "\nSales\nMaintenance\nShopping Cart",
- "permlevel": 0,
- "print_hide": 1,
- "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_break1",
- "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",
- "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%"
- },
- {
- "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",
- "fieldtype": "Link",
- "hidden": 1,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Amended From",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "amended_from",
- "oldfieldtype": "Data",
- "options": "Sales Order",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "width": "150px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
- "fetch_if_empty": 0,
- "fieldname": "company",
- "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,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "company",
- "oldfieldtype": "Link",
- "options": "Company",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 1,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
- "width": "150px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Today",
- "fetch_if_empty": 0,
- "fieldname": "transaction_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": 1,
- "label": "Date",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "transaction_date",
- "oldfieldtype": "Date",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
- "width": "160px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "delivery_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_standard_filter": 0,
- "label": "Delivery Date",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "description": "",
- "fetch_if_empty": 0,
- "fieldname": "po_no",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Customer's Purchase Order",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "po_no",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
- "width": "100px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.po_no",
- "description": "",
- "fetch_if_empty": 0,
- "fieldname": "po_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": "Customer's Purchase Order Date",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "po_date",
- "oldfieldtype": "Date",
- "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": "100px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "tax_id",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Tax Id",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
- "width": "100px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "collapsible_depends_on": "",
- "columns": 0,
- "depends_on": "customer",
- "fetch_if_empty": 0,
- "fieldname": "contact_info",
- "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": "Address and Contact",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-bullhorn",
- "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": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "customer_address",
- "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": "Customer Address",
- "length": 0,
- "no_copy": 0,
- "options": "Address",
- "permlevel": 0,
- "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": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "address_display",
- "fieldtype": "Small Text",
- "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": "Address",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "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": "contact_person",
- "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": "Contact Person",
- "length": 0,
- "no_copy": 0,
- "options": "Contact",
- "permlevel": 0,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "contact_display",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Contact",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "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": "contact_mobile",
- "fieldtype": "Small Text",
- "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": "Mobile No",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "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": "contact_email",
- "fieldtype": "Data",
- "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": "Contact Email",
- "length": 0,
- "no_copy": 0,
- "options": "Email",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "company_address_display",
- "fieldtype": "Small Text",
- "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,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "company_address",
- "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 Address",
- "length": 0,
- "no_copy": 0,
- "options": "Address",
- "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": "col_break46",
- "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,
- "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%"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "shipping_address_name",
- "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": "Shipping Address Name",
- "length": 0,
- "no_copy": 0,
- "options": "Address",
- "permlevel": 0,
- "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": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "shipping_address",
- "fieldtype": "Small Text",
- "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": "Shipping Address",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "description": "",
- "fetch_if_empty": 0,
- "fieldname": "customer_group",
- "fieldtype": "Link",
- "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": "Customer Group",
- "length": 0,
- "no_copy": 0,
- "options": "Customer Group",
- "permlevel": 0,
- "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,
- "description": "",
- "fetch_if_empty": 0,
- "fieldname": "territory",
- "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": "Territory",
- "length": 0,
- "no_copy": 0,
- "options": "Territory",
- "permlevel": 0,
- "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": 1,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "currency_and_price_list",
- "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": "Currency and Price List",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-tag",
- "permlevel": 0,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "currency",
- "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": "Currency",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "currency",
- "oldfieldtype": "Select",
- "options": "Currency",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "width": "100px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Rate at which customer's currency is converted to company's base currency",
- "fetch_if_empty": 0,
- "fieldname": "conversion_rate",
- "fieldtype": "Float",
- "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": "Exchange Rate",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "conversion_rate",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "precision": "9",
- "print_hide": 1,
- "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,
- "width": "100px"
- },
- {
- "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_break2",
- "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,
- "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%"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "selling_price_list",
- "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": "Price List",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "price_list_name",
- "oldfieldtype": "Select",
- "options": "Price List",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "width": "100px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "price_list_currency",
- "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": "Price List Currency",
- "length": 0,
- "no_copy": 0,
- "options": "Currency",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "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,
- "description": "Rate at which Price list currency is converted to company's base currency",
- "fetch_if_empty": 0,
- "fieldname": "plc_conversion_rate",
- "fieldtype": "Float",
- "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": "Price List Exchange Rate",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "9",
- "print_hide": 1,
- "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": "ignore_pricing_rule",
- "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": "Ignore Pricing Rule",
- "length": 0,
- "no_copy": 1,
- "permlevel": 1,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "sec_warehouse",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "set_warehouse",
- "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": "Set Source Warehouse",
- "length": 0,
- "no_copy": 0,
- "options": "Warehouse",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "items_section",
- "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,
- "oldfieldtype": "Section Break",
- "options": "fa fa-shopping-cart",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "scan_barcode",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Scan Barcode",
- "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": 1,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "items",
- "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": "Items",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "sales_order_details",
- "oldfieldtype": "Table",
- "options": "Sales Order Item",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "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": "pricing_rule_details",
- "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": "Pricing Rules",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "pricing_rules",
- "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": "Pricing Rule Detail",
- "length": 0,
- "no_copy": 0,
- "options": "Pricing Rule Detail",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "section_break_31",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "column_break_33a",
- "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,
- "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": "total_qty",
- "fieldtype": "Float",
- "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": "Total Quantity",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "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": "base_total",
- "fieldtype": "Currency",
- "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": "Total (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "base_net_total",
- "fieldtype": "Currency",
- "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": "Net Total (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "net_total",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "width": "150px"
- },
- {
- "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_33",
- "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,
- "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": "total",
- "fieldtype": "Currency",
- "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": "Total",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "net_total",
- "fieldtype": "Currency",
- "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": "Net Total",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "total_net_weight",
- "fieldtype": "Float",
- "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": "Total Net Weight",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "taxes_section",
- "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": "Taxes and Charges",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "options": "fa fa-money",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "tax_category",
- "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": "Tax Category",
- "length": 0,
- "no_copy": 0,
- "options": "Tax Category",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "column_break_38",
- "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,
- "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": "shipping_rule",
- "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": "Shipping Rule",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Button",
- "options": "Shipping Rule",
- "permlevel": 0,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "section_break_40",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "taxes_and_charges",
- "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": "Sales Taxes and Charges Template",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "charge",
- "oldfieldtype": "Link",
- "options": "Sales Taxes and Charges Template",
- "permlevel": 0,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "taxes",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Sales Taxes and Charges",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "other_charges",
- "oldfieldtype": "Table",
- "options": "Sales Taxes and Charges",
- "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": 1,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "sec_tax_breakup",
- "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": "Tax Breakup",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "other_charges_calculation",
- "fieldtype": "Text",
- "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": "Taxes and Charges Calculation",
- "length": 0,
- "no_copy": 1,
- "oldfieldtype": "HTML",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "section_break_43",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "base_total_taxes_and_charges",
- "fieldtype": "Currency",
- "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": "Total Taxes and Charges (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "other_charges_total",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "width": "150px"
- },
- {
- "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_46",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "total_taxes_and_charges",
- "fieldtype": "Currency",
- "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": "Total Taxes and Charges",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "loyalty_points_redemption",
- "fieldtype": "Section Break",
- "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": "Loyalty Points Redemption",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "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": "loyalty_points",
- "fieldtype": "Int",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Loyalty Points",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "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": "loyalty_amount",
- "fieldtype": "Currency",
- "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": "Loyalty Amount",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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": 1,
- "collapsible_depends_on": "discount_amount",
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_48",
- "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": "Additional Discount",
- "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,
- "default": "Grand Total",
- "fetch_if_empty": 0,
- "fieldname": "apply_discount_on",
- "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": "Apply Additional Discount On",
- "length": 0,
- "no_copy": 0,
- "options": "\nGrand Total\nNet Total",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "base_discount_amount",
- "fieldtype": "Currency",
- "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": "Additional Discount Amount (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "column_break_50",
- "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,
- "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": "additional_discount_percentage",
- "fieldtype": "Float",
- "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": "Additional Discount Percentage",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "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": "discount_amount",
- "fieldtype": "Currency",
- "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": "Additional Discount Amount",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "totals",
- "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,
- "oldfieldtype": "Section Break",
- "options": "fa fa-money",
- "permlevel": 0,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "base_grand_total",
- "fieldtype": "Currency",
- "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": "Grand Total (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "grand_total",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "width": "150px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "base_rounding_adjustment",
- "fieldtype": "Currency",
- "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": "Rounding Adjustment (Company Currency)",
- "length": 0,
- "no_copy": 1,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "base_rounded_total",
- "fieldtype": "Currency",
- "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": "Rounded Total (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "rounded_total",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "width": "150px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "In Words will be visible once you save the Sales Order.",
- "fetch_if_empty": 0,
- "fieldname": "base_in_words",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "In Words (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "in_words",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "width": "200px"
- },
- {
- "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_break3",
- "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",
- "permlevel": 0,
- "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,
- "width": "50%"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "grand_total",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Grand Total",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "grand_total_export",
- "oldfieldtype": "Currency",
- "options": "currency",
- "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,
- "width": "150px"
- },
- {
- "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": "rounding_adjustment",
- "fieldtype": "Currency",
- "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": "Rounding Adjustment",
- "length": 0,
- "no_copy": 1,
- "options": "currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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": 1,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "rounded_total",
- "fieldtype": "Currency",
- "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": "Rounded Total",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "rounded_total_export",
- "oldfieldtype": "Currency",
- "options": "currency",
- "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,
- "width": "150px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "in_words",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "In Words",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "in_words_export",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "width": "200px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "advance_paid",
- "fieldtype": "Currency",
- "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": "Advance Paid",
- "length": 0,
- "no_copy": 1,
- "options": "party_account_currency",
- "permlevel": 0,
- "print_hide": 1,
- "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": 1,
- "collapsible_depends_on": "packed_items",
- "columns": 0,
- "description": "",
- "fetch_if_empty": 0,
- "fieldname": "packing_list",
- "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": "Packing List",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "options": "fa fa-suitcase",
- "permlevel": 0,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "packed_items",
- "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": "Packed Items",
- "length": 0,
- "no_copy": 0,
- "options": "Packed Item",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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,
- "collapsible_depends_on": "",
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "payment_schedule_section",
- "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": "Payment Terms",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "payment_terms_template",
- "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": "Payment Terms Template",
- "length": 0,
- "no_copy": 0,
- "options": "Payment Terms Template",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "payment_schedule",
- "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": "Payment Schedule",
- "length": 0,
- "no_copy": 1,
- "options": "Payment Schedule",
- "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": 1,
- "collapsible_depends_on": "terms",
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "terms_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": "Terms and Conditions",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "options": "fa fa-legal",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "tc_name",
- "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": "Terms",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "tc_name",
- "oldfieldtype": "Link",
- "options": "Terms and Conditions",
- "permlevel": 0,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "terms",
- "fieldtype": "Text Editor",
- "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": "Terms and Conditions Details",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "terms",
- "oldfieldtype": "Text Editor",
- "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": 1,
- "collapsible_depends_on": "project",
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "more_info",
- "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": "More Information",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "options": "fa fa-file-text",
- "permlevel": 0,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "inter_company_order_reference",
- "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": "Inter Company Order Reference",
- "length": 0,
- "no_copy": 0,
- "options": "Purchase Order",
- "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,
- "description": "Track this Sales Order against any Project",
- "fetch_if_empty": 0,
- "fieldname": "project",
- "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": "Project",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "project",
- "oldfieldtype": "Link",
- "options": "Project",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "party_account_currency",
- "fieldtype": "Link",
- "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": "Party Account Currency",
- "length": 0,
- "no_copy": 1,
- "options": "Currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "column_break_77",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "source",
- "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",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "source",
- "oldfieldtype": "Select",
- "options": "Lead Source",
- "permlevel": 0,
- "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,
- "depends_on": "",
- "fetch_if_empty": 0,
- "fieldname": "campaign",
- "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": "Campaign",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "campaign",
- "oldfieldtype": "Link",
- "options": "Campaign",
- "permlevel": 0,
- "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": 1,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "printing_details",
- "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": "Printing Details",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "language",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Print Language",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "letter_head",
- "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": "Letter Head",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "letter_head",
- "oldfieldtype": "Select",
- "options": "Letter Head",
- "permlevel": 0,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "column_break4",
- "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",
- "permlevel": 0,
- "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,
- "width": "50%"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "select_print_heading",
- "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": "Print Heading",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "select_print_heading",
- "oldfieldtype": "Link",
- "options": "Print Heading",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "group_same_items",
- "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": "Group same items",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_78",
- "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": "Billing and Delivery Status",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Column Break",
- "permlevel": 0,
- "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,
- "width": "50%"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Draft",
- "fetch_if_empty": 0,
- "fieldname": "status",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Status",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "status",
- "oldfieldtype": "Select",
- "options": "\nDraft\nOn Hold\nTo Deliver and Bill\nTo Bill\nTo Deliver\nCompleted\nCancelled\nClosed",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
- "width": "100px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "delivery_status",
- "fieldtype": "Select",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 1,
- "label": "Delivery Status",
- "length": 0,
- "no_copy": 1,
- "options": "Not Delivered\nFully Delivered\nPartly Delivered\nClosed\nNot Applicable",
- "permlevel": 0,
- "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,
- "depends_on": "eval:!doc.__islocal",
- "description": "% of materials delivered against this Sales Order",
- "fetch_if_empty": 0,
- "fieldname": "per_delivered",
- "fieldtype": "Percent",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "% Delivered",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "per_delivered",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "width": "100px"
- },
- {
- "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_81",
- "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,
- "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.__islocal",
- "description": "% of materials billed against this Sales Order",
- "fetch_if_empty": 0,
- "fieldname": "per_billed",
- "fieldtype": "Percent",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "% Amount Billed",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "per_billed",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "print_hide": 1,
- "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,
- "width": "100px"
- },
- {
- "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": "billing_status",
- "fieldtype": "Select",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 1,
- "label": "Billing Status",
- "length": 0,
- "no_copy": 1,
- "options": "Not Billed\nFully Billed\nPartly Billed\nClosed",
- "permlevel": 0,
- "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": 1,
- "collapsible_depends_on": "commission_rate",
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "sales_team_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": "Commission",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "options": "fa fa-group",
- "permlevel": 0,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "sales_partner",
- "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": "Sales Partner",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "sales_partner",
- "oldfieldtype": "Link",
- "options": "Sales Partner",
- "permlevel": 0,
- "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,
- "width": "150px"
- },
- {
- "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_break7",
- "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,
- "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,
- "width": "50%"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "commission_rate",
- "fieldtype": "Float",
- "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": "Commission Rate",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "commission_rate",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "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,
- "width": "100px"
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "total_commission",
- "fieldtype": "Currency",
- "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": "Total Commission",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "total_commission",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "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": 1,
- "collapsible_depends_on": "sales_team",
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break1",
- "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": "Sales Team",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "sales_team",
- "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": "Sales Team1",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "sales_team",
- "oldfieldtype": "Table",
- "options": "Sales Team",
- "permlevel": 0,
- "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": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "subscription_section",
- "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": "Auto Repeat Section",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "description": "",
- "fetch_if_empty": 0,
- "fieldname": "from_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": "From Date",
- "length": 0,
- "no_copy": 1,
- "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": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "description": "",
- "fetch_if_empty": 0,
- "fieldname": "to_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": "To Date",
- "length": 0,
- "no_copy": 1,
- "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,
- "fetch_if_empty": 0,
- "fieldname": "column_break_108",
- "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,
- "fetch_if_empty": 0,
- "fieldname": "auto_repeat",
- "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": "Auto Repeat",
- "length": 0,
- "no_copy": 0,
- "options": "Auto Repeat",
- "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,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval: doc.auto_repeat",
- "fetch_if_empty": 0,
- "fieldname": "update_auto_repeat_reference",
- "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": "Update Auto Repeat Reference",
- "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
- }
- ],
- "has_web_view": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-file-text",
- "idx": 105,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-04-18 12:05:23.464968",
- "modified_by": "Administrator",
- "module": "Selling",
- "name": "Sales Order",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Sales User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
- "write": 1
- },
- {
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 1,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Sales Manager",
- "set_user_permissions": 1,
- "share": 1,
- "submit": 1,
- "write": 1
- },
- {
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Maintenance User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
- "write": 1
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 0,
- "role": "Accounts User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 1,
- "role": "Stock User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
- {
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 1,
- "print": 0,
- "read": 1,
- "report": 0,
- "role": "Sales Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 0,
- "read_only": 0,
- "search_fields": "status,transaction_date,customer,customer_name, territory,order_type,company",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "timeline_field": "customer",
- "title_field": "title",
- "track_changes": 1,
- "track_seen": 1,
- "track_views": 0
- }
\ No newline at end of file
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "creation": "2013-06-18 12:39:59",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "customer_section",
+ "column_break0",
+ "title",
+ "naming_series",
+ "customer",
+ "customer_name",
+ "order_type",
+ "column_break1",
+ "amended_from",
+ "company",
+ "transaction_date",
+ "delivery_date",
+ "po_no",
+ "po_date",
+ "tax_id",
+ "contact_info",
+ "customer_address",
+ "address_display",
+ "contact_person",
+ "contact_display",
+ "contact_phone",
+ "contact_mobile",
+ "contact_email",
+ "company_address_display",
+ "company_address",
+ "col_break46",
+ "shipping_address_name",
+ "shipping_address",
+ "customer_group",
+ "territory",
+ "currency_and_price_list",
+ "currency",
+ "conversion_rate",
+ "column_break2",
+ "selling_price_list",
+ "price_list_currency",
+ "plc_conversion_rate",
+ "ignore_pricing_rule",
+ "sec_warehouse",
+ "set_warehouse",
+ "items_section",
+ "scan_barcode",
+ "items",
+ "pricing_rule_details",
+ "pricing_rules",
+ "section_break_31",
+ "column_break_33a",
+ "total_qty",
+ "base_total",
+ "base_net_total",
+ "column_break_33",
+ "total",
+ "net_total",
+ "total_net_weight",
+ "taxes_section",
+ "tax_category",
+ "column_break_38",
+ "shipping_rule",
+ "section_break_40",
+ "taxes_and_charges",
+ "taxes",
+ "sec_tax_breakup",
+ "other_charges_calculation",
+ "section_break_43",
+ "base_total_taxes_and_charges",
+ "column_break_46",
+ "total_taxes_and_charges",
+ "loyalty_points_redemption",
+ "loyalty_points",
+ "loyalty_amount",
+ "section_break_48",
+ "apply_discount_on",
+ "base_discount_amount",
+ "column_break_50",
+ "additional_discount_percentage",
+ "discount_amount",
+ "totals",
+ "base_grand_total",
+ "base_rounding_adjustment",
+ "base_rounded_total",
+ "base_in_words",
+ "column_break3",
+ "grand_total",
+ "rounding_adjustment",
+ "rounded_total",
+ "in_words",
+ "advance_paid",
+ "packing_list",
+ "packed_items",
+ "payment_schedule_section",
+ "payment_terms_template",
+ "payment_schedule",
+ "terms_section_break",
+ "tc_name",
+ "terms",
+ "more_info",
+ "inter_company_order_reference",
+ "project",
+ "party_account_currency",
+ "column_break_77",
+ "source",
+ "campaign",
+ "printing_details",
+ "language",
+ "letter_head",
+ "column_break4",
+ "select_print_heading",
+ "group_same_items",
+ "section_break_78",
+ "status",
+ "delivery_status",
+ "per_delivered",
+ "column_break_81",
+ "per_billed",
+ "billing_status",
+ "sales_team_section_break",
+ "sales_partner",
+ "column_break7",
+ "commission_rate",
+ "total_commission",
+ "section_break1",
+ "sales_team",
+ "subscription_section",
+ "from_date",
+ "to_date",
+ "column_break_108",
+ "auto_repeat",
+ "update_auto_repeat_reference"
+ ],
+ "fields": [
+ {
+ "fieldname": "customer_section",
+ "fieldtype": "Section Break",
+ "options": "fa fa-user"
+ },
+ {
+ "fieldname": "column_break0",
+ "fieldtype": "Column Break",
+ "oldfieldtype": "Column Break",
+ "width": "50%"
+ },
+ {
+ "allow_on_submit": 1,
+ "default": "{customer_name}",
+ "fieldname": "title",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Title",
+ "no_copy": 1,
+ "print_hide": 1
+ },
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "no_copy": 1,
+ "oldfieldname": "naming_series",
+ "oldfieldtype": "Select",
+ "options": "SAL-ORD-.YYYY.-",
+ "print_hide": 1,
+ "reqd": 1,
+ "set_only_once": 1
+ },
+ {
+ "bold": 1,
+ "fieldname": "customer",
+ "fieldtype": "Link",
+ "in_global_search": 1,
+ "in_standard_filter": 1,
+ "label": "Customer",
+ "oldfieldname": "customer",
+ "oldfieldtype": "Link",
+ "options": "Customer",
+ "print_hide": 1,
+ "reqd": 1,
+ "search_index": 1
+ },
+ {
+ "bold": 1,
+ "fetch_from": "customer.customer_name",
+ "fieldname": "customer_name",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "label": "Customer Name",
+ "read_only": 1
+ },
+ {
+ "default": "Sales",
+ "fieldname": "order_type",
+ "fieldtype": "Select",
+ "label": "Order Type",
+ "oldfieldname": "order_type",
+ "oldfieldtype": "Select",
+ "options": "\nSales\nMaintenance\nShopping Cart",
+ "print_hide": 1,
+ "reqd": 1
+ },
+ {
+ "fieldname": "column_break1",
+ "fieldtype": "Column Break",
+ "oldfieldtype": "Column Break",
+ "width": "50%"
+ },
+ {
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "ignore_user_permissions": 1,
+ "label": "Amended From",
+ "no_copy": 1,
+ "oldfieldname": "amended_from",
+ "oldfieldtype": "Data",
+ "options": "Sales Order",
+ "print_hide": 1,
+ "read_only": 1,
+ "width": "150px"
+ },
+ {
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "in_standard_filter": 1,
+ "label": "Company",
+ "oldfieldname": "company",
+ "oldfieldtype": "Link",
+ "options": "Company",
+ "print_hide": 1,
+ "remember_last_selected_value": 1,
+ "reqd": 1,
+ "width": "150px"
+ },
+ {
+ "default": "Today",
+ "fieldname": "transaction_date",
+ "fieldtype": "Date",
+ "in_standard_filter": 1,
+ "label": "Date",
+ "no_copy": 1,
+ "oldfieldname": "transaction_date",
+ "oldfieldtype": "Date",
+ "reqd": 1,
+ "search_index": 1,
+ "width": "160px"
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "delivery_date",
+ "fieldtype": "Date",
+ "in_list_view": 1,
+ "label": "Delivery Date",
+ "no_copy": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "po_no",
+ "fieldtype": "Data",
+ "label": "Customer's Purchase Order",
+ "oldfieldname": "po_no",
+ "oldfieldtype": "Data",
+ "width": "100px"
+ },
+ {
+ "allow_on_submit": 1,
+ "depends_on": "eval:doc.po_no",
+ "fieldname": "po_date",
+ "fieldtype": "Date",
+ "label": "Customer's Purchase Order Date",
+ "oldfieldname": "po_date",
+ "oldfieldtype": "Date",
+ "width": "100px"
+ },
+ {
+ "fieldname": "tax_id",
+ "fieldtype": "Data",
+ "label": "Tax Id",
+ "read_only": 1,
+ "width": "100px"
+ },
+ {
+ "collapsible": 1,
+ "depends_on": "customer",
+ "fieldname": "contact_info",
+ "fieldtype": "Section Break",
+ "label": "Address and Contact",
+ "options": "fa fa-bullhorn"
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "customer_address",
+ "fieldtype": "Link",
+ "label": "Customer Address",
+ "options": "Address",
+ "print_hide": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "address_display",
+ "fieldtype": "Small Text",
+ "label": "Address",
+ "read_only": 1
+ },
+ {
+ "fieldname": "contact_person",
+ "fieldtype": "Link",
+ "label": "Contact Person",
+ "options": "Contact",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "contact_display",
+ "fieldtype": "Small Text",
+ "in_global_search": 1,
+ "label": "Contact",
+ "read_only": 1
+ },
+ {
+ "fieldname": "contact_mobile",
+ "fieldtype": "Small Text",
+ "label": "Mobile No",
+ "read_only": 1
+ },
+ {
+ "fieldname": "contact_email",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Contact Email",
+ "options": "Email",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "company_address_display",
+ "fieldtype": "Small Text",
+ "read_only": 1
+ },
+ {
+ "fieldname": "company_address",
+ "fieldtype": "Link",
+ "label": "Company Address",
+ "options": "Address"
+ },
+ {
+ "fieldname": "col_break46",
+ "fieldtype": "Column Break",
+ "width": "50%"
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "shipping_address_name",
+ "fieldtype": "Link",
+ "label": "Shipping Address Name",
+ "options": "Address",
+ "print_hide": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "shipping_address",
+ "fieldtype": "Small Text",
+ "label": "Shipping Address",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "customer_group",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Customer Group",
+ "options": "Customer Group",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "territory",
+ "fieldtype": "Link",
+ "label": "Territory",
+ "options": "Territory",
+ "print_hide": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "currency_and_price_list",
+ "fieldtype": "Section Break",
+ "label": "Currency and Price List",
+ "options": "fa fa-tag",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "currency",
+ "fieldtype": "Link",
+ "label": "Currency",
+ "oldfieldname": "currency",
+ "oldfieldtype": "Select",
+ "options": "Currency",
+ "print_hide": 1,
+ "reqd": 1,
+ "width": "100px"
+ },
+ {
+ "description": "Rate at which customer's currency is converted to company's base currency",
+ "fieldname": "conversion_rate",
+ "fieldtype": "Float",
+ "label": "Exchange Rate",
+ "oldfieldname": "conversion_rate",
+ "oldfieldtype": "Currency",
+ "precision": "9",
+ "print_hide": 1,
+ "reqd": 1,
+ "width": "100px"
+ },
+ {
+ "fieldname": "column_break2",
+ "fieldtype": "Column Break",
+ "width": "50%"
+ },
+ {
+ "fieldname": "selling_price_list",
+ "fieldtype": "Link",
+ "label": "Price List",
+ "oldfieldname": "price_list_name",
+ "oldfieldtype": "Select",
+ "options": "Price List",
+ "print_hide": 1,
+ "reqd": 1,
+ "width": "100px"
+ },
+ {
+ "fieldname": "price_list_currency",
+ "fieldtype": "Link",
+ "label": "Price List Currency",
+ "options": "Currency",
+ "print_hide": 1,
+ "read_only": 1,
+ "reqd": 1
+ },
+ {
+ "description": "Rate at which Price list currency is converted to company's base currency",
+ "fieldname": "plc_conversion_rate",
+ "fieldtype": "Float",
+ "label": "Price List Exchange Rate",
+ "precision": "9",
+ "print_hide": 1,
+ "reqd": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "ignore_pricing_rule",
+ "fieldtype": "Check",
+ "label": "Ignore Pricing Rule",
+ "no_copy": 1,
+ "permlevel": 1,
+ "print_hide": 1
+ },
+ {
+ "fieldname": "sec_warehouse",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "set_warehouse",
+ "fieldtype": "Link",
+ "label": "Set Source Warehouse",
+ "options": "Warehouse",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "items_section",
+ "fieldtype": "Section Break",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-shopping-cart"
+ },
+ {
+ "fieldname": "scan_barcode",
+ "fieldtype": "Data",
+ "label": "Scan Barcode"
+ },
+ {
+ "allow_bulk_edit": 1,
+ "fieldname": "items",
+ "fieldtype": "Table",
+ "label": "Items",
+ "oldfieldname": "sales_order_details",
+ "oldfieldtype": "Table",
+ "options": "Sales Order Item",
+ "reqd": 1
+ },
+ {
+ "fieldname": "pricing_rule_details",
+ "fieldtype": "Section Break",
+ "label": "Pricing Rules"
+ },
+ {
+ "fieldname": "pricing_rules",
+ "fieldtype": "Table",
+ "label": "Pricing Rule Detail",
+ "options": "Pricing Rule Detail",
+ "read_only": 1
+ },
+ {
+ "fieldname": "section_break_31",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "column_break_33a",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "total_qty",
+ "fieldtype": "Float",
+ "label": "Total Quantity",
+ "read_only": 1
+ },
+ {
+ "fieldname": "base_total",
+ "fieldtype": "Currency",
+ "label": "Total (Company Currency)",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "base_net_total",
+ "fieldtype": "Currency",
+ "label": "Net Total (Company Currency)",
+ "oldfieldname": "net_total",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1,
+ "width": "150px"
+ },
+ {
+ "fieldname": "column_break_33",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "total",
+ "fieldtype": "Currency",
+ "label": "Total",
+ "options": "currency",
+ "read_only": 1
+ },
+ {
+ "fieldname": "net_total",
+ "fieldtype": "Currency",
+ "label": "Net Total",
+ "options": "currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "total_net_weight",
+ "fieldtype": "Float",
+ "label": "Total Net Weight",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "taxes_section",
+ "fieldtype": "Section Break",
+ "label": "Taxes and Charges",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-money"
+ },
+ {
+ "fieldname": "tax_category",
+ "fieldtype": "Link",
+ "label": "Tax Category",
+ "options": "Tax Category",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "column_break_38",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "shipping_rule",
+ "fieldtype": "Link",
+ "label": "Shipping Rule",
+ "oldfieldtype": "Button",
+ "options": "Shipping Rule",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "section_break_40",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "taxes_and_charges",
+ "fieldtype": "Link",
+ "label": "Sales Taxes and Charges Template",
+ "oldfieldname": "charge",
+ "oldfieldtype": "Link",
+ "options": "Sales Taxes and Charges Template",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "taxes",
+ "fieldtype": "Table",
+ "label": "Sales Taxes and Charges",
+ "oldfieldname": "other_charges",
+ "oldfieldtype": "Table",
+ "options": "Sales Taxes and Charges"
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "sec_tax_breakup",
+ "fieldtype": "Section Break",
+ "label": "Tax Breakup"
+ },
+ {
+ "fieldname": "other_charges_calculation",
+ "fieldtype": "Text",
+ "label": "Taxes and Charges Calculation",
+ "no_copy": 1,
+ "oldfieldtype": "HTML",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "section_break_43",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "base_total_taxes_and_charges",
+ "fieldtype": "Currency",
+ "label": "Total Taxes and Charges (Company Currency)",
+ "oldfieldname": "other_charges_total",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1,
+ "width": "150px"
+ },
+ {
+ "fieldname": "column_break_46",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "total_taxes_and_charges",
+ "fieldtype": "Currency",
+ "label": "Total Taxes and Charges",
+ "options": "currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "loyalty_points_redemption",
+ "fieldtype": "Section Break",
+ "hidden": 1,
+ "label": "Loyalty Points Redemption",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "loyalty_points",
+ "fieldtype": "Int",
+ "hidden": 1,
+ "label": "Loyalty Points",
+ "read_only": 1
+ },
+ {
+ "fieldname": "loyalty_amount",
+ "fieldtype": "Currency",
+ "hidden": 1,
+ "label": "Loyalty Amount",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "collapsible": 1,
+ "collapsible_depends_on": "discount_amount",
+ "fieldname": "section_break_48",
+ "fieldtype": "Section Break",
+ "label": "Additional Discount"
+ },
+ {
+ "default": "Grand Total",
+ "fieldname": "apply_discount_on",
+ "fieldtype": "Select",
+ "label": "Apply Additional Discount On",
+ "options": "\nGrand Total\nNet Total",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "base_discount_amount",
+ "fieldtype": "Currency",
+ "label": "Additional Discount Amount (Company Currency)",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_50",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "additional_discount_percentage",
+ "fieldtype": "Float",
+ "label": "Additional Discount Percentage",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "discount_amount",
+ "fieldtype": "Currency",
+ "label": "Additional Discount Amount",
+ "options": "currency",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "totals",
+ "fieldtype": "Section Break",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-money",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "base_grand_total",
+ "fieldtype": "Currency",
+ "label": "Grand Total (Company Currency)",
+ "oldfieldname": "grand_total",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1,
+ "width": "150px"
+ },
+ {
+ "fieldname": "base_rounding_adjustment",
+ "fieldtype": "Currency",
+ "label": "Rounding Adjustment (Company Currency)",
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "base_rounded_total",
+ "fieldtype": "Currency",
+ "label": "Rounded Total (Company Currency)",
+ "oldfieldname": "rounded_total",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1,
+ "width": "150px"
+ },
+ {
+ "description": "In Words will be visible once you save the Sales Order.",
+ "fieldname": "base_in_words",
+ "fieldtype": "Data",
+ "label": "In Words (Company Currency)",
+ "oldfieldname": "in_words",
+ "oldfieldtype": "Data",
+ "print_hide": 1,
+ "read_only": 1,
+ "width": "200px"
+ },
+ {
+ "fieldname": "column_break3",
+ "fieldtype": "Column Break",
+ "oldfieldtype": "Column Break",
+ "print_hide": 1,
+ "width": "50%"
+ },
+ {
+ "fieldname": "grand_total",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Grand Total",
+ "oldfieldname": "grand_total_export",
+ "oldfieldtype": "Currency",
+ "options": "currency",
+ "read_only": 1,
+ "width": "150px"
+ },
+ {
+ "fieldname": "rounding_adjustment",
+ "fieldtype": "Currency",
+ "label": "Rounding Adjustment",
+ "no_copy": 1,
+ "options": "currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "bold": 1,
+ "fieldname": "rounded_total",
+ "fieldtype": "Currency",
+ "label": "Rounded Total",
+ "oldfieldname": "rounded_total_export",
+ "oldfieldtype": "Currency",
+ "options": "currency",
+ "read_only": 1,
+ "width": "150px"
+ },
+ {
+ "fieldname": "in_words",
+ "fieldtype": "Data",
+ "label": "In Words",
+ "oldfieldname": "in_words_export",
+ "oldfieldtype": "Data",
+ "print_hide": 1,
+ "read_only": 1,
+ "width": "200px"
+ },
+ {
+ "fieldname": "advance_paid",
+ "fieldtype": "Currency",
+ "label": "Advance Paid",
+ "no_copy": 1,
+ "options": "party_account_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "collapsible": 1,
+ "collapsible_depends_on": "packed_items",
+ "fieldname": "packing_list",
+ "fieldtype": "Section Break",
+ "label": "Packing List",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-suitcase",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "packed_items",
+ "fieldtype": "Table",
+ "label": "Packed Items",
+ "options": "Packed Item",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "payment_schedule_section",
+ "fieldtype": "Section Break",
+ "label": "Payment Terms"
+ },
+ {
+ "fieldname": "payment_terms_template",
+ "fieldtype": "Link",
+ "label": "Payment Terms Template",
+ "options": "Payment Terms Template",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "payment_schedule",
+ "fieldtype": "Table",
+ "label": "Payment Schedule",
+ "no_copy": 1,
+ "options": "Payment Schedule",
+ "print_hide": 1
+ },
+ {
+ "collapsible": 1,
+ "collapsible_depends_on": "terms",
+ "fieldname": "terms_section_break",
+ "fieldtype": "Section Break",
+ "label": "Terms and Conditions",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-legal"
+ },
+ {
+ "fieldname": "tc_name",
+ "fieldtype": "Link",
+ "label": "Terms",
+ "oldfieldname": "tc_name",
+ "oldfieldtype": "Link",
+ "options": "Terms and Conditions",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "terms",
+ "fieldtype": "Text Editor",
+ "label": "Terms and Conditions Details",
+ "oldfieldname": "terms",
+ "oldfieldtype": "Text Editor"
+ },
+ {
+ "collapsible": 1,
+ "collapsible_depends_on": "project",
+ "fieldname": "more_info",
+ "fieldtype": "Section Break",
+ "label": "More Information",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-file-text",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "inter_company_order_reference",
+ "fieldtype": "Link",
+ "label": "Inter Company Order Reference",
+ "options": "Purchase Order"
+ },
+ {
+ "description": "Track this Sales Order against any Project",
+ "fieldname": "project",
+ "fieldtype": "Link",
+ "label": "Project",
+ "oldfieldname": "project",
+ "oldfieldtype": "Link",
+ "options": "Project"
+ },
+ {
+ "fieldname": "party_account_currency",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Party Account Currency",
+ "no_copy": 1,
+ "options": "Currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_77",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "source",
+ "fieldtype": "Link",
+ "label": "Source",
+ "oldfieldname": "source",
+ "oldfieldtype": "Select",
+ "options": "Lead Source",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "campaign",
+ "fieldtype": "Link",
+ "label": "Campaign",
+ "oldfieldname": "campaign",
+ "oldfieldtype": "Link",
+ "options": "Campaign",
+ "print_hide": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "printing_details",
+ "fieldtype": "Section Break",
+ "label": "Printing Details"
+ },
+ {
+ "fieldname": "language",
+ "fieldtype": "Data",
+ "label": "Print Language",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "letter_head",
+ "fieldtype": "Link",
+ "label": "Letter Head",
+ "oldfieldname": "letter_head",
+ "oldfieldtype": "Select",
+ "options": "Letter Head",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "column_break4",
+ "fieldtype": "Column Break",
+ "oldfieldtype": "Column Break",
+ "print_hide": 1,
+ "width": "50%"
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "select_print_heading",
+ "fieldtype": "Link",
+ "label": "Print Heading",
+ "no_copy": 1,
+ "oldfieldname": "select_print_heading",
+ "oldfieldtype": "Link",
+ "options": "Print Heading",
+ "print_hide": 1,
+ "report_hide": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "default": "0",
+ "fieldname": "group_same_items",
+ "fieldtype": "Check",
+ "label": "Group same items",
+ "print_hide": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "section_break_78",
+ "fieldtype": "Section Break",
+ "label": "Billing and Delivery Status",
+ "oldfieldtype": "Column Break",
+ "print_hide": 1,
+ "width": "50%"
+ },
+ {
+ "default": "Draft",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Status",
+ "no_copy": 1,
+ "oldfieldname": "status",
+ "oldfieldtype": "Select",
+ "options": "\nDraft\nOn Hold\nTo Deliver and Bill\nTo Bill\nTo Deliver\nCompleted\nCancelled\nClosed",
+ "print_hide": 1,
+ "read_only": 1,
+ "reqd": 1,
+ "search_index": 1,
+ "width": "100px"
+ },
+ {
+ "fieldname": "delivery_status",
+ "fieldtype": "Select",
+ "hidden": 1,
+ "in_standard_filter": 1,
+ "label": "Delivery Status",
+ "no_copy": 1,
+ "options": "Not Delivered\nFully Delivered\nPartly Delivered\nClosed\nNot Applicable",
+ "print_hide": 1
+ },
+ {
+ "depends_on": "eval:!doc.__islocal",
+ "description": "% of materials delivered against this Sales Order",
+ "fieldname": "per_delivered",
+ "fieldtype": "Percent",
+ "in_list_view": 1,
+ "label": "% Delivered",
+ "no_copy": 1,
+ "oldfieldname": "per_delivered",
+ "oldfieldtype": "Currency",
+ "print_hide": 1,
+ "read_only": 1,
+ "width": "100px"
+ },
+ {
+ "fieldname": "column_break_81",
+ "fieldtype": "Column Break"
+ },
+ {
+ "depends_on": "eval:!doc.__islocal",
+ "description": "% of materials billed against this Sales Order",
+ "fieldname": "per_billed",
+ "fieldtype": "Percent",
+ "in_list_view": 1,
+ "label": "% Amount Billed",
+ "no_copy": 1,
+ "oldfieldname": "per_billed",
+ "oldfieldtype": "Currency",
+ "print_hide": 1,
+ "read_only": 1,
+ "width": "100px"
+ },
+ {
+ "fieldname": "billing_status",
+ "fieldtype": "Select",
+ "hidden": 1,
+ "in_standard_filter": 1,
+ "label": "Billing Status",
+ "no_copy": 1,
+ "options": "Not Billed\nFully Billed\nPartly Billed\nClosed",
+ "print_hide": 1
+ },
+ {
+ "collapsible": 1,
+ "collapsible_depends_on": "commission_rate",
+ "fieldname": "sales_team_section_break",
+ "fieldtype": "Section Break",
+ "label": "Commission",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-group",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "sales_partner",
+ "fieldtype": "Link",
+ "label": "Sales Partner",
+ "oldfieldname": "sales_partner",
+ "oldfieldtype": "Link",
+ "options": "Sales Partner",
+ "print_hide": 1,
+ "width": "150px"
+ },
+ {
+ "fieldname": "column_break7",
+ "fieldtype": "Column Break",
+ "print_hide": 1,
+ "width": "50%"
+ },
+ {
+ "fieldname": "commission_rate",
+ "fieldtype": "Float",
+ "label": "Commission Rate",
+ "oldfieldname": "commission_rate",
+ "oldfieldtype": "Currency",
+ "print_hide": 1,
+ "width": "100px"
+ },
+ {
+ "fieldname": "total_commission",
+ "fieldtype": "Currency",
+ "label": "Total Commission",
+ "oldfieldname": "total_commission",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "print_hide": 1
+ },
+ {
+ "collapsible": 1,
+ "collapsible_depends_on": "sales_team",
+ "fieldname": "section_break1",
+ "fieldtype": "Section Break",
+ "label": "Sales Team",
+ "print_hide": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "sales_team",
+ "fieldtype": "Table",
+ "label": "Sales Team1",
+ "oldfieldname": "sales_team",
+ "oldfieldtype": "Table",
+ "options": "Sales Team",
+ "print_hide": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "subscription_section",
+ "fieldtype": "Section Break",
+ "label": "Auto Repeat Section",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "from_date",
+ "fieldtype": "Date",
+ "label": "From Date",
+ "no_copy": 1
+ },
+ {
+ "allow_on_submit": 1,
+ "fieldname": "to_date",
+ "fieldtype": "Date",
+ "label": "To Date",
+ "no_copy": 1
+ },
+ {
+ "fieldname": "column_break_108",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "auto_repeat",
+ "fieldtype": "Link",
+ "label": "Auto Repeat",
+ "options": "Auto Repeat"
+ },
+ {
+ "allow_on_submit": 1,
+ "depends_on": "eval: doc.auto_repeat",
+ "fieldname": "update_auto_repeat_reference",
+ "fieldtype": "Button",
+ "label": "Update Auto Repeat Reference"
+ },
+ {
+ "fieldname": "contact_phone",
+ "fieldtype": "Data",
+ "label": "Phone",
+ "read_only": 1
+ }
+ ],
+ "icon": "fa fa-file-text",
+ "idx": 105,
+ "is_submittable": 1,
+ "modified": "2019-09-12 02:13:56.308839",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Sales Order",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Sales User",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "import": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Sales Manager",
+ "set_user_permissions": 1,
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Maintenance User",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "role": "Accounts User"
+ },
+ {
+ "read": 1,
+ "report": 1,
+ "role": "Stock User"
+ },
+ {
+ "permlevel": 1,
+ "read": 1,
+ "role": "Sales Manager",
+ "write": 1
+ }
+ ],
+ "search_fields": "status,transaction_date,customer,customer_name, territory,order_type,company",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "timeline_field": "customer",
+ "title_field": "title",
+ "track_changes": 1,
+ "track_seen": 1
+}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 09dc9a9..12b9a8e 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -72,9 +72,7 @@
frappe.msgprint(_("Warning: Sales Order {0} already exists against Customer's Purchase Order {1}").format(so[0][0], self.po_no))
def validate_for_items(self):
- check_list = []
for d in self.get('items'):
- check_list.append(cstr(d.item_code))
# used for production plan
d.transaction_date = self.transaction_date
@@ -83,13 +81,6 @@
where item_code = %s and warehouse = %s", (d.item_code, d.warehouse))
d.projected_qty = tot_avail_qty and flt(tot_avail_qty[0][0]) or 0
- # check for same entry multiple times
- unique_chk_list = set(check_list)
- if len(unique_chk_list) != len(check_list) and \
- not cint(frappe.db.get_single_value("Selling Settings", "allow_multiple_items")):
- frappe.msgprint(_("Same item has been entered multiple times"),
- title=_("Warning"), indicator='orange')
-
def product_bundle_has_stock_item(self, product_bundle):
"""Returns true if product bundle has stock item"""
ret = len(frappe.db.sql("""select i.name from tabItem i, `tabProduct Bundle Item` pbi
@@ -217,7 +208,9 @@
def check_credit_limit(self):
# if bypass credit limit check is set to true (1) at sales order level,
# then we need not to check credit limit and vise versa
- if not cint(frappe.get_cached_value("Customer", self.customer, "bypass_credit_limit_check_at_sales_order")):
+ if not cint(frappe.db.get_value("Customer Credit Limit",
+ {'parent': self.customer, 'parenttype': 'Customer', 'company': self.company},
+ "bypass_credit_limit_check")):
check_credit_limit(self.customer, self.company)
def check_nextdoc_docstatus(self):
@@ -527,7 +520,7 @@
"doctype": "Material Request Item",
"field_map": {
"parent": "sales_order",
- "stock_uom": "uom"
+ "uom": "stock_uom"
},
"postprocess": update_item
},
@@ -568,7 +561,7 @@
return doc
@frappe.whitelist()
-def make_delivery_note(source_name, target_doc=None):
+def make_delivery_note(source_name, target_doc=None, skip_item_mapping=False):
def set_missing_values(source, target):
target.ignore_pricing_rule = 1
target.run_method("set_missing_values")
@@ -593,23 +586,13 @@
or item.get("buying_cost_center") \
or item_group.get("buying_cost_center")
- target_doc = get_mapped_doc("Sales Order", source_name, {
+ mapper = {
"Sales Order": {
"doctype": "Delivery Note",
"validation": {
"docstatus": ["=", 1]
}
},
- "Sales Order Item": {
- "doctype": "Delivery Note Item",
- "field_map": {
- "rate": "rate",
- "name": "so_detail",
- "parent": "against_sales_order",
- },
- "postprocess": update_item,
- "condition": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1
- },
"Sales Taxes and Charges": {
"doctype": "Sales Taxes and Charges",
"add_if_empty": True
@@ -618,7 +601,21 @@
"doctype": "Sales Team",
"add_if_empty": True
}
- }, target_doc, set_missing_values)
+ }
+
+ if not skip_item_mapping:
+ mapper["Sales Order Item"] = {
+ "doctype": "Delivery Note Item",
+ "field_map": {
+ "rate": "rate",
+ "name": "so_detail",
+ "parent": "against_sales_order",
+ },
+ "postprocess": update_item,
+ "condition": lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1
+ }
+
+ target_doc = get_mapped_doc("Sales Order", source_name, mapper, target_doc, set_missing_values)
return target_doc
@@ -996,3 +993,33 @@
def make_inter_company_purchase_order(source_name, target_doc=None):
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_company_transaction
return make_inter_company_transaction("Sales Order", source_name, target_doc)
+
+@frappe.whitelist()
+def create_pick_list(source_name, target_doc=None):
+ def update_item_quantity(source, target, source_parent):
+ target.qty = flt(source.qty) - flt(source.delivered_qty)
+ target.stock_qty = (flt(source.qty) - flt(source.delivered_qty)) * flt(source.conversion_factor)
+
+ doc = get_mapped_doc('Sales Order', source_name, {
+ 'Sales Order': {
+ 'doctype': 'Pick List',
+ 'validation': {
+ 'docstatus': ['=', 1]
+ }
+ },
+ 'Sales Order Item': {
+ 'doctype': 'Pick List Item',
+ 'field_map': {
+ 'parent': 'sales_order',
+ 'name': 'sales_order_item'
+ },
+ 'postprocess': update_item_quantity,
+ 'condition': lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1
+ },
+ }, target_doc)
+
+ doc.purpose = 'Delivery against Sales Order'
+
+ doc.set_item_locations()
+
+ return doc
diff --git a/erpnext/selling/doctype/sales_order/sales_order_dashboard.py b/erpnext/selling/doctype/sales_order/sales_order_dashboard.py
index aab6db2..4126bc6 100644
--- a/erpnext/selling/doctype/sales_order/sales_order_dashboard.py
+++ b/erpnext/selling/doctype/sales_order/sales_order_dashboard.py
@@ -17,7 +17,7 @@
'transactions': [
{
'label': _('Fulfillment'),
- 'items': ['Sales Invoice', 'Delivery Note']
+ 'items': ['Sales Invoice', 'Pick List', 'Delivery Note']
},
{
'label': _('Purchasing'),
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_bypass_credit_limit_check.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_bypass_credit_limit_check.js
index dbd58c1..79d798b 100644
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_bypass_credit_limit_check.js
+++ b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_bypass_credit_limit_check.js
@@ -1,7 +1,7 @@
QUnit.module('Sales Order');
QUnit.test("test_sales_order_with_bypass_credit_limit_check", function(assert) {
-//#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
+//#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
assert.expect(2);
let done = assert.async();
frappe.run_serially([
@@ -10,8 +10,10 @@
() => frappe.quick_entry.dialog.$wrapper.find('.edit-full').click(),
() => frappe.timeout(1),
() => cur_frm.set_value("customer_name", "Test Customer 10"),
- () => cur_frm.set_value("credit_limit", 100.00),
- () => cur_frm.set_value("bypass_credit_limit_check_at_sales_order", 1),
+ () => cur_frm.add_child('credit_limits', {
+ 'company': cur_frm.doc.company || '_Test Company'
+ 'credit_limit': 1000,
+ 'bypass_credit_limit_check': 1}),
// save form
() => cur_frm.save(),
() => frappe.timeout(1),
@@ -22,10 +24,10 @@
() => frappe.timeout(1),
() => cur_frm.set_value("item_code", "Test Product 10"),
() => cur_frm.set_value("item_group", "Products"),
- () => cur_frm.set_value("standard_rate", 100),
+ () => cur_frm.set_value("standard_rate", 100),
// save form
() => cur_frm.save(),
- () => frappe.timeout(1),
+ () => frappe.timeout(1),
() => {
return frappe.tests.make('Sales Order', [
@@ -46,11 +48,11 @@
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(3),
() => {
-
+
assert.ok(cur_frm.doc.status=="To Deliver and Bill", "It is submited. Credit limit is NOT checked for sales order");
- },
+ },
() => done()
]);
});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_without_bypass_credit_limit_check.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_without_bypass_credit_limit_check.js
index 4e81fb0..8de39f9 100644
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order_without_bypass_credit_limit_check.js
+++ b/erpnext/selling/doctype/sales_order/tests/test_sales_order_without_bypass_credit_limit_check.js
@@ -1,7 +1,7 @@
QUnit.module('Sales Order');
QUnit.test("test_sales_order_without_bypass_credit_limit_check", function(assert) {
-//#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
+//#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
assert.expect(2);
let done = assert.async();
frappe.run_serially([
@@ -10,8 +10,10 @@
() => frappe.quick_entry.dialog.$wrapper.find('.edit-full').click(),
() => frappe.timeout(1),
() => cur_frm.set_value("customer_name", "Test Customer 11"),
- () => cur_frm.set_value("credit_limit", 100.00),
- () => cur_frm.set_value("bypass_credit_limit_check_at_sales_order", 0),
+ () => cur_frm.add_child('credit_limits', {
+ 'credit_limit': 1000,
+ 'company': '_Test Company',
+ 'bypass_credit_limit_check': 1}),
// save form
() => cur_frm.save(),
() => frappe.timeout(1),
@@ -21,10 +23,10 @@
() => frappe.click_link('Edit in full page'),
() => cur_frm.set_value("item_code", "Test Product 11"),
() => cur_frm.set_value("item_group", "Products"),
- () => cur_frm.set_value("standard_rate", 100),
+ () => cur_frm.set_value("standard_rate", 100),
// save form
() => cur_frm.save(),
- () => frappe.timeout(1),
+ () => frappe.timeout(1),
() => {
return frappe.tests.make('Sales Order', [
@@ -45,14 +47,14 @@
() => frappe.tests.click_button('Yes'),
() => frappe.timeout(3),
() => {
-
- if (cur_dialog.body.innerText.match(/^Credit limit has been crossed for customer.*$/))
- {
+
+ if (cur_dialog.body.innerText.match(/^Credit limit has been crossed for customer.*$/))
+ {
/*Match found */
assert.ok(true, "Credit Limit crossed message received");
}
-
-
+
+
},
() => cur_dialog.cancel(),
() => done()
diff --git a/erpnext/selling/doctype/sms_center/sms_center.py b/erpnext/selling/doctype/sms_center/sms_center.py
index bb6ba1f..289b045 100644
--- a/erpnext/selling/doctype/sms_center/sms_center.py
+++ b/erpnext/selling/doctype/sms_center/sms_center.py
@@ -31,7 +31,7 @@
self.sales_partner.replace("'", "\'") or " and ifnull(dl.link_name, '') != ''"
if self.send_to in ['All Contact', 'All Customer Contact', 'All Supplier Contact', 'All Sales Partner Contact']:
rec = frappe.db.sql("""select CONCAT(ifnull(c.first_name,''), ' ', ifnull(c.last_name,'')),
- c.mobile_no from `tabContact` c, `tabDynamic Link` dl where ifnull(c.mobile_no,'')!='' and
+ c.phone from `tabContact` c, `tabDynamic Link` dl where ifnull(c.phone,'')!='' and
c.docstatus != 2 and dl.parent = c.name%s""" % where_clause)
elif self.send_to == 'All Lead (Open)':
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js
index d233b41..d2c2d70 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.js
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.js
@@ -4,7 +4,7 @@
frappe.pages['point-of-sale'].on_page_load = function(wrapper) {
frappe.ui.make_app_page({
parent: wrapper,
- title: 'Point of Sale',
+ title: __('Point of Sale'),
single_column: true
});
diff --git a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
index ee0d72b..cd50568 100644
--- a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
+++ b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
@@ -29,7 +29,7 @@
if customer_naming_type == "Naming Series":
row = [d.name, d.customer_name, credit_limit, outstanding_amt, bal,
- d.bypass_credit_limit_check_at_sales_order, d.is_frozen,
+ d.bypass_credit_limit_check, d.is_frozen,
d.disabled]
else:
row = [d.name, credit_limit, outstanding_amt, bal,
@@ -60,9 +60,15 @@
conditions = ""
if filters.get("customer"):
- conditions += " where name = %(customer)s"
+ conditions += " AND c.name = " + filters.get("customer")
- return frappe.db.sql("""select name, customer_name,
- bypass_credit_limit_check_at_sales_order, is_frozen, disabled from `tabCustomer` %s
- """ % conditions, filters, as_dict=1)
-
+ return frappe.db.sql("""SELECT
+ c.name, c.customer_name,
+ ccl.bypass_credit_limit_check,
+ c.is_frozen, c.disabled
+ FROM `tabCustomer` c, `tabCustomer Credit Limit` ccl
+ WHERE
+ c.name = ccl.parent
+ AND ccl.company = %s
+ {0}
+ """.format(conditions), (filters.get("company")), as_dict=1) #nosec
diff --git a/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py b/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py
index 670b4e9..14d8031 100644
--- a/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py
+++ b/erpnext/selling/report/pending_so_items_for_purchase_request/pending_so_items_for_purchase_request.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
-from frappe.utils import cint,cstr
+from frappe.utils import flt
def execute(filters=None):
columns = get_columns()
@@ -100,7 +100,7 @@
so.transaction_date,
so.customer,
so.territory,
- sum(so_item.qty) as net_qty,
+ sum(so_item.qty) as total_qty,
so.company
FROM `tabSales Order` so, `tabSales Order Item` so_item
WHERE
@@ -111,10 +111,15 @@
so.name,so_item.item_code
""", as_dict = 1)
+ sales_orders = [row.name for row in sales_order_entry]
mr_records = frappe.get_all("Material Request Item",
- {"sales_order_item": ("!=",""), "docstatus": 1},
+ {"sales_order": ("in", sales_orders), "docstatus": 1},
["parent", "qty", "sales_order", "item_code"])
+ bundled_item_map = get_packed_items(sales_orders)
+
+ item_with_product_bundle = get_items_with_product_bundle([row.item_code for row in sales_order_entry])
+
materials_request_dict = {}
for record in mr_records:
@@ -131,27 +136,64 @@
if record.parent not in details.get('material_requests'):
details['material_requests'].append(record.parent)
- pending_so=[]
+ pending_so = []
for so in sales_order_entry:
- # fetch all the material request records for a sales order item
- key = (so.name, so.item_code)
- materials_request = materials_request_dict.get(key) or {}
+ if so.item_code not in item_with_product_bundle:
+ material_requests_against_so = materials_request_dict.get((so.name, so.item_code)) or {}
+ # check for pending sales order
+ if flt(so.total_qty) > flt(material_requests_against_so.get('qty')):
+ so_record = {
+ "item_code": so.item_code,
+ "item_name": so.item_name,
+ "description": so.description,
+ "sales_order_no": so.name,
+ "date": so.transaction_date,
+ "material_request": ','.join(material_requests_against_so.get('material_requests', [])),
+ "customer": so.customer,
+ "territory": so.territory,
+ "so_qty": so.total_qty,
+ "requested_qty": material_requests_against_so.get('qty'),
+ "pending_qty": so.total_qty - flt(material_requests_against_so.get('qty')),
+ "company": so.company
+ }
+ pending_so.append(so_record)
+ else:
+ for item in bundled_item_map.get((so.name, so.item_code)):
+ material_requests_against_so = materials_request_dict.get((so.name, item.item_code)) or {}
+ if flt(item.qty) > flt(material_requests_against_so.get('qty')):
+ so_record = {
+ "item_code": item.item_code,
+ "item_name": item.item_name,
+ "description": item.description,
+ "sales_order_no": so.name,
+ "date": so.transaction_date,
+ "material_request": ','.join(material_requests_against_so.get('material_requests', [])),
+ "customer": so.customer,
+ "territory": so.territory,
+ "so_qty": item.qty,
+ "requested_qty": material_requests_against_so.get('qty', 0),
+ "pending_qty": item.qty - flt(material_requests_against_so.get('qty', 0)),
+ "company": so.company
+ }
+ pending_so.append(so_record)
- # check for pending sales order
- if cint(so.net_qty) > cint(materials_request.get('qty')):
- so_record = {
- "item_code": so.item_code,
- "item_name": so.item_name,
- "description": so.description,
- "sales_order_no": so.name,
- "date": so.transaction_date,
- "material_request": ','.join(materials_request.get('material_requests', [])),
- "customer": so.customer,
- "territory": so.territory,
- "so_qty": so.net_qty,
- "requested_qty": cint(materials_request.get('qty')),
- "pending_qty": so.net_qty - cint(materials_request.get('qty')),
- "company": so.company
- }
- pending_so.append(so_record)
- return pending_so
\ No newline at end of file
+
+ return pending_so
+
+def get_items_with_product_bundle(item_list):
+ bundled_items = frappe.get_all("Product Bundle", filters = [
+ ("new_item_code", "IN", item_list)
+ ], fields = ["new_item_code"])
+
+ return [d.new_item_code for d in bundled_items]
+
+def get_packed_items(sales_order_list):
+ packed_items = frappe.get_all("Packed Item", filters = [
+ ("parent", "IN", sales_order_list)
+ ], fields = ["parent_item", "item_code", "qty", "item_name", "description", "parent"])
+
+ bundled_item_map = frappe._dict()
+ for d in packed_items:
+ bundled_item_map.setdefault((d.parent, d.parent_item), []).append(d)
+
+ return bundled_item_map
diff --git a/erpnext/selling/report/sales_analytics/sales_analytics.py b/erpnext/selling/report/sales_analytics/sales_analytics.py
index 8a5e50a..72767f0 100644
--- a/erpnext/selling/report/sales_analytics/sales_analytics.py
+++ b/erpnext/selling/report/sales_analytics/sales_analytics.py
@@ -40,6 +40,16 @@
"fieldtype": "Data",
"width": 140
})
+
+ if self.filters.tree_type == "Item":
+ self.columns.append({
+ "label": _("UOM"),
+ "fieldname": 'stock_uom',
+ "fieldtype": "Link",
+ "options": "UOM",
+ "width": 100
+ })
+
for end_date in self.periodic_daterange:
period = self.get_period(end_date)
self.columns.append({
@@ -129,7 +139,7 @@
value_field = 'qty'
self.entries = frappe.db.sql("""
- select i.item_code as entity, i.item_name as entity_name, i.{value_field} as value_field, s.{date_field}
+ select i.item_code as entity, i.item_name as entity_name, i.stock_uom, i.{value_field} as value_field, s.{date_field}
from `tab{doctype} Item` i , `tab{doctype}` s
where s.name = i.parent and i.docstatus = 1 and s.company = %s
and s.{date_field} between %s and %s
@@ -198,6 +208,10 @@
total += amount
row["total"] = total
+
+ if self.filters.tree_type == "Item":
+ row["stock_uom"] = period_data.get("stock_uom")
+
self.data.append(row)
def get_rows_by_group(self):
@@ -232,6 +246,9 @@
self.entity_periodic_data.setdefault(d.entity, frappe._dict()).setdefault(period, 0.0)
self.entity_periodic_data[d.entity][period] += flt(d.value_field)
+ if self.filters.tree_type == "Item":
+ self.entity_periodic_data[d.entity]['stock_uom'] = d.stock_uom
+
def get_period(self, posting_date):
if self.filters.range == 'Weekly':
period = "Week " + str(posting_date.isocalendar()[1]) + " " + str(posting_date.year)
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index da29d20..584391e 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -252,7 +252,7 @@
def set_mode_of_payment_account(self):
cash = frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name')
if cash and self.default_cash_account \
- and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': 'Cash'}):
+ and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': cash}):
mode_of_payment = frappe.get_doc('Mode of Payment', cash)
mode_of_payment.append('accounts', {
'company': self.name,
diff --git a/erpnext/setup/doctype/customer_group/customer_group.json b/erpnext/setup/doctype/customer_group/customer_group.json
index c130e79..3565b4b 100644
--- a/erpnext/setup/doctype/customer_group/customer_group.json
+++ b/erpnext/setup/doctype/customer_group/customer_group.json
@@ -1,553 +1,194 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
+ "_comments": "[]",
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:customer_group_name",
- "beta": 0,
"creation": "2013-01-10 16:34:23",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
- "editable_grid": 0,
+ "field_order": [
+ "customer_group_name",
+ "parent_customer_group",
+ "is_group",
+ "cb0",
+ "default_price_list",
+ "payment_terms",
+ "lft",
+ "rgt",
+ "old_parent",
+ "default_receivable_account",
+ "accounts",
+ "credit_limit_section",
+ "credit_limits"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "customer_group_name",
"fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Customer Group Name",
- "length": 0,
"no_copy": 1,
"oldfieldname": "customer_group_name",
"oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
"reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
"unique": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
"bold": 1,
- "collapsible": 0,
- "columns": 0,
- "description": "",
"fieldname": "parent_customer_group",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Parent Customer Group",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "parent_customer_group",
"oldfieldtype": "Link",
- "options": "Customer Group",
- "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
+ "options": "Customer Group"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
"bold": 1,
- "collapsible": 0,
- "columns": 0,
+ "default": "0",
"description": "Only leaf nodes are allowed in transaction",
"fieldname": "is_group",
"fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
"in_list_view": 1,
- "in_standard_filter": 0,
"label": "Is Group",
- "length": 0,
- "no_copy": 0,
"oldfieldname": "is_group",
- "oldfieldtype": "Select",
- "options": "",
- "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
+ "oldfieldtype": "Select"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "cb0",
- "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,
- "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
+ "fieldtype": "Column Break"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "default_price_list",
"fieldtype": "Link",
- "hidden": 0,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "Default Price List",
- "length": 0,
- "no_copy": 0,
- "options": "Price List",
- "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
+ "options": "Price List"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
"fieldname": "payment_terms",
"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": "Default Payment Terms Template",
- "length": 0,
- "no_copy": 0,
- "options": "Payment Terms Template",
- "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
+ "options": "Payment Terms Template"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "credit_limit",
- "fieldtype": "Currency",
- "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": "Credit Limit",
- "length": 0,
- "no_copy": 0,
- "permlevel": 1,
- "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": "lft",
"fieldtype": "Int",
"hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "lft",
- "length": 0,
"no_copy": 1,
"oldfieldname": "lft",
"oldfieldtype": "Int",
- "permlevel": 0,
"print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
"report_hide": 1,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "rgt",
- "length": 0,
"no_copy": 1,
"oldfieldname": "rgt",
"oldfieldtype": "Int",
- "permlevel": 0,
"print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
"report_hide": 1,
- "reqd": 0,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "search_index": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
"fieldname": "old_parent",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
"label": "old_parent",
- "length": 0,
"no_copy": 1,
"oldfieldname": "old_parent",
"oldfieldtype": "Data",
"options": "Customer Group",
- "permlevel": 0,
"print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "report_hide": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "default_receivable_account",
"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": "Default Receivable Account",
- "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
+ "label": "Default Receivable Account"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"depends_on": "eval:!doc.__islocal",
"description": "Mention if non-standard receivable account applicable",
"fieldname": "accounts",
"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": "Accounts",
- "length": 0,
- "no_copy": 0,
- "options": "Party Account",
- "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
+ "options": "Party Account"
+ },
+ {
+ "fieldname": "credit_limit_section",
+ "fieldtype": "Section Break",
+ "label": "Credit Limits"
+ },
+ {
+ "fieldname": "credit_limits",
+ "fieldtype": "Table",
+ "label": "Credit Limit",
+ "options": "Customer Credit Limit"
}
],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
"icon": "fa fa-sitemap",
"idx": 1,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-08-29 06:26:05.935871",
+ "modified": "2019-09-06 12:40:14.954697",
"modified_by": "Administrator",
"module": "Setup",
"name": "Customer Group",
"owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
- "role": "Sales Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Sales Manager"
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
"email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
- "role": "Sales User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Sales User"
},
{
- "amend": 0,
- "cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
- "if_owner": 0,
"import": 1,
- "permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Master Manager",
"set_user_permissions": 1,
"share": 1,
- "submit": 0,
"write": 1
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
"permlevel": 1,
- "print": 0,
"read": 1,
- "report": 0,
"role": "Sales Master Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
"write": 1
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
"permlevel": 1,
- "print": 0,
"read": 1,
- "report": 0,
- "role": "Sales User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Sales User"
},
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
"permlevel": 1,
- "print": 0,
"read": 1,
- "report": 0,
- "role": "Sales Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
+ "role": "Sales Manager"
}
],
"quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
"search_fields": "parent_customer_group",
"show_name_in_global_search": 1,
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/global_defaults/global_defaults.py b/erpnext/setup/doctype/global_defaults/global_defaults.py
index a39e246..fa7bc50 100644
--- a/erpnext/setup/doctype/global_defaults/global_defaults.py
+++ b/erpnext/setup/doctype/global_defaults/global_defaults.py
@@ -58,7 +58,7 @@
# Make property setters to hide rounded total fields
for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note",
- "Supplier Quotation", "Purchase Order"):
+ "Supplier Quotation", "Purchase Order", "Purchase Invoice"):
make_property_setter(doctype, "base_rounded_total", "hidden", self.disable_rounded_total, "Check")
make_property_setter(doctype, "base_rounded_total", "print_hide", 1, "Check")
diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py
index 33ab992..5603f17 100644
--- a/erpnext/setup/doctype/item_group/item_group.py
+++ b/erpnext/setup/doctype/item_group/item_group.py
@@ -4,6 +4,7 @@
from __future__ import unicode_literals
import frappe
import copy
+from frappe import _
from frappe.utils import nowdate, cint, cstr
from frappe.utils.nestedset import NestedSet
from frappe.website.website_generator import WebsiteGenerator
@@ -26,6 +27,11 @@
def validate(self):
super(ItemGroup, self).validate()
+
+ if not self.parent_item_group and not frappe.flags.in_test:
+ if frappe.db.exists("Item Group", _('All Item Groups')):
+ self.parent_item_group = _('All Item Groups')
+
self.make_route()
def on_update(self):
diff --git a/erpnext/setup/doctype/naming_series/naming_series.py b/erpnext/setup/doctype/naming_series/naming_series.py
index cb7ad38..b2cffbb 100644
--- a/erpnext/setup/doctype/naming_series/naming_series.py
+++ b/erpnext/setup/doctype/naming_series/naming_series.py
@@ -151,7 +151,7 @@
def insert_series(self, series):
"""insert series if missing"""
- if not frappe.db.get_value('Series', series, 'name', order_by="name"):
+ if frappe.db.get_value('Series', series, 'name', order_by="name") == None:
frappe.db.sql("insert into tabSeries (name, current) values (%s, 0)", (series))
def update_series_start(self):
diff --git a/erpnext/setup/setup_wizard/data/dashboard_charts.py b/erpnext/setup/setup_wizard/data/dashboard_charts.py
new file mode 100644
index 0000000..bb8c131
--- /dev/null
+++ b/erpnext/setup/setup_wizard/data/dashboard_charts.py
@@ -0,0 +1,117 @@
+from __future__ import unicode_literals
+from frappe import _
+import frappe
+import json
+
+def get_company_for_dashboards():
+ company = frappe.defaults.get_defaults().company
+ if company:
+ return company
+ else:
+ company_list = frappe.get_list("Company")
+ if company_list:
+ return company_list[0].name
+ return None
+
+def get_default_dashboards():
+ company = frappe.get_doc("Company", get_company_for_dashboards())
+ income_account = company.default_income_account or get_account("Income Account", company.name)
+ expense_account = company.default_expense_account or get_account("Expense Account", company.name)
+ bank_account = company.default_bank_account or get_account("Bank", company.name)
+
+ return {
+ "Dashboards": [
+ {
+ "doctype": "Dashboard",
+ "dashboard_name": "Accounts",
+ "charts": [
+ { "chart": "Outgoing Bills (Sales Invoice)" },
+ { "chart": "Incoming Bills (Purchase Invoice)" },
+ { "chart": "Bank Balance" },
+ { "chart": "Income" },
+ { "chart": "Expenses" }
+ ]
+ }
+ ],
+ "Charts": [
+ {
+ "doctype": "Dashboard Chart",
+ "time_interval": "Quarterly",
+ "chart_name": "Income",
+ "timespan": "Last Year",
+ "color": None,
+ "filters_json": json.dumps({"company": company.name, "account": income_account}),
+ "source": "Account Balance Timeline",
+ "chart_type": "Custom",
+ "timeseries": 1,
+ "owner": "Administrator",
+ "type": "Line",
+ "width": "Half"
+ },
+ {
+ "doctype": "Dashboard Chart",
+ "time_interval": "Quarterly",
+ "chart_name": "Expenses",
+ "timespan": "Last Year",
+ "color": None,
+ "filters_json": json.dumps({"company": company.name, "account": expense_account}),
+ "source": "Account Balance Timeline",
+ "chart_type": "Custom",
+ "timeseries": 1,
+ "owner": "Administrator",
+ "type": "Line",
+ "width": "Half"
+ },
+ {
+ "doctype": "Dashboard Chart",
+ "time_interval": "Quarterly",
+ "chart_name": "Bank Balance",
+ "timespan": "Last Year",
+ "color": "#ffb868",
+ "filters_json": json.dumps({"company": company.name, "account": bank_account}),
+ "source": "Account Balance Timeline",
+ "chart_type": "Custom",
+ "timeseries": 1,
+ "owner": "Administrator",
+ "type": "Line",
+ "width": "Half"
+ },
+ {
+ "doctype": "Dashboard Chart",
+ "time_interval": "Monthly",
+ "chart_name": "Incoming Bills (Purchase Invoice)",
+ "timespan": "Last Year",
+ "color": "#a83333",
+ "value_based_on": "base_grand_total",
+ "filters_json": json.dumps({}),
+ "chart_type": "Sum",
+ "timeseries": 1,
+ "based_on": "posting_date",
+ "owner": "Administrator",
+ "document_type": "Purchase Invoice",
+ "type": "Bar",
+ "width": "Half"
+ },
+ {
+ "doctype": "Dashboard Chart",
+ "time_interval": "Monthly",
+ "chart_name": "Outgoing Bills (Sales Invoice)",
+ "timespan": "Last Year",
+ "color": "#7b933d",
+ "value_based_on": "base_grand_total",
+ "filters_json": json.dumps({}),
+ "chart_type": "Sum",
+ "timeseries": 1,
+ "based_on": "posting_date",
+ "owner": "Administrator",
+ "document_type": "Sales Invoice",
+ "type": "Bar",
+ "width": "Half"
+ }
+ ]
+ }
+
+def get_account(account_type, company):
+ accounts = frappe.get_list("Account", filters={"account_type": account_type, "company": company})
+ if accounts:
+ return accounts[0].name
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index 4b734df..b657165 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -475,13 +475,14 @@
frappe.db.set_value("Company", args.company_name, "default_bank_account", bank_account.name, update_modified=False)
- return doc
except RootNotEditable:
frappe.throw(_("Bank account cannot be named as {0}").format(args.bank_account))
except frappe.DuplicateEntryError:
# bank account same as a CoA entry
pass
+ add_dashboards()
+
# Now, with fixtures out of the way, onto concrete stuff
records = [
@@ -499,6 +500,27 @@
make_records(records)
+def add_dashboards():
+ from erpnext.setup.setup_wizard.data.dashboard_charts import get_company_for_dashboards
+
+ if not get_company_for_dashboards():
+ return
+
+ from erpnext.setup.setup_wizard.data.dashboard_charts import get_default_dashboards
+ from frappe.modules.import_file import import_file_by_path
+
+ dashboard_data = get_default_dashboards()
+
+ # create account balance timeline before creating dashbaord charts
+ doctype = "dashboard_chart_source"
+ docname = "account_balance_timeline"
+ folder = os.path.dirname(frappe.get_module("erpnext.accounts").__file__)
+ doc_path = os.path.join(folder, doctype, docname, docname) + ".json"
+ import_file_by_path(doc_path, force=0, for_sync=True)
+
+ make_records(dashboard_data["Charts"])
+ make_records(dashboard_data["Dashboards"])
+
def get_fy_details(fy_start_date, fy_end_date):
start_year = getdate(fy_start_date).year
diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py
index 0922f3d..db2c327 100644
--- a/erpnext/shopping_cart/cart.py
+++ b/erpnext/shopping_cart/cart.py
@@ -336,19 +336,20 @@
def _set_price_list(quotation, cart_settings):
"""Set price list based on customer or shopping cart default"""
- if quotation.selling_price_list:
- return
+ from erpnext.accounts.party import get_default_price_list
# check if customer price list exists
selling_price_list = None
if quotation.party_name:
- from erpnext.accounts.party import get_default_price_list
- selling_price_list = get_default_price_list(frappe.get_doc("Customer", quotation.party_name))
+ selling_price_list = frappe.db.get_value('Customer', quotation.party_name, 'default_price_list')
# else check for territory based price list
if not selling_price_list:
selling_price_list = cart_settings.price_list
+ if not selling_price_list and quotation.party_name:
+ selling_price_list = get_default_price_list(frappe.get_doc("Customer", quotation.party_name))
+
quotation.selling_price_list = selling_price_list
def set_taxes(quotation, cart_settings):
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json
index b5f2c34..1116273 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.json
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.json
@@ -1,4514 +1,1308 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 0,
- "creation": "2013-05-24 19:29:09",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 0,
+ "allow_import": 1,
+ "autoname": "naming_series:",
+ "creation": "2013-05-24 19:29:09",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "field_order": [
+ "delivery_to_section",
+ "column_break0",
+ "title",
+ "naming_series",
+ "customer",
+ "customer_name",
+ "column_break1",
+ "amended_from",
+ "company",
+ "posting_date",
+ "posting_time",
+ "set_posting_time",
+ "is_return",
+ "issue_credit_note",
+ "return_against",
+ "customer_po_details",
+ "po_no",
+ "section_break_18",
+ "pick_list",
+ "column_break_17",
+ "po_date",
+ "contact_info",
+ "shipping_address_name",
+ "shipping_address",
+ "contact_person",
+ "contact_display",
+ "contact_mobile",
+ "contact_email",
+ "col_break21",
+ "customer_address",
+ "tax_id",
+ "address_display",
+ "company_address",
+ "company_address_display",
+ "currency_and_price_list",
+ "currency",
+ "conversion_rate",
+ "col_break23",
+ "selling_price_list",
+ "price_list_currency",
+ "plc_conversion_rate",
+ "ignore_pricing_rule",
+ "sec_warehouse",
+ "set_warehouse",
+ "col_break_warehouse",
+ "to_warehouse",
+ "items_section",
+ "scan_barcode",
+ "items",
+ "pricing_rule_details",
+ "pricing_rules",
+ "packing_list",
+ "packed_items",
+ "product_bundle_help",
+ "section_break_31",
+ "total_qty",
+ "base_total",
+ "base_net_total",
+ "column_break_33",
+ "total",
+ "net_total",
+ "total_net_weight",
+ "taxes_section",
+ "tax_category",
+ "column_break_39",
+ "shipping_rule",
+ "section_break_41",
+ "taxes_and_charges",
+ "taxes",
+ "sec_tax_breakup",
+ "other_charges_calculation",
+ "section_break_44",
+ "base_total_taxes_and_charges",
+ "column_break_47",
+ "total_taxes_and_charges",
+ "section_break_49",
+ "apply_discount_on",
+ "base_discount_amount",
+ "column_break_51",
+ "additional_discount_percentage",
+ "discount_amount",
+ "totals",
+ "base_grand_total",
+ "base_rounding_adjustment",
+ "base_rounded_total",
+ "base_in_words",
+ "column_break3",
+ "grand_total",
+ "rounding_adjustment",
+ "rounded_total",
+ "in_words",
+ "terms_section_break",
+ "tc_name",
+ "terms",
+ "transporter_info",
+ "transporter",
+ "driver",
+ "lr_no",
+ "vehicle_no",
+ "col_break34",
+ "transporter_name",
+ "driver_name",
+ "lr_date",
+ "more_info",
+ "project",
+ "campaign",
+ "source",
+ "column_break5",
+ "per_billed",
+ "customer_group",
+ "territory",
+ "printing_details",
+ "letter_head",
+ "select_print_heading",
+ "language",
+ "column_break_88",
+ "print_without_amount",
+ "group_same_items",
+ "section_break_83",
+ "status",
+ "per_installed",
+ "installation_status",
+ "column_break_89",
+ "excise_page",
+ "instructions",
+ "subscription_section",
+ "auto_repeat",
+ "sales_team_section_break",
+ "sales_partner",
+ "column_break7",
+ "commission_rate",
+ "total_commission",
+ "section_break1",
+ "sales_team"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "delivery_to_section",
- "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": "Delivery To",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-user",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "delivery_to_section",
+ "fieldtype": "Section Break",
+ "label": "Delivery To",
+ "options": "fa fa-user"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break0",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Column Break",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "print_width": "50%",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "column_break0",
+ "fieldtype": "Column Break",
+ "oldfieldtype": "Column Break",
+ "print_width": "50%",
"width": "50%"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "{customer_name}",
- "fieldname": "title",
- "fieldtype": "Data",
- "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": "Title",
- "length": 0,
- "no_copy": 1,
- "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_on_submit": 1,
+ "default": "{customer_name}",
+ "fieldname": "title",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Title",
+ "no_copy": 1,
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "naming_series",
- "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",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "naming_series",
- "oldfieldtype": "Select",
- "options": "MAT-DN-.YYYY.-",
- "permlevel": 0,
- "print_hide": 1,
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "no_copy": 1,
+ "oldfieldname": "naming_series",
+ "oldfieldtype": "Select",
+ "options": "MAT-DN-.YYYY.-",
+ "print_hide": 1,
+ "reqd": 1,
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "customer",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 1,
- "label": "Customer",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "customer",
- "oldfieldtype": "Link",
- "options": "Customer",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "customer",
+ "fieldtype": "Link",
+ "in_global_search": 1,
+ "in_standard_filter": 1,
+ "label": "Customer",
+ "oldfieldname": "customer",
+ "oldfieldtype": "Link",
+ "options": "Customer",
+ "print_hide": 1,
+ "reqd": 1,
+ "search_index": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "customer",
- "fetch_from": "customer.customer_name",
- "fieldname": "customer_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Customer Name",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
- },
+ "bold": 1,
+ "depends_on": "customer",
+ "fetch_from": "customer.customer_name",
+ "fieldname": "customer_name",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "label": "Customer Name",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break1",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Column Break",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break1",
+ "fieldtype": "Column Break",
+ "oldfieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amended_from",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Amended From",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "amended_from",
- "oldfieldtype": "Data",
- "options": "Delivery Note",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "150px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Amended From",
+ "no_copy": 1,
+ "oldfieldname": "amended_from",
+ "oldfieldtype": "Data",
+ "options": "Delivery Note",
+ "print_hide": 1,
+ "print_width": "150px",
+ "read_only": 1,
"width": "150px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
- "fieldname": "company",
- "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,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "company",
- "oldfieldtype": "Link",
- "options": "Company",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "150px",
- "read_only": 0,
- "remember_last_selected_value": 1,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "in_standard_filter": 1,
+ "label": "Company",
+ "oldfieldname": "company",
+ "oldfieldtype": "Link",
+ "options": "Company",
+ "print_hide": 1,
+ "print_width": "150px",
+ "remember_last_selected_value": 1,
+ "reqd": 1,
"width": "150px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Today",
- "depends_on": "",
- "fieldname": "posting_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": "Date",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "posting_date",
- "oldfieldtype": "Date",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "print_width": "100px",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "default": "Today",
+ "fieldname": "posting_date",
+ "fieldtype": "Date",
+ "label": "Date",
+ "no_copy": 1,
+ "oldfieldname": "posting_date",
+ "oldfieldtype": "Date",
+ "print_width": "100px",
+ "reqd": 1,
+ "search_index": 1,
"width": "100px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "description": "",
- "fieldname": "posting_time",
- "fieldtype": "Time",
- "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": "Posting Time",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "posting_time",
- "oldfieldtype": "Time",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "100px",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "posting_time",
+ "fieldtype": "Time",
+ "label": "Posting Time",
+ "oldfieldname": "posting_time",
+ "oldfieldtype": "Time",
+ "print_hide": 1,
+ "print_width": "100px",
+ "reqd": 1,
"width": "100px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.docstatus==0",
- "fieldname": "set_posting_time",
- "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": "Edit Posting Date and Time",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "depends_on": "eval:doc.docstatus==0",
+ "fieldname": "set_posting_time",
+ "fieldtype": "Check",
+ "label": "Edit Posting Date and Time",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "is_return",
- "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": "Is Return",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "default": "0",
+ "fieldname": "is_return",
+ "fieldtype": "Check",
+ "label": "Is Return",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "is_return",
- "fieldname": "issue_credit_note",
- "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": "Issue Credit Note",
- "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
- },
+ "default": "0",
+ "depends_on": "is_return",
+ "fieldname": "issue_credit_note",
+ "fieldtype": "Check",
+ "label": "Issue Credit Note"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "is_return",
- "fieldname": "return_against",
- "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": "Return Against Delivery Note",
- "length": 0,
- "no_copy": 1,
- "options": "Delivery Note",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "depends_on": "is_return",
+ "fieldname": "return_against",
+ "fieldtype": "Link",
+ "label": "Return Against Delivery Note",
+ "no_copy": 1,
+ "options": "Delivery Note",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "collapsible_depends_on": "po_no",
- "columns": 0,
- "fieldname": "customer_po_details",
- "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": "Customer PO Details",
- "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
- },
+ "collapsible": 1,
+ "collapsible_depends_on": "po_no",
+ "fieldname": "customer_po_details",
+ "fieldtype": "Section Break",
+ "label": "Customer PO Details"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "po_no",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Customer's Purchase Order No",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "po_no",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "100px",
- "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_on_submit": 1,
+ "fieldname": "po_no",
+ "fieldtype": "Data",
+ "label": "Customer's Purchase Order No",
+ "no_copy": 1,
+ "oldfieldname": "po_no",
+ "oldfieldtype": "Data",
+ "print_hide": 1,
+ "print_width": "100px",
"width": "100px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_17",
- "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
- },
+ "fieldname": "column_break_17",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.po_no",
- "fieldname": "po_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": "Customer's Purchase Order Date",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "po_date",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "100px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "depends_on": "eval:doc.po_no",
+ "fieldname": "po_date",
+ "fieldtype": "Date",
+ "label": "Customer's Purchase Order Date",
+ "oldfieldname": "po_date",
+ "oldfieldtype": "Data",
+ "print_hide": 1,
+ "print_width": "100px",
+ "read_only": 1,
"width": "100px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "depends_on": "customer",
- "fieldname": "contact_info",
- "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": "Address and Contact",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-bullhorn",
- "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
- },
+ "collapsible": 1,
+ "depends_on": "customer",
+ "fieldname": "contact_info",
+ "fieldtype": "Section Break",
+ "label": "Address and Contact",
+ "options": "fa fa-bullhorn"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "shipping_address_name",
- "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": "Shipping Address",
- "length": 0,
- "no_copy": 0,
- "options": "Address",
- "permlevel": 0,
- "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
- },
+ "fieldname": "shipping_address_name",
+ "fieldtype": "Link",
+ "label": "Shipping Address",
+ "options": "Address",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "shipping_address",
- "fieldtype": "Small Text",
- "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": "Shipping Address",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "shipping_address",
+ "fieldtype": "Small Text",
+ "label": "Shipping Address",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "contact_person",
- "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": "Contact Person",
- "length": 0,
- "no_copy": 0,
- "options": "Contact",
- "permlevel": 0,
- "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
- },
+ "fieldname": "contact_person",
+ "fieldtype": "Link",
+ "label": "Contact Person",
+ "options": "Contact",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "contact_display",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Contact",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "contact_display",
+ "fieldtype": "Small Text",
+ "in_global_search": 1,
+ "label": "Contact",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "contact_mobile",
- "fieldtype": "Small Text",
- "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": "Mobile No",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "contact_mobile",
+ "fieldtype": "Small Text",
+ "hidden": 1,
+ "label": "Mobile No",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "contact_email",
- "fieldtype": "Data",
- "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": "Contact Email",
- "length": 0,
- "no_copy": 0,
- "options": "Email",
- "permlevel": 0,
- "print_hide": 1,
- "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
- },
+ "fieldname": "contact_email",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Contact Email",
+ "options": "Email",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "col_break21",
- "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,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "print_width": "50%",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "col_break21",
+ "fieldtype": "Column Break",
+ "print_width": "50%",
"width": "50%"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "customer",
- "fieldname": "customer_address",
- "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": "Billing Address Name",
- "length": 0,
- "no_copy": 0,
- "options": "Address",
- "permlevel": 0,
- "print_hide": 1,
- "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
- },
+ "depends_on": "customer",
+ "fieldname": "customer_address",
+ "fieldtype": "Link",
+ "label": "Billing Address Name",
+ "options": "Address",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "tax_id",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Tax Id",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "tax_id",
+ "fieldtype": "Data",
+ "label": "Tax Id",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "address_display",
- "fieldtype": "Small Text",
- "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": "Billing Address",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "address_display",
+ "fieldtype": "Small Text",
+ "label": "Billing Address",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company_address",
- "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 Address Name",
- "length": 0,
- "no_copy": 0,
- "options": "Address",
- "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
- },
+ "fieldname": "company_address",
+ "fieldtype": "Link",
+ "label": "Company Address Name",
+ "options": "Address"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company_address_display",
- "fieldtype": "Small Text",
- "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 Address",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "company_address_display",
+ "fieldtype": "Small Text",
+ "label": "Company Address"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "currency_and_price_list",
- "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": "Currency and Price List",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-tag",
- "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
- },
+ "collapsible": 1,
+ "fieldname": "currency_and_price_list",
+ "fieldtype": "Section Break",
+ "label": "Currency and Price List",
+ "options": "fa fa-tag"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "currency",
- "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": "Currency",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "currency",
- "oldfieldtype": "Select",
- "options": "Currency",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "currency",
+ "fieldtype": "Link",
+ "label": "Currency",
+ "oldfieldname": "currency",
+ "oldfieldtype": "Select",
+ "options": "Currency",
+ "print_hide": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Rate at which customer's currency is converted to company's base currency",
- "fieldname": "conversion_rate",
- "fieldtype": "Float",
- "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": "Exchange Rate",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "conversion_rate",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "precision": "9",
- "print_hide": 1,
- "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
- },
+ "description": "Rate at which customer's currency is converted to company's base currency",
+ "fieldname": "conversion_rate",
+ "fieldtype": "Float",
+ "label": "Exchange Rate",
+ "oldfieldname": "conversion_rate",
+ "oldfieldtype": "Currency",
+ "precision": "9",
+ "print_hide": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "col_break23",
- "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,
- "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
- },
+ "fieldname": "col_break23",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "selling_price_list",
- "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": "Price List",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "price_list_name",
- "oldfieldtype": "Select",
- "options": "Price List",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "selling_price_list",
+ "fieldtype": "Link",
+ "label": "Price List",
+ "oldfieldname": "price_list_name",
+ "oldfieldtype": "Select",
+ "options": "Price List",
+ "print_hide": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "price_list_currency",
- "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": "Price List Currency",
- "length": 0,
- "no_copy": 0,
- "options": "Currency",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "price_list_currency",
+ "fieldtype": "Link",
+ "label": "Price List Currency",
+ "options": "Currency",
+ "print_hide": 1,
+ "read_only": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Rate at which Price list currency is converted to company's base currency",
- "fieldname": "plc_conversion_rate",
- "fieldtype": "Float",
- "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": "Price List Exchange Rate",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "9",
- "print_hide": 1,
- "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
- },
+ "description": "Rate at which Price list currency is converted to company's base currency",
+ "fieldname": "plc_conversion_rate",
+ "fieldtype": "Float",
+ "label": "Price List Exchange Rate",
+ "precision": "9",
+ "print_hide": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "ignore_pricing_rule",
- "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": "Ignore Pricing Rule",
- "length": 0,
- "no_copy": 1,
- "permlevel": 1,
- "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
- },
+ "default": "0",
+ "fieldname": "ignore_pricing_rule",
+ "fieldtype": "Check",
+ "label": "Ignore Pricing Rule",
+ "no_copy": 1,
+ "permlevel": 1,
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sec_warehouse",
- "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
- },
+ "fieldname": "sec_warehouse",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "set_warehouse",
- "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": "Set Source Warehouse",
- "length": 0,
- "no_copy": 0,
- "options": "Warehouse",
- "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
- },
+ "fieldname": "set_warehouse",
+ "fieldtype": "Link",
+ "label": "Set Source Warehouse",
+ "options": "Warehouse",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "col_break_warehouse",
- "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
- },
+ "fieldname": "col_break_warehouse",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Required only for sample item.",
- "fieldname": "to_warehouse",
- "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,
- "label": "To Warehouse",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "to_warehouse",
- "oldfieldtype": "Link",
- "options": "Warehouse",
- "permlevel": 0,
- "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
- },
+ "description": "Required only for sample item.",
+ "fieldname": "to_warehouse",
+ "fieldtype": "Link",
+ "in_standard_filter": 1,
+ "label": "To Warehouse",
+ "no_copy": 1,
+ "oldfieldname": "to_warehouse",
+ "oldfieldtype": "Link",
+ "options": "Warehouse",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "items_section",
- "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,
- "oldfieldtype": "Section Break",
- "options": "fa fa-shopping-cart",
- "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
- },
+ "fieldname": "items_section",
+ "fieldtype": "Section Break",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-shopping-cart"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "scan_barcode",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Scan Barcode",
- "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
- },
+ "fieldname": "scan_barcode",
+ "fieldtype": "Data",
+ "label": "Scan Barcode"
+ },
{
- "allow_bulk_edit": 1,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "items",
- "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": "Items",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "delivery_note_details",
- "oldfieldtype": "Table",
- "options": "Delivery Note Item",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_bulk_edit": 1,
+ "fieldname": "items",
+ "fieldtype": "Table",
+ "label": "Items",
+ "oldfieldname": "delivery_note_details",
+ "oldfieldtype": "Table",
+ "options": "Delivery Note Item",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "collapsible_depends_on": "",
- "columns": 0,
- "fieldname": "pricing_rule_details",
- "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": "Pricing Rules",
- "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
- },
+ "fieldname": "pricing_rule_details",
+ "fieldtype": "Section Break",
+ "label": "Pricing Rules"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "collapsible_depends_on": "",
- "columns": 0,
- "fieldname": "pricing_rules",
- "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": "Pricing Rule Detail",
- "length": 0,
- "no_copy": 0,
- "options": "Pricing Rule Detail",
- "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
- },
+ "fieldname": "pricing_rules",
+ "fieldtype": "Table",
+ "label": "Pricing Rule Detail",
+ "options": "Pricing Rule Detail",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "collapsible_depends_on": "packed_items",
- "columns": 0,
- "fieldname": "packing_list",
- "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": "Packing List",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "options": "fa fa-suitcase",
- "permlevel": 0,
- "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
- },
+ "collapsible": 1,
+ "collapsible_depends_on": "packed_items",
+ "fieldname": "packing_list",
+ "fieldtype": "Section Break",
+ "label": "Packing List",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-suitcase",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "packed_items",
- "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": "Packed Items",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "packing_details",
- "oldfieldtype": "Table",
- "options": "Packed Item",
- "permlevel": 0,
- "print_hide": 1,
- "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
- },
+ "fieldname": "packed_items",
+ "fieldtype": "Table",
+ "label": "Packed Items",
+ "oldfieldname": "packing_details",
+ "oldfieldtype": "Table",
+ "options": "Packed Item",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "product_bundle_help",
- "fieldtype": "HTML",
- "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": "Product Bundle Help",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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
- },
+ "fieldname": "product_bundle_help",
+ "fieldtype": "HTML",
+ "label": "Product Bundle Help",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_31",
- "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
- },
+ "fieldname": "section_break_31",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "total_qty",
- "fieldtype": "Float",
- "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": "Total Quantity",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "total_qty",
+ "fieldtype": "Float",
+ "label": "Total Quantity",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "base_total",
- "fieldtype": "Currency",
- "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": "Total (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fieldname": "base_total",
+ "fieldtype": "Currency",
+ "label": "Total (Company Currency)",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "base_net_total",
- "fieldtype": "Currency",
- "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": "Net Total (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "net_total",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "150px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "base_net_total",
+ "fieldtype": "Currency",
+ "label": "Net Total (Company Currency)",
+ "oldfieldname": "net_total",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "print_width": "150px",
+ "read_only": 1,
"width": "150px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "column_break_33",
- "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,
- "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
- },
+ "fieldname": "column_break_33",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "total",
- "fieldtype": "Currency",
- "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": "Total",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "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
- },
+ "fieldname": "total",
+ "fieldtype": "Currency",
+ "label": "Total",
+ "options": "currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "net_total",
- "fieldtype": "Currency",
- "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": "Net Total",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "print_hide": 1,
- "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
- },
+ "fieldname": "net_total",
+ "fieldtype": "Currency",
+ "label": "Net Total",
+ "options": "currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "total_net_weight",
- "fieldtype": "Float",
- "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": "Total Net Weight",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fieldname": "total_net_weight",
+ "fieldtype": "Float",
+ "label": "Total Net Weight",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "taxes_section",
- "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": "Taxes and Charges",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "options": "fa fa-money",
- "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
- },
+ "fieldname": "taxes_section",
+ "fieldtype": "Section Break",
+ "label": "Taxes and Charges",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-money"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "tax_category",
- "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": "Tax Category",
- "length": 0,
- "no_copy": 0,
- "options": "Tax Category",
- "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
- },
+ "fieldname": "tax_category",
+ "fieldtype": "Link",
+ "label": "Tax Category",
+ "options": "Tax Category",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_39",
- "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,
- "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
- },
+ "fieldname": "column_break_39",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "shipping_rule",
- "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": "Shipping Rule",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Button",
- "options": "Shipping Rule",
- "permlevel": 0,
- "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
- },
+ "fieldname": "shipping_rule",
+ "fieldtype": "Link",
+ "label": "Shipping Rule",
+ "oldfieldtype": "Button",
+ "options": "Shipping Rule",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_41",
- "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
- },
+ "fieldname": "section_break_41",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "If you have created a standard template in Sales Taxes and Charges Template, select one and click on the button below.",
- "fieldname": "taxes_and_charges",
- "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": "Sales Taxes and Charges Template",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "charge",
- "oldfieldtype": "Link",
- "options": "Sales Taxes and Charges Template",
- "permlevel": 0,
- "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
- },
+ "description": "If you have created a standard template in Sales Taxes and Charges Template, select one and click on the button below.",
+ "fieldname": "taxes_and_charges",
+ "fieldtype": "Link",
+ "label": "Sales Taxes and Charges Template",
+ "oldfieldname": "charge",
+ "oldfieldtype": "Link",
+ "options": "Sales Taxes and Charges Template",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "taxes",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Sales Taxes and Charges",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "other_charges",
- "oldfieldtype": "Table",
- "options": "Sales Taxes and Charges",
- "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
- },
+ "fieldname": "taxes",
+ "fieldtype": "Table",
+ "label": "Sales Taxes and Charges",
+ "oldfieldname": "other_charges",
+ "oldfieldtype": "Table",
+ "options": "Sales Taxes and Charges"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "sec_tax_breakup",
- "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": "Tax Breakup",
- "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
- },
+ "collapsible": 1,
+ "fieldname": "sec_tax_breakup",
+ "fieldtype": "Section Break",
+ "label": "Tax Breakup"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "other_charges_calculation",
- "fieldtype": "Text",
- "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": "Taxes and Charges Calculation",
- "length": 0,
- "no_copy": 1,
- "oldfieldtype": "HTML",
- "permlevel": 0,
- "print_hide": 1,
- "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
- },
+ "fieldname": "other_charges_calculation",
+ "fieldtype": "Text",
+ "label": "Taxes and Charges Calculation",
+ "no_copy": 1,
+ "oldfieldtype": "HTML",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_44",
- "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
- },
+ "fieldname": "section_break_44",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "base_total_taxes_and_charges",
- "fieldtype": "Currency",
- "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": "Total Taxes and Charges (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "other_charges_total",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "150px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "base_total_taxes_and_charges",
+ "fieldtype": "Currency",
+ "label": "Total Taxes and Charges (Company Currency)",
+ "oldfieldname": "other_charges_total",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "print_width": "150px",
+ "read_only": 1,
"width": "150px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_47",
- "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
- },
+ "fieldname": "column_break_47",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "total_taxes_and_charges",
- "fieldtype": "Currency",
- "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": "Total Taxes and Charges",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "print_hide": 1,
- "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
- },
+ "fieldname": "total_taxes_and_charges",
+ "fieldtype": "Currency",
+ "label": "Total Taxes and Charges",
+ "options": "currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "collapsible_depends_on": "discount_amount",
- "columns": 0,
- "fieldname": "section_break_49",
- "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": "Additional Discount",
- "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
- },
+ "collapsible": 1,
+ "collapsible_depends_on": "discount_amount",
+ "fieldname": "section_break_49",
+ "fieldtype": "Section Break",
+ "label": "Additional Discount"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Grand Total",
- "fieldname": "apply_discount_on",
- "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": "Apply Additional Discount On",
- "length": 0,
- "no_copy": 0,
- "options": "\nGrand Total\nNet Total",
- "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
- },
+ "default": "Grand Total",
+ "fieldname": "apply_discount_on",
+ "fieldtype": "Select",
+ "label": "Apply Additional Discount On",
+ "options": "\nGrand Total\nNet Total",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "base_discount_amount",
- "fieldtype": "Currency",
- "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": "Additional Discount Amount (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fieldname": "base_discount_amount",
+ "fieldtype": "Currency",
+ "label": "Additional Discount Amount (Company Currency)",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_51",
- "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,
- "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
- },
+ "fieldname": "column_break_51",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "additional_discount_percentage",
- "fieldtype": "Float",
- "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": "Additional Discount Percentage",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "additional_discount_percentage",
+ "fieldtype": "Float",
+ "label": "Additional Discount Percentage",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "discount_amount",
- "fieldtype": "Currency",
- "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": "Additional Discount Amount",
- "length": 0,
- "no_copy": 0,
- "options": "currency",
- "permlevel": 0,
- "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
- },
+ "fieldname": "discount_amount",
+ "fieldtype": "Currency",
+ "label": "Additional Discount Amount",
+ "options": "currency",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "totals",
- "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,
- "oldfieldtype": "Section Break",
- "options": "fa fa-money",
- "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
- },
+ "fieldname": "totals",
+ "fieldtype": "Section Break",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-money"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "base_grand_total",
- "fieldtype": "Currency",
- "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": "Grand Total (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "grand_total",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "150px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "base_grand_total",
+ "fieldtype": "Currency",
+ "label": "Grand Total (Company Currency)",
+ "oldfieldname": "grand_total",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "print_width": "150px",
+ "read_only": 1,
"width": "150px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "base_rounding_adjustment",
- "fieldtype": "Currency",
- "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": "Rounding Adjustment (Company Currency)",
- "length": 0,
- "no_copy": 1,
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fieldname": "base_rounding_adjustment",
+ "fieldtype": "Currency",
+ "label": "Rounding Adjustment (Company Currency)",
+ "no_copy": 1,
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "base_rounded_total",
- "fieldtype": "Currency",
- "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": "Rounded Total (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "rounded_total",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "150px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "base_rounded_total",
+ "fieldtype": "Currency",
+ "label": "Rounded Total (Company Currency)",
+ "oldfieldname": "rounded_total",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "print_hide": 1,
+ "print_width": "150px",
+ "read_only": 1,
"width": "150px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "In Words will be visible once you save the Delivery Note.",
- "fieldname": "base_in_words",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "In Words (Company Currency)",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "in_words",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "200px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "description": "In Words will be visible once you save the Delivery Note.",
+ "fieldname": "base_in_words",
+ "fieldtype": "Data",
+ "label": "In Words (Company Currency)",
+ "oldfieldname": "in_words",
+ "oldfieldtype": "Data",
+ "print_hide": 1,
+ "print_width": "200px",
+ "read_only": 1,
"width": "200px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break3",
- "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",
- "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
- },
+ "fieldname": "column_break3",
+ "fieldtype": "Column Break",
+ "oldfieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "grand_total",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Grand Total",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "grand_total_export",
- "oldfieldtype": "Currency",
- "options": "currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "print_width": "150px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "grand_total",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Grand Total",
+ "oldfieldname": "grand_total_export",
+ "oldfieldtype": "Currency",
+ "options": "currency",
+ "print_width": "150px",
+ "read_only": 1,
"width": "150px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "rounding_adjustment",
- "fieldtype": "Currency",
- "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": "Rounding Adjustment",
- "length": 0,
- "no_copy": 1,
- "options": "currency",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fieldname": "rounding_adjustment",
+ "fieldtype": "Currency",
+ "label": "Rounding Adjustment",
+ "no_copy": 1,
+ "options": "currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 1,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "rounded_total",
- "fieldtype": "Currency",
- "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": "Rounded Total",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "rounded_total_export",
- "oldfieldtype": "Currency",
- "options": "currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "print_width": "150px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "bold": 1,
+ "fieldname": "rounded_total",
+ "fieldtype": "Currency",
+ "label": "Rounded Total",
+ "oldfieldname": "rounded_total_export",
+ "oldfieldtype": "Currency",
+ "options": "currency",
+ "print_width": "150px",
+ "read_only": 1,
"width": "150px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "In Words (Export) will be visible once you save the Delivery Note.",
- "fieldname": "in_words",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "In Words",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "in_words_export",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "150px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "description": "In Words (Export) will be visible once you save the Delivery Note.",
+ "fieldname": "in_words",
+ "fieldtype": "Data",
+ "label": "In Words",
+ "oldfieldname": "in_words_export",
+ "oldfieldtype": "Data",
+ "print_hide": 1,
+ "print_width": "150px",
+ "read_only": 1,
"width": "150px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "collapsible_depends_on": "terms",
- "columns": 0,
- "fieldname": "terms_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": "Terms and Conditions",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "options": "fa fa-legal",
- "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
- },
+ "collapsible": 1,
+ "collapsible_depends_on": "terms",
+ "fieldname": "terms_section_break",
+ "fieldtype": "Section Break",
+ "label": "Terms and Conditions",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-legal"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "tc_name",
- "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": "Terms",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "tc_name",
- "oldfieldtype": "Link",
- "options": "Terms and Conditions",
- "permlevel": 0,
- "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
- },
+ "fieldname": "tc_name",
+ "fieldtype": "Link",
+ "label": "Terms",
+ "oldfieldname": "tc_name",
+ "oldfieldtype": "Link",
+ "options": "Terms and Conditions",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "terms",
- "fieldtype": "Text Editor",
- "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": "Terms and Conditions Details",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "terms",
- "oldfieldtype": "Text Editor",
- "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
- },
+ "fieldname": "terms",
+ "fieldtype": "Text Editor",
+ "label": "Terms and Conditions Details",
+ "oldfieldname": "terms",
+ "oldfieldtype": "Text Editor"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "collapsible_depends_on": "transporter",
- "columns": 0,
- "fieldname": "transporter_info",
- "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": "Transporter Info",
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-truck",
- "permlevel": 0,
- "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
- },
+ "collapsible": 1,
+ "collapsible_depends_on": "transporter",
+ "fieldname": "transporter_info",
+ "fieldtype": "Section Break",
+ "label": "Transporter Info",
+ "options": "fa fa-truck",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "transporter",
- "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": "Transporter",
- "length": 0,
- "no_copy": 0,
- "options": "Supplier",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "150px",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "transporter",
+ "fieldtype": "Link",
+ "label": "Transporter",
+ "options": "Supplier",
+ "print_hide": 1,
+ "print_width": "150px",
"width": "150px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "driver",
- "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": "Driver",
- "length": 0,
- "no_copy": 0,
- "options": "Driver",
- "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
- },
+ "fieldname": "driver",
+ "fieldtype": "Link",
+ "label": "Driver",
+ "options": "Driver",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
- "fieldname": "lr_no",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Transport Receipt No",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "lr_no",
- "oldfieldtype": "Data",
- "options": "",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "100px",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "lr_no",
+ "fieldtype": "Data",
+ "label": "Transport Receipt No",
+ "oldfieldname": "lr_no",
+ "oldfieldtype": "Data",
+ "print_hide": 1,
+ "print_width": "100px",
"width": "100px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "vehicle_no",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Vehicle No",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "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
- },
+ "fieldname": "vehicle_no",
+ "fieldtype": "Data",
+ "label": "Vehicle No",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "col_break34",
- "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,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "print_width": "50%",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "col_break34",
+ "fieldtype": "Column Break",
+ "print_width": "50%",
"width": "50%"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "transporter.name",
- "fieldname": "transporter_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Transporter Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fetch_from": "transporter.name",
+ "fieldname": "transporter_name",
+ "fieldtype": "Data",
+ "label": "Transporter Name",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "driver.full_name",
- "fieldname": "driver_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Driver Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "driver.full_name",
+ "fieldname": "driver_name",
+ "fieldtype": "Data",
+ "label": "Driver Name",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Today",
- "description": "",
- "fieldname": "lr_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": "Transport Receipt Date",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "lr_date",
- "oldfieldtype": "Date",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "100px",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "default": "Today",
+ "fieldname": "lr_date",
+ "fieldtype": "Date",
+ "label": "Transport Receipt Date",
+ "oldfieldname": "lr_date",
+ "oldfieldtype": "Date",
+ "print_hide": 1,
+ "print_width": "100px",
"width": "100px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "more_info",
- "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": "More Information",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "options": "fa fa-file-text",
- "permlevel": 0,
- "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
- },
+ "collapsible": 1,
+ "fieldname": "more_info",
+ "fieldtype": "Section Break",
+ "label": "More Information",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-file-text",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "Track this Delivery Note against any Project",
- "fieldname": "project",
- "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": "Project",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "project",
- "oldfieldtype": "Link",
- "options": "Project",
- "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
- },
+ "description": "Track this Delivery Note against any Project",
+ "fieldname": "project",
+ "fieldtype": "Link",
+ "label": "Project",
+ "oldfieldname": "project",
+ "oldfieldtype": "Link",
+ "options": "Project"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "campaign",
- "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": "Campaign",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "campaign",
- "oldfieldtype": "Link",
- "options": "Campaign",
- "permlevel": 0,
- "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
- },
+ "fieldname": "campaign",
+ "fieldtype": "Link",
+ "label": "Campaign",
+ "oldfieldname": "campaign",
+ "oldfieldtype": "Link",
+ "options": "Campaign",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "source",
- "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",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "source",
- "oldfieldtype": "Select",
- "options": "Lead Source",
- "permlevel": 0,
- "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
- },
+ "fieldname": "source",
+ "fieldtype": "Link",
+ "label": "Source",
+ "oldfieldname": "source",
+ "oldfieldtype": "Select",
+ "options": "Lead Source",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break5",
- "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",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "50%",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "column_break5",
+ "fieldtype": "Column Break",
+ "oldfieldtype": "Column Break",
+ "print_hide": 1,
+ "print_width": "50%",
"width": "50%"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "per_billed",
- "fieldtype": "Percent",
- "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": "% Amount Billed",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fieldname": "per_billed",
+ "fieldtype": "Percent",
+ "label": "% Amount Billed",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
- "fieldname": "customer_group",
- "fieldtype": "Link",
- "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": "Customer Group",
- "length": 0,
- "no_copy": 0,
- "options": "Customer Group",
- "permlevel": 0,
- "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
- },
+ "fieldname": "customer_group",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Customer Group",
+ "options": "Customer Group",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "",
- "fieldname": "territory",
- "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": "Territory",
- "length": 0,
- "no_copy": 0,
- "options": "Territory",
- "permlevel": 0,
- "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
- },
+ "fieldname": "territory",
+ "fieldtype": "Link",
+ "label": "Territory",
+ "options": "Territory",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "printing_details",
- "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": "Printing Details",
- "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
- },
+ "collapsible": 1,
+ "fieldname": "printing_details",
+ "fieldtype": "Section Break",
+ "label": "Printing Details"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "letter_head",
- "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": "Letter Head",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "letter_head",
- "oldfieldtype": "Link",
- "options": "Letter Head",
- "permlevel": 0,
- "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_on_submit": 1,
+ "fieldname": "letter_head",
+ "fieldtype": "Link",
+ "label": "Letter Head",
+ "oldfieldname": "letter_head",
+ "oldfieldtype": "Link",
+ "options": "Letter Head",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "select_print_heading",
- "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": "Print Heading",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "select_print_heading",
- "oldfieldtype": "Link",
- "options": "Print Heading",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 1,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "fieldname": "select_print_heading",
+ "fieldtype": "Link",
+ "label": "Print Heading",
+ "no_copy": 1,
+ "oldfieldname": "select_print_heading",
+ "oldfieldtype": "Link",
+ "options": "Print Heading",
+ "print_hide": 1,
+ "report_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "language",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Print Language",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fieldname": "language",
+ "fieldtype": "Data",
+ "label": "Print Language",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_88",
- "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
- },
+ "fieldname": "column_break_88",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "print_without_amount",
- "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": "Print Without Amount",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "print_without_amount",
- "oldfieldtype": "Check",
- "permlevel": 0,
- "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_on_submit": 1,
+ "default": "0",
+ "fieldname": "print_without_amount",
+ "fieldtype": "Check",
+ "label": "Print Without Amount",
+ "oldfieldname": "print_without_amount",
+ "oldfieldtype": "Check",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "group_same_items",
- "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": "Group same items",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "default": "0",
+ "fieldname": "group_same_items",
+ "fieldtype": "Check",
+ "label": "Group same items",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "section_break_83",
- "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": "Status",
- "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
- },
+ "collapsible": 1,
+ "fieldname": "section_break_83",
+ "fieldtype": "Section Break",
+ "label": "Status"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Draft",
- "fieldname": "status",
- "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,
- "label": "Status",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "status",
- "oldfieldtype": "Select",
- "options": "\nDraft\nTo Bill\nCompleted\nCancelled\nClosed",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "150px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 1,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "default": "Draft",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "in_standard_filter": 1,
+ "label": "Status",
+ "no_copy": 1,
+ "oldfieldname": "status",
+ "oldfieldtype": "Select",
+ "options": "\nDraft\nTo Bill\nCompleted\nCancelled\nClosed",
+ "print_hide": 1,
+ "print_width": "150px",
+ "read_only": 1,
+ "reqd": 1,
+ "search_index": 1,
"width": "150px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:!doc.__islocal",
- "description": "% of materials delivered against this Delivery Note",
- "fieldname": "per_installed",
- "fieldtype": "Percent",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "% Installed",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "per_installed",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "print_hide": 1,
- "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
- },
+ "depends_on": "eval:!doc.__islocal",
+ "description": "% of materials delivered against this Delivery Note",
+ "fieldname": "per_installed",
+ "fieldtype": "Percent",
+ "in_list_view": 1,
+ "label": "% Installed",
+ "no_copy": 1,
+ "oldfieldname": "per_installed",
+ "oldfieldtype": "Currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "installation_status",
- "fieldtype": "Select",
- "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": "Installation Status",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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
- },
+ "fieldname": "installation_status",
+ "fieldtype": "Select",
+ "hidden": 1,
+ "label": "Installation Status",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_89",
- "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,
- "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
- },
+ "fieldname": "column_break_89",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "excise_page",
- "fieldtype": "Data",
- "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": "Excise Page Number",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "excise_page",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "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
- },
+ "fieldname": "excise_page",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Excise Page Number",
+ "oldfieldname": "excise_page",
+ "oldfieldtype": "Data",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "instructions",
- "fieldtype": "Text",
- "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": "Instructions",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "instructions",
- "oldfieldtype": "Text",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "instructions",
+ "fieldtype": "Text",
+ "label": "Instructions",
+ "oldfieldname": "instructions",
+ "oldfieldtype": "Text"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "subscription_section",
- "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": "Subscription Section",
- "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
- },
+ "fieldname": "subscription_section",
+ "fieldtype": "Section Break",
+ "label": "Subscription Section"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "auto_repeat",
- "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": "Auto Repeat",
- "length": 0,
- "no_copy": 1,
- "options": "Auto Repeat",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "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
- },
+ "fieldname": "auto_repeat",
+ "fieldtype": "Link",
+ "label": "Auto Repeat",
+ "no_copy": 1,
+ "options": "Auto Repeat",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "collapsible_depends_on": "total_commission",
- "columns": 0,
- "fieldname": "sales_team_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": "Commission",
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Section Break",
- "options": "fa fa-group",
- "permlevel": 0,
- "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
- },
+ "collapsible": 1,
+ "collapsible_depends_on": "total_commission",
+ "fieldname": "sales_team_section_break",
+ "fieldtype": "Section Break",
+ "label": "Commission",
+ "oldfieldtype": "Section Break",
+ "options": "fa fa-group",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sales_partner",
- "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": "Sales Partner",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "sales_partner",
- "oldfieldtype": "Link",
- "options": "Sales Partner",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "150px",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "sales_partner",
+ "fieldtype": "Link",
+ "label": "Sales Partner",
+ "oldfieldname": "sales_partner",
+ "oldfieldtype": "Link",
+ "options": "Sales Partner",
+ "print_hide": 1,
+ "print_width": "150px",
"width": "150px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break7",
- "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,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "50%",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "column_break7",
+ "fieldtype": "Column Break",
+ "print_hide": 1,
+ "print_width": "50%",
"width": "50%"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "commission_rate",
- "fieldtype": "Float",
- "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": "Commission Rate (%)",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "commission_rate",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "print_width": "100px",
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0,
+ "fieldname": "commission_rate",
+ "fieldtype": "Float",
+ "label": "Commission Rate (%)",
+ "oldfieldname": "commission_rate",
+ "oldfieldtype": "Currency",
+ "print_hide": 1,
+ "print_width": "100px",
"width": "100px"
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "total_commission",
- "fieldtype": "Currency",
- "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": "Total Commission",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "total_commission",
- "oldfieldtype": "Currency",
- "options": "Company:company:default_currency",
- "permlevel": 0,
- "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
- },
+ "fieldname": "total_commission",
+ "fieldtype": "Currency",
+ "label": "Total Commission",
+ "oldfieldname": "total_commission",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "collapsible_depends_on": "sales_team",
- "columns": 0,
- "fieldname": "section_break1",
- "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": "Sales Team",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "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
- },
+ "collapsible": 1,
+ "collapsible_depends_on": "sales_team",
+ "fieldname": "section_break1",
+ "fieldtype": "Section Break",
+ "label": "Sales Team",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sales_team",
- "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": "Sales Team1",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "sales_team",
- "oldfieldtype": "Table",
- "options": "Sales Team",
- "permlevel": 0,
- "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_on_submit": 1,
+ "fieldname": "sales_team",
+ "fieldtype": "Table",
+ "label": "Sales Team",
+ "oldfieldname": "sales_team",
+ "oldfieldtype": "Table",
+ "options": "Sales Team",
+ "print_hide": 1
+ },
+ {
+ "fieldname": "pick_list",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Pick List",
+ "options": "Pick List",
+ "read_only": 1
+ },
+ {
+ "fieldname": "section_break_18",
+ "fieldtype": "Section Break"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-truck",
- "idx": 146,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "menu_index": 0,
- "modified": "2019-02-13 01:06:29.783590",
- "modified_by": "Administrator",
- "module": "Stock",
- "name": "Delivery Note",
- "owner": "Administrator",
+ ],
+ "icon": "fa fa-truck",
+ "idx": 146,
+ "is_submittable": 1,
+ "modified": "2019-08-26 07:37:39.766014",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Delivery Note",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Stock User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Stock User",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Stock Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Stock Manager",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Sales User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Sales User",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 1,
- "role": "Accounts User",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
- "write": 0
- },
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User"
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 0,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 1,
- "print": 0,
- "read": 1,
- "report": 0,
- "role": "Stock Manager",
- "set_user_permissions": 0,
- "share": 0,
- "submit": 0,
+ "permlevel": 1,
+ "read": 1,
+ "role": "Stock Manager",
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 1,
- "search_fields": "status,customer,customer_name, territory,base_grand_total",
- "show_name_in_global_search": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "timeline_field": "customer",
- "title_field": "title",
- "track_changes": 1,
- "track_seen": 1,
- "track_views": 0
-}
+ ],
+ "search_fields": "status,customer,customer_name, territory,base_grand_total",
+ "show_name_in_global_search": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "timeline_field": "customer",
+ "title_field": "title",
+ "track_changes": 1,
+ "track_seen": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 2de9b97..bdb49e4 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -166,24 +166,7 @@
frappe.throw(_("Customer {0} does not belong to project {1}").format(self.customer, self.project))
def validate_for_items(self):
- check_list, chk_dupl_itm = [], []
- if cint(frappe.db.get_single_value("Selling Settings", "allow_multiple_items")):
- return
-
for d in self.get('items'):
- e = [d.item_code, d.description, d.warehouse, d.against_sales_order or d.against_sales_invoice, d.batch_no or '']
- f = [d.item_code, d.description, d.against_sales_order or d.against_sales_invoice]
-
- if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1:
- if e in check_list:
- frappe.msgprint(_("Note: Item {0} entered multiple times").format(d.item_code))
- else:
- check_list.append(e)
- else:
- if f in chk_dupl_itm:
- frappe.msgprint(_("Note: Item {0} entered multiple times").format(d.item_code))
- else:
- chk_dupl_itm.append(f)
#Customer Provided parts will have zero valuation rate
if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'):
d.allow_zero_valuation_rate = 1
@@ -251,8 +234,10 @@
extra_amount = 0
validate_against_credit_limit = False
- bypass_credit_limit_check_at_sales_order = cint(frappe.db.get_value("Customer", self.customer,
- "bypass_credit_limit_check_at_sales_order"))
+ bypass_credit_limit_check_at_sales_order = cint(frappe.db.get_value("Customer Credit Limit",
+ filters={'parent': self.customer, 'parenttype': 'Customer', 'company': self.company},
+ fieldname="bypass_credit_limit_check"))
+
if bypass_credit_limit_check_at_sales_order:
validate_against_credit_limit = True
extra_amount = self.base_grand_total
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index bc95c96..91b6f4c 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -701,6 +701,7 @@
"qty": args.qty or 1,
"rate": args.rate or 100,
"conversion_factor": 1.0,
+ "allow_zero_valuation_rate": args.allow_zero_valuation_rate or 1,
"expense_account": "Cost of Goods Sold - _TC",
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"serial_no": args.serial_no,
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
index a253811..77d322e 100644
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
@@ -238,7 +238,7 @@
try:
directions = maps_client.directions(**directions_data)
except Exception as e:
- frappe.throw(_(e.message))
+ frappe.throw(_(e))
return directions[0] if directions else False
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 383fb61..46efd4e 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -904,7 +904,7 @@
"description": "Item Image (if not slideshow)",
"fieldname": "website_image",
"fieldtype": "Attach",
- "label": "Image"
+ "label": "Website Image"
},
{
"fieldname": "thumbnail",
@@ -1040,7 +1040,7 @@
"idx": 2,
"image_field": "image",
"max_attachments": 1,
- "modified": "2019-07-12 12:18:13.977931",
+ "modified": "2019-09-03 18:34:13.977931",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 1568729..518fe74 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -124,6 +124,7 @@
self.update_defaults_from_item_group()
self.validate_auto_reorder_enabled_in_stock_settings()
self.cant_change()
+ self.update_show_in_website()
if not self.get("__islocal"):
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
@@ -476,6 +477,10 @@
[self.remove(d) for d in to_remove]
+ def update_show_in_website(self):
+ if self.disabled:
+ self.show_in_website = False
+
def update_template_tables(self):
template = frappe.get_doc("Item", self.variant_of)
diff --git a/erpnext/stock/doctype/item_price/item_price.py b/erpnext/stock/doctype/item_price/item_price.py
index 30675b5..4c496cb 100644
--- a/erpnext/stock/doctype/item_price/item_price.py
+++ b/erpnext/stock/doctype/item_price/item_price.py
@@ -32,10 +32,16 @@
def update_price_list_details(self):
if self.price_list:
- self.buying, self.selling, self.currency = \
- frappe.db.get_value("Price List",
- {"name": self.price_list, "enabled": 1},
- ["buying", "selling", "currency"])
+ price_list_details = frappe.db.get_value("Price List",
+ {"name": self.price_list, "enabled": 1},
+ ["buying", "selling", "currency"])
+
+ if not price_list_details:
+ link = frappe.utils.get_link_to_form('Price List', self.price_list)
+ frappe.throw("The price list {0} does not exists or disabled".
+ format(link))
+
+ self.buying, self.selling, self.currency = price_list_details
def update_item_details(self):
if self.item_code:
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index 96e31ff..99195c3 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -8,6 +8,7 @@
setup: function(frm) {
frm.custom_make_buttons = {
'Stock Entry': 'Issue Material',
+ 'Pick List': 'Pick List',
'Purchase Order': 'Purchase Order',
'Request for Quotation': 'Request for Quotation',
'Supplier Quotation': 'Supplier Quotation',
@@ -55,8 +56,13 @@
if (frm.doc.docstatus == 1 && frm.doc.status != 'Stopped') {
if (flt(frm.doc.per_ordered, 2) < 100) {
- // make
+ let add_create_pick_list_button = () => {
+ frm.add_custom_button(__('Pick List'),
+ () => frm.events.create_pick_list(frm), __('Create'));
+ }
+
if (frm.doc.material_request_type === "Material Transfer") {
+ add_create_pick_list_button();
frm.add_custom_button(__("Transfer Material"),
() => frm.events.make_stock_entry(frm), __('Create'));
}
@@ -258,6 +264,13 @@
});
},
+ create_pick_list: (frm) => {
+ frappe.model.open_mapped_doc({
+ method: "erpnext.stock.doctype.material_request.material_request.create_pick_list",
+ frm: frm
+ });
+ },
+
raise_work_orders: function(frm) {
frappe.call({
method:"erpnext.stock.doctype.material_request.material_request.raise_work_orders",
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index f2fe448..44e890c 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -502,3 +502,28 @@
frappe.throw(_("Productions Orders cannot be raised for:") + '\n' + new_line_sep(errors))
return work_orders
+
+@frappe.whitelist()
+def create_pick_list(source_name, target_doc=None):
+ doc = get_mapped_doc('Material Request', source_name, {
+ 'Material Request': {
+ 'doctype': 'Pick List',
+ 'field_map': {
+ 'material_request_type': 'purpose'
+ },
+ 'validation': {
+ 'docstatus': ['=', 1]
+ }
+ },
+ 'Material Request Item': {
+ 'doctype': 'Pick List Item',
+ 'field_map': {
+ 'name': 'material_request_item',
+ 'qty': 'stock_qty'
+ },
+ },
+ }, target_doc)
+
+ doc.set_item_locations()
+
+ return doc
\ No newline at end of file
diff --git a/erpnext/stock/doctype/material_request/material_request_dashboard.py b/erpnext/stock/doctype/material_request/material_request_dashboard.py
index adfab86..cbd6478 100644
--- a/erpnext/stock/doctype/material_request/material_request_dashboard.py
+++ b/erpnext/stock/doctype/material_request/material_request_dashboard.py
@@ -8,7 +8,7 @@
'transactions': [
{
'label': _('Related'),
- 'items': ['Request for Quotation', 'Supplier Quotation', 'Purchase Order', "Stock Entry"]
+ 'items': ['Request for Quotation', 'Supplier Quotation', 'Purchase Order', 'Stock Entry', 'Pick List']
},
{
'label': _('Manufacturing'),
diff --git a/erpnext/stock/doctype/packed_item/packed_item.json b/erpnext/stock/doctype/packed_item/packed_item.json
index 6c8b2b1..b089e75 100644
--- a/erpnext/stock/doctype/packed_item/packed_item.json
+++ b/erpnext/stock/doctype/packed_item/packed_item.json
@@ -1,685 +1,203 @@
{
- "allow_copy": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2013-02-22 01:28:00",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "creation": "2013-02-22 01:28:00",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "parent_item",
+ "item_code",
+ "item_name",
+ "column_break_5",
+ "description",
+ "section_break_6",
+ "warehouse",
+ "target_warehouse",
+ "column_break_9",
+ "qty",
+ "section_break_9",
+ "serial_no",
+ "column_break_11",
+ "batch_no",
+ "section_break_13",
+ "actual_qty",
+ "projected_qty",
+ "column_break_16",
+ "uom",
+ "page_break",
+ "prevdoc_doctype",
+ "parent_detail_docname"
+ ],
"fields": [
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "parent_item",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Parent Item",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "parent_item",
- "oldfieldtype": "Link",
- "options": "Item",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "parent_item",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Parent Item",
+ "oldfieldname": "parent_item",
+ "oldfieldtype": "Link",
+ "options": "Item",
+ "read_only": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "item_code",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Item Code",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "item_code",
- "oldfieldtype": "Link",
- "options": "Item",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "item_code",
+ "fieldtype": "Link",
+ "in_global_search": 1,
+ "in_list_view": 1,
+ "label": "Item Code",
+ "oldfieldname": "item_code",
+ "oldfieldtype": "Link",
+ "options": "Item",
+ "read_only": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "item_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Item Name",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "item_name",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "label": "Item Name",
+ "oldfieldname": "item_name",
+ "oldfieldtype": "Data",
+ "read_only": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_5",
- "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,
- "unique": 0
- },
+ "fieldname": "column_break_5",
+ "fieldtype": "Column Break"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "description",
- "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_standard_filter": 0,
- "label": "Description",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "description",
- "oldfieldtype": "Text",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "print_width": "300px",
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0,
+ "fieldname": "description",
+ "fieldtype": "Text Editor",
+ "in_list_view": 1,
+ "label": "Description",
+ "oldfieldname": "description",
+ "oldfieldtype": "Text",
+ "print_width": "300px",
"width": "300px"
- },
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_6",
- "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,
- "unique": 0
- },
+ "fieldname": "section_break_6",
+ "fieldtype": "Section Break"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "warehouse",
- "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": "From Warehouse",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "warehouse",
- "oldfieldtype": "Link",
- "options": "Warehouse",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "warehouse",
+ "fieldtype": "Link",
+ "label": "From Warehouse",
+ "oldfieldname": "warehouse",
+ "oldfieldtype": "Link",
+ "options": "Warehouse"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "target_warehouse",
- "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": "To Warehouse (Optional)",
- "length": 0,
- "no_copy": 0,
- "options": "Warehouse",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "target_warehouse",
+ "fieldtype": "Link",
+ "label": "To Warehouse (Optional)",
+ "options": "Warehouse",
+ "print_hide": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_9",
- "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,
- "unique": 0
- },
+ "fieldname": "column_break_9",
+ "fieldtype": "Column Break"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "qty",
- "fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Qty",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "qty",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "qty",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Qty",
+ "oldfieldname": "qty",
+ "oldfieldtype": "Currency",
+ "read_only": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_9",
- "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,
- "unique": 0
- },
+ "fieldname": "section_break_9",
+ "fieldtype": "Section Break"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "serial_no",
- "fieldtype": "Text",
- "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": "Serial No",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "serial_no",
+ "fieldtype": "Text",
+ "label": "Serial No"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_11",
- "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,
- "unique": 0
- },
+ "fieldname": "column_break_11",
+ "fieldtype": "Column Break"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "batch_no",
- "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": "Batch No",
- "length": 0,
- "no_copy": 0,
- "options": "Batch",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "batch_no",
+ "fieldtype": "Link",
+ "label": "Batch No",
+ "options": "Batch"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_13",
- "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,
- "unique": 0
- },
+ "fieldname": "section_break_13",
+ "fieldtype": "Section Break"
+ },
{
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "actual_qty",
- "fieldtype": "Float",
- "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": "Actual Qty",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "actual_qty",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "fieldname": "actual_qty",
+ "fieldtype": "Float",
+ "label": "Actual Qty",
+ "no_copy": 1,
+ "oldfieldname": "actual_qty",
+ "oldfieldtype": "Currency",
+ "read_only": 1
+ },
{
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "projected_qty",
- "fieldtype": "Float",
- "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": "Projected Qty",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "projected_qty",
- "oldfieldtype": "Currency",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "fieldname": "projected_qty",
+ "fieldtype": "Float",
+ "label": "Projected Qty",
+ "no_copy": 1,
+ "oldfieldname": "projected_qty",
+ "oldfieldtype": "Currency",
+ "read_only": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_16",
- "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,
- "unique": 0
- },
+ "fieldname": "column_break_16",
+ "fieldtype": "Column Break"
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "uom",
- "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": "UOM",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "uom",
- "oldfieldtype": "Link",
- "options": "UOM",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "uom",
+ "fieldtype": "Link",
+ "label": "UOM",
+ "oldfieldname": "uom",
+ "oldfieldtype": "Link",
+ "options": "UOM",
+ "read_only": 1
+ },
{
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "page_break",
- "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": "Page Break",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "page_break",
- "oldfieldtype": "Check",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "default": "0",
+ "fieldname": "page_break",
+ "fieldtype": "Check",
+ "label": "Page Break",
+ "oldfieldname": "page_break",
+ "oldfieldtype": "Check",
+ "read_only": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "prevdoc_doctype",
- "fieldtype": "Data",
- "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": "Prevdoc DocType",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "prevdoc_doctype",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
+ "fieldname": "prevdoc_doctype",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Prevdoc DocType",
+ "oldfieldname": "prevdoc_doctype",
+ "oldfieldtype": "Data",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "parent_detail_docname",
- "fieldtype": "Data",
- "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": "Parent Detail docname",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "parent_detail_docname",
- "oldfieldtype": "Data",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
+ "fieldname": "parent_detail_docname",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Parent Detail docname",
+ "no_copy": 1,
+ "oldfieldname": "parent_detail_docname",
+ "oldfieldtype": "Data",
+ "print_hide": 1,
+ "read_only": 1
}
- ],
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
-
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2017-02-20 13:27:37.569945",
- "modified_by": "Administrator",
- "module": "Stock",
- "name": "Packed Item",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
+ ],
+ "idx": 1,
+ "istable": 1,
+ "modified": "2019-08-27 18:17:37.167512",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Packed Item",
+ "owner": "Administrator",
+ "permissions": [],
+ "track_changes": 1
+}
diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py
index cf72527..2fd6516 100644
--- a/erpnext/stock/doctype/packed_item/packed_item.py
+++ b/erpnext/stock/doctype/packed_item/packed_item.py
@@ -30,14 +30,14 @@
where item_code = %s and warehouse = %s""", (item, warehouse), as_dict = 1)
return det and det[0] or frappe._dict()
-def update_packing_list_item(doc, packing_item_code, qty, main_item_row, description):
+def update_packing_list_item(doc, packing_item_code, qty, main_item_row, description):
item = get_packing_item_details(packing_item_code, doc.company)
# check if exists
exists = 0
for d in doc.get("packed_items"):
if d.parent_item == main_item_row.item_code and d.item_code == packing_item_code and\
- d.parent_detail_docname == main_item_row.name and d.description == description:
+ d.parent_detail_docname == main_item_row.name:
pi, exists = d, 1
break
@@ -48,10 +48,10 @@
pi.item_code = packing_item_code
pi.item_name = item.item_name
pi.parent_detail_docname = main_item_row.name
- pi.description = item.description
pi.uom = item.stock_uom
pi.qty = flt(qty)
- pi.description = description
+ if description and not pi.description:
+ pi.description = description
if not pi.warehouse:
pi.warehouse = (main_item_row.warehouse if ((doc.get('is_pos')
or not item.default_warehouse) and main_item_row.warehouse) else item.default_warehouse)
@@ -112,4 +112,4 @@
return items
def on_doctype_update():
- frappe.db.add_index("Packed Item", ["item_code", "warehouse"])
\ No newline at end of file
+ frappe.db.add_index("Packed Item", ["item_code", "warehouse"])
diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.js b/erpnext/stock/doctype/packing_slip/packing_slip.js
index 9f6b9ff..bd14e5f 100644
--- a/erpnext/stock/doctype/packing_slip/packing_slip.js
+++ b/erpnext/stock/doctype/packing_slip/packing_slip.js
@@ -10,7 +10,7 @@
cur_frm.fields_dict['items'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) {
if(!doc.delivery_note) {
- frappe.throw(__("Please Delivery Note first"))
+ frappe.throw(__("Please select a Delivery Note"));
} else {
return {
query: "erpnext.stock.doctype.packing_slip.packing_slip.item_details",
@@ -125,4 +125,4 @@
return '<table style="width:100%">' + make_row('Gross Weight', doc.gross_weight_pkg) + '</table>'
}
-// TODO: validate gross weight field
\ No newline at end of file
+// TODO: validate gross weight field
diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.json b/erpnext/stock/doctype/packing_slip/packing_slip.json
index 0ed039a..ec8d57c 100644
--- a/erpnext/stock/doctype/packing_slip/packing_slip.json
+++ b/erpnext/stock/doctype/packing_slip/packing_slip.json
@@ -74,7 +74,7 @@
{
"description": "Identification of the package for the delivery (for print)",
"fieldname": "from_case_no",
- "fieldtype": "Data",
+ "fieldtype": "Int",
"in_list_view": 1,
"label": "From Package No.",
"no_copy": 1,
@@ -88,7 +88,7 @@
{
"description": "If more than one package of the same type (for print)",
"fieldname": "to_case_no",
- "fieldtype": "Data",
+ "fieldtype": "Int",
"in_list_view": 1,
"label": "To Package No.",
"no_copy": 1,
@@ -180,7 +180,7 @@
"icon": "fa fa-suitcase",
"idx": 1,
"is_submittable": 1,
- "modified": "2019-05-31 04:45:08.082862",
+ "modified": "2019-09-09 04:45:08.082862",
"modified_by": "Administrator",
"module": "Stock",
"name": "Packing Slip",
@@ -261,4 +261,4 @@
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC"
- }
\ No newline at end of file
+ }
diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.py b/erpnext/stock/doctype/packing_slip/packing_slip.py
index b99215c..7a5ae31 100644
--- a/erpnext/stock/doctype/packing_slip/packing_slip.py
+++ b/erpnext/stock/doctype/packing_slip/packing_slip.py
@@ -49,11 +49,10 @@
frappe.msgprint(_("Please specify a valid 'From Case No.'"), raise_exception=1)
elif not self.to_case_no:
self.to_case_no = self.from_case_no
- elif self.from_case_no > self.to_case_no:
+ elif cint(self.from_case_no) > cint(self.to_case_no):
frappe.msgprint(_("'To Case No.' cannot be less than 'From Case No.'"),
raise_exception=1)
-
res = frappe.db.sql("""SELECT name FROM `tabPacking Slip`
WHERE delivery_note = %(delivery_note)s AND docstatus = 1 AND
((from_case_no BETWEEN %(from_case_no)s AND %(to_case_no)s)
diff --git a/erpnext/stock/doctype/pick_list/__init__.py b/erpnext/stock/doctype/pick_list/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/doctype/pick_list/__init__.py
diff --git a/erpnext/stock/doctype/pick_list/pick_list.js b/erpnext/stock/doctype/pick_list/pick_list.js
new file mode 100644
index 0000000..3f66743
--- /dev/null
+++ b/erpnext/stock/doctype/pick_list/pick_list.js
@@ -0,0 +1,180 @@
+// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Pick List', {
+ setup: (frm) => {
+ frm.custom_make_buttons = {
+ 'Delivery Note': 'Delivery Note',
+ 'Stock Entry': 'Stock Entry',
+ };
+ frm.set_query('parent_warehouse', () => {
+ return {
+ filters: {
+ 'is_group': 1,
+ 'company': frm.doc.company
+ }
+ };
+ });
+ frm.set_query('work_order', () => {
+ return {
+ query: 'erpnext.stock.doctype.pick_list.pick_list.get_pending_work_orders',
+ filters: {
+ 'company': frm.doc.company
+ }
+ };
+ });
+ frm.set_query('material_request', () => {
+ return {
+ filters: {
+ 'material_request_type': ['=', frm.doc.purpose]
+ }
+ };
+ });
+ frm.set_query('item_code', 'locations', () => {
+ return {
+ filters: {
+ is_stock_item: 1
+ }
+ };
+ });
+ },
+ get_item_locations: (frm) => {
+ if (!frm.doc.locations || !frm.doc.locations.length) {
+ frappe.msgprint(__('First add items in the Item Locations table'));
+ } else {
+ frm.call('set_item_locations');
+ }
+ },
+ refresh: (frm) => {
+ frm.trigger('add_get_items_button');
+ if (frm.doc.docstatus === 1) {
+ frappe.xcall('erpnext.stock.doctype.pick_list.pick_list.target_document_exists', {
+ 'pick_list_name': frm.doc.name,
+ 'purpose': frm.doc.purpose
+ }).then(target_document_exists => {
+ if (target_document_exists) return;
+ if (frm.doc.purpose === 'Delivery against Sales Order') {
+ frm.add_custom_button(__('Delivery Note'), () => frm.trigger('create_delivery_note'), __('Create'));
+ } else {
+ frm.add_custom_button(__('Stock Entry'), () => frm.trigger('create_stock_entry'), __('Create'));
+ }
+ });
+ }
+ },
+ work_order: (frm) => {
+ frappe.db.get_value('Work Order',
+ frm.doc.work_order,
+ ['qty', 'material_transferred_for_manufacturing']
+ ).then(data => {
+ let qty_data = data.message;
+ let max = qty_data.qty - qty_data.material_transferred_for_manufacturing;
+ frappe.prompt({
+ fieldtype: 'Float',
+ label: __('Qty of Finished Goods Item'),
+ fieldname: 'qty',
+ description: __('Max: {0}', [max]),
+ default: max
+ }, (data) => {
+ frm.set_value('for_qty', data.qty);
+ if (data.qty > max) {
+ frappe.msgprint(__('Quantity must not be more than {0}', [max]));
+ return;
+ }
+ frm.clear_table('locations');
+ erpnext.utils.map_current_doc({
+ method: 'erpnext.manufacturing.doctype.work_order.work_order.create_pick_list',
+ target: frm,
+ source_name: frm.doc.work_order
+ });
+ }, __('Select Quantity'), __('Get Items'));
+ });
+ },
+ material_request: (frm) => {
+ erpnext.utils.map_current_doc({
+ method: 'erpnext.stock.doctype.material_request.material_request.create_pick_list',
+ target: frm,
+ source_name: frm.doc.material_request
+ });
+ },
+ purpose: (frm) => {
+ frm.clear_table('locations');
+ frm.trigger('add_get_items_button');
+ },
+ create_delivery_note: (frm) => {
+ frappe.model.open_mapped_doc({
+ method: 'erpnext.stock.doctype.pick_list.pick_list.create_delivery_note',
+ frm: frm
+ });
+ },
+ create_stock_entry: (frm) => {
+ frappe.xcall('erpnext.stock.doctype.pick_list.pick_list.create_stock_entry', {
+ 'pick_list': frm.doc,
+ }).then(stock_entry => {
+ frappe.model.sync(stock_entry);
+ frappe.set_route("Form", 'Stock Entry', stock_entry.name);
+ });
+ },
+ add_get_items_button: (frm) => {
+ let purpose = frm.doc.purpose;
+ if (purpose != 'Delivery against Sales Order' || frm.doc.docstatus !== 0) return;
+ let get_query_filters = {
+ docstatus: 1,
+ per_delivered: ['<', 100],
+ status: ['!=', ''],
+ customer: frm.doc.customer
+ };
+ frm.get_items_btn = frm.add_custom_button(__('Get Items'), () => {
+ if (!frm.doc.customer) {
+ frappe.msgprint(__('Please select Customer first'));
+ return;
+ }
+ erpnext.utils.map_current_doc({
+ method: 'erpnext.selling.doctype.sales_order.sales_order.create_pick_list',
+ source_doctype: 'Sales Order',
+ target: frm,
+ setters: {
+ company: frm.doc.company,
+ customer: frm.doc.customer
+ },
+ date_field: 'transaction_date',
+ get_query_filters: get_query_filters
+ });
+ });
+ }
+});
+
+frappe.ui.form.on('Pick List Item', {
+ item_code: (frm, cdt, cdn) => {
+ let row = frappe.get_doc(cdt, cdn);
+ if (row.item_code) {
+ get_item_details(row.item_code).then(data => {
+ frappe.model.set_value(cdt, cdn, 'uom', data.stock_uom);
+ frappe.model.set_value(cdt, cdn, 'stock_uom', data.stock_uom);
+ frappe.model.set_value(cdt, cdn, 'conversion_factor', 1);
+ });
+ }
+ },
+ uom: (frm, cdt, cdn) => {
+ let row = frappe.get_doc(cdt, cdn);
+ if (row.uom) {
+ get_item_details(row.item_code, row.uom).then(data => {
+ frappe.model.set_value(cdt, cdn, 'conversion_factor', data.conversion_factor);
+ });
+ }
+ },
+ qty: (frm, cdt, cdn) => {
+ let row = frappe.get_doc(cdt, cdn);
+ frappe.model.set_value(cdt, cdn, 'stock_qty', row.qty * row.conversion_factor);
+ },
+ conversion_factor: (frm, cdt, cdn) => {
+ let row = frappe.get_doc(cdt, cdn);
+ frappe.model.set_value(cdt, cdn, 'stock_qty', row.qty * row.conversion_factor);
+ }
+});
+
+function get_item_details(item_code, uom=null) {
+ return frappe.xcall('erpnext.stock.doctype.pick_list.pick_list.get_item_details', {
+ item_code,
+ uom
+ });
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/pick_list/pick_list.json b/erpnext/stock/doctype/pick_list/pick_list.json
new file mode 100644
index 0000000..8d5ef3d
--- /dev/null
+++ b/erpnext/stock/doctype/pick_list/pick_list.json
@@ -0,0 +1,184 @@
+{
+ "autoname": "naming_series:",
+ "creation": "2019-07-11 16:03:13.681045",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "naming_series",
+ "company",
+ "purpose",
+ "customer",
+ "work_order",
+ "material_request",
+ "for_qty",
+ "column_break_4",
+ "parent_warehouse",
+ "get_item_locations",
+ "section_break_6",
+ "locations",
+ "amended_from"
+ ],
+ "fields": [
+ {
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Company",
+ "options": "Company",
+ "reqd": 1
+ },
+ {
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "section_break_6",
+ "fieldtype": "Section Break"
+ },
+ {
+ "description": "Items under this warehouse will be suggested",
+ "fieldname": "parent_warehouse",
+ "fieldtype": "Link",
+ "label": "Parent Warehouse",
+ "options": "Warehouse"
+ },
+ {
+ "depends_on": "eval:doc.purpose==='Delivery against Sales Order'",
+ "fieldname": "customer",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Customer",
+ "options": "Customer"
+ },
+ {
+ "depends_on": "eval:doc.purpose==='Material Transfer for Manufacture'",
+ "fieldname": "work_order",
+ "fieldtype": "Link",
+ "label": "Work Order",
+ "options": "Work Order"
+ },
+ {
+ "fieldname": "locations",
+ "fieldtype": "Table",
+ "label": "Item Locations",
+ "options": "Pick List Item"
+ },
+ {
+ "depends_on": "eval:doc.purpose==='Material Transfer for Manufacture'",
+ "description": "Qty of raw materials will be decided based on the qty of the Finished Goods Item",
+ "fieldname": "for_qty",
+ "fieldtype": "Float",
+ "label": "Qty of Finished Goods Item",
+ "read_only": 1
+ },
+ {
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Pick List",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "default": "Material Transfer for Manufacture",
+ "fieldname": "purpose",
+ "fieldtype": "Select",
+ "label": "Purpose",
+ "options": "Material Transfer for Manufacture\nMaterial Transfer\nDelivery against Sales Order"
+ },
+ {
+ "depends_on": "eval:['Material Transfer', 'Material Issue'].includes(doc.purpose)",
+ "fieldname": "material_request",
+ "fieldtype": "Link",
+ "label": "Material Request",
+ "options": "Material Request"
+ },
+ {
+ "depends_on": "eval:doc.docstatus===0",
+ "fieldname": "get_item_locations",
+ "fieldtype": "Button",
+ "label": "Get Item Locations"
+ },
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "options": "STO-PICK-.YYYY.-",
+ "reqd": 1,
+ "set_only_once": 1
+ }
+ ],
+ "is_submittable": 1,
+ "modified": "2019-08-29 21:10:11.572387",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Pick List",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Stock Manager",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Stock User",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Manufacturing Manager",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ },
+ {
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Manufacturing User",
+ "share": 1,
+ "submit": 1,
+ "write": 1
+ }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
new file mode 100644
index 0000000..c4d8c41
--- /dev/null
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -0,0 +1,432 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+import json
+from six import iteritems
+from frappe.model.document import Document
+from frappe import _
+from collections import OrderedDict
+from frappe.utils import floor, flt, today, cint
+from frappe.model.mapper import get_mapped_doc, map_child_doc
+from erpnext.stock.get_item_details import get_conversion_factor
+from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note as create_delivery_note_from_sales_order
+
+# TODO: Prioritize SO or WO group warehouse
+
+class PickList(Document):
+ def before_save(self):
+ self.set_item_locations()
+
+ def before_submit(self):
+ for item in self.locations:
+ if not frappe.get_cached_value('Item', item.item_code, 'has_serial_no'):
+ continue
+ if len(item.serial_no.split('\n')) == item.picked_qty:
+ continue
+ frappe.throw(_('For item {0} at row {1}, count of serial numbers does not match with the picked quantity')
+ .format(frappe.bold(item.item_code), frappe.bold(item.idx)))
+
+ def set_item_locations(self):
+ items = self.aggregate_item_qty()
+ self.item_location_map = frappe._dict()
+
+ from_warehouses = None
+ if self.parent_warehouse:
+ from_warehouses = frappe.db.get_descendants('Warehouse', self.parent_warehouse)
+
+ # reset
+ self.delete_key('locations')
+ for item_doc in items:
+ item_code = item_doc.item_code
+
+ self.item_location_map.setdefault(item_code,
+ get_available_item_locations(item_code, from_warehouses, self.item_count_map.get(item_code)))
+
+ locations = get_items_with_location_and_quantity(item_doc, self.item_location_map)
+
+ item_doc.idx = None
+ item_doc.name = None
+
+ for row in locations:
+ row.update({
+ 'picked_qty': row.stock_qty
+ })
+
+ location = item_doc.as_dict()
+ location.update(row)
+ self.append('locations', location)
+
+ def aggregate_item_qty(self):
+ locations = self.get('locations')
+ self.item_count_map = {}
+ # aggregate qty for same item
+ item_map = OrderedDict()
+ for item in locations:
+ item_code = item.item_code
+ reference = item.sales_order_item or item.material_request_item
+ key = (item_code, item.uom, reference)
+
+ item.idx = None
+ item.name = None
+
+ if item_map.get(key):
+ item_map[key].qty += item.qty
+ item_map[key].stock_qty += item.stock_qty
+ else:
+ item_map[key] = item
+
+ # maintain count of each item (useful to limit get query)
+ self.item_count_map.setdefault(item_code, 0)
+ self.item_count_map[item_code] += item.stock_qty
+
+ return item_map.values()
+
+
+def get_items_with_location_and_quantity(item_doc, item_location_map):
+ available_locations = item_location_map.get(item_doc.item_code)
+ locations = []
+
+ remaining_stock_qty = item_doc.stock_qty
+ while remaining_stock_qty > 0 and available_locations:
+ item_location = available_locations.pop(0)
+ item_location = frappe._dict(item_location)
+
+ stock_qty = remaining_stock_qty if item_location.qty >= remaining_stock_qty else item_location.qty
+ qty = stock_qty / (item_doc.conversion_factor or 1)
+
+ uom_must_be_whole_number = frappe.db.get_value('UOM', item_doc.uom, 'must_be_whole_number')
+ if uom_must_be_whole_number:
+ qty = floor(qty)
+ stock_qty = qty * item_doc.conversion_factor
+ if not stock_qty: break
+
+ serial_nos = None
+ if item_location.serial_no:
+ serial_nos = '\n'.join(item_location.serial_no[0: cint(stock_qty)])
+
+ locations.append(frappe._dict({
+ 'qty': qty,
+ 'stock_qty': stock_qty,
+ 'warehouse': item_location.warehouse,
+ 'serial_no': serial_nos,
+ 'batch_no': item_location.batch_no
+ }))
+
+ remaining_stock_qty -= stock_qty
+
+ qty_diff = item_location.qty - stock_qty
+ # if extra quantity is available push current warehouse to available locations
+ if qty_diff > 0:
+ item_location.qty = qty_diff
+ if item_location.serial_no:
+ # set remaining serial numbers
+ item_location.serial_no = item_location.serial_no[-qty_diff:]
+ available_locations = [item_location] + available_locations
+
+ # update available locations for the item
+ item_location_map[item_doc.item_code] = available_locations
+ return locations
+
+def get_available_item_locations(item_code, from_warehouses, required_qty):
+ locations = []
+ if frappe.get_cached_value('Item', item_code, 'has_serial_no'):
+ locations = get_available_item_locations_for_serialized_item(item_code, from_warehouses, required_qty)
+ elif frappe.get_cached_value('Item', item_code, 'has_batch_no'):
+ locations = get_available_item_locations_for_batched_item(item_code, from_warehouses, required_qty)
+ else:
+ locations = get_available_item_locations_for_other_item(item_code, from_warehouses, required_qty)
+
+ total_qty_available = sum(location.get('qty') for location in locations)
+
+ remaining_qty = required_qty - total_qty_available
+
+ if remaining_qty > 0:
+ frappe.msgprint(_('{0} units of {1} is not available.')
+ .format(remaining_qty, frappe.get_desk_link('Item', item_code)))
+
+ return locations
+
+
+def get_available_item_locations_for_serialized_item(item_code, from_warehouses, required_qty):
+ filters = frappe._dict({
+ 'item_code': item_code,
+ 'warehouse': ['!=', '']
+ })
+
+ if from_warehouses:
+ filters.warehouse = ['in', from_warehouses]
+
+ serial_nos = frappe.get_all('Serial No',
+ fields=['name', 'warehouse'],
+ filters=filters,
+ limit=required_qty,
+ order_by='purchase_date',
+ as_list=1)
+
+ warehouse_serial_nos_map = frappe._dict()
+ for serial_no, warehouse in serial_nos:
+ warehouse_serial_nos_map.setdefault(warehouse, []).append(serial_no)
+
+ locations = []
+ for warehouse, serial_nos in iteritems(warehouse_serial_nos_map):
+ locations.append({
+ 'qty': len(serial_nos),
+ 'warehouse': warehouse,
+ 'serial_no': serial_nos
+ })
+
+ return locations
+
+def get_available_item_locations_for_batched_item(item_code, from_warehouses, required_qty):
+ warehouse_condition = 'and warehouse in %(warehouses)s' if from_warehouses else ''
+ batch_locations = frappe.db.sql("""
+ SELECT
+ sle.`warehouse`,
+ sle.`batch_no`,
+ SUM(sle.`actual_qty`) AS `qty`
+ FROM
+ `tabStock Ledger Entry` sle, `tabBatch` batch
+ WHERE
+ sle.batch_no = batch.name
+ and sle.`item_code`=%(item_code)s
+ and IFNULL(batch.`expiry_date`, '2200-01-01') > %(today)s
+ {warehouse_condition}
+ GROUP BY
+ `warehouse`,
+ `batch_no`,
+ `item_code`
+ HAVING `qty` > 0
+ ORDER BY IFNULL(batch.`expiry_date`, '2200-01-01'), batch.`creation`
+ """.format(warehouse_condition=warehouse_condition), { #nosec
+ 'item_code': item_code,
+ 'today': today(),
+ 'warehouses': from_warehouses
+ }, as_dict=1)
+
+ return batch_locations
+
+def get_available_item_locations_for_other_item(item_code, from_warehouses, required_qty):
+ # gets all items available in different warehouses
+ filters = frappe._dict({
+ 'item_code': item_code,
+ 'actual_qty': ['>', 0]
+ })
+
+ if from_warehouses:
+ filters.warehouse = ['in', from_warehouses]
+
+ item_locations = frappe.get_all('Bin',
+ fields=['warehouse', 'actual_qty as qty'],
+ filters=filters,
+ limit=required_qty,
+ order_by='creation')
+
+ return item_locations
+
+
+@frappe.whitelist()
+def create_delivery_note(source_name, target_doc=None):
+ pick_list = frappe.get_doc('Pick List', source_name)
+ sales_orders = [d.sales_order for d in pick_list.locations]
+ sales_orders = set(sales_orders)
+
+ delivery_note = None
+ for sales_order in sales_orders:
+ delivery_note = create_delivery_note_from_sales_order(sales_order,
+ delivery_note, skip_item_mapping=True)
+
+ item_table_mapper = {
+ 'doctype': 'Delivery Note Item',
+ 'field_map': {
+ 'rate': 'rate',
+ 'name': 'so_detail',
+ 'parent': 'against_sales_order',
+ },
+ 'condition': lambda doc: abs(doc.delivered_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1
+ }
+
+ for location in pick_list.locations:
+ sales_order_item = frappe.get_cached_doc('Sales Order Item', location.sales_order_item)
+ dn_item = map_child_doc(sales_order_item, delivery_note, item_table_mapper)
+
+ if dn_item:
+ dn_item.warehouse = location.warehouse
+ dn_item.qty = location.picked_qty
+ dn_item.batch_no = location.batch_no
+ dn_item.serial_no = location.serial_no
+
+ update_delivery_note_item(sales_order_item, dn_item, delivery_note)
+
+ set_delivery_note_missing_values(delivery_note)
+
+ delivery_note.pick_list = pick_list.name
+
+ return delivery_note
+
+@frappe.whitelist()
+def create_stock_entry(pick_list):
+ pick_list = frappe.get_doc(json.loads(pick_list))
+
+ if stock_entry_exists(pick_list.get('name')):
+ return frappe.msgprint(_('Stock Entry has been already created against this Pick List'))
+
+ stock_entry = frappe.new_doc('Stock Entry')
+ stock_entry.pick_list = pick_list.get('name')
+ stock_entry.purpose = pick_list.get('purpose')
+ stock_entry.set_stock_entry_type()
+
+ if pick_list.get('work_order'):
+ stock_entry = update_stock_entry_based_on_work_order(pick_list, stock_entry)
+ elif pick_list.get('material_request'):
+ stock_entry = update_stock_entry_based_on_material_request(pick_list, stock_entry)
+ else:
+ stock_entry = update_stock_entry_items_with_no_reference(pick_list, stock_entry)
+
+ stock_entry.set_incoming_rate()
+ stock_entry.set_actual_qty()
+ stock_entry.calculate_rate_and_amount(update_finished_item_rate=False)
+
+ return stock_entry.as_dict()
+
+@frappe.whitelist()
+def get_pending_work_orders(doctype, txt, searchfield, start, page_length, filters, as_dict):
+ return frappe.db.sql("""
+ SELECT
+ `name`, `company`, `planned_start_date`
+ FROM
+ `tabWork Order`
+ WHERE
+ `status` not in ('Completed', 'Stopped')
+ AND `qty` > `material_transferred_for_manufacturing`
+ AND `docstatus` = 1
+ AND `company` = %(company)s
+ AND `name` like %(txt)s
+ ORDER BY
+ if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999), name
+ LIMIT
+ %(start)s, %(page_length)s""",
+ {
+ 'txt': "%%%s%%" % txt,
+ '_txt': txt.replace('%', ''),
+ 'start': start,
+ 'page_length': frappe.utils.cint(page_length),
+ 'company': filters.get('company')
+ }, as_dict=as_dict)
+
+@frappe.whitelist()
+def target_document_exists(pick_list_name, purpose):
+ if purpose == 'Delivery against Sales Order':
+ return frappe.db.exists('Delivery Note', {
+ 'pick_list': pick_list_name
+ })
+
+ return stock_entry_exists(pick_list_name)
+
+@frappe.whitelist()
+def get_item_details(item_code, uom=None):
+ details = frappe.db.get_value('Item', item_code, ['stock_uom', 'name'], as_dict=1)
+ details.uom = uom or details.stock_uom
+ if uom:
+ details.update(get_conversion_factor(item_code, uom))
+
+ return details
+
+
+def update_delivery_note_item(source, target, delivery_note):
+ cost_center = frappe.db.get_value('Project', delivery_note.project, 'cost_center')
+ if not cost_center:
+ cost_center = get_cost_center(source.item_code, 'Item', delivery_note.company)
+
+ if not cost_center:
+ cost_center = get_cost_center(source.item_group, 'Item Group', delivery_note.company)
+
+ target.cost_center = cost_center
+
+def get_cost_center(for_item, from_doctype, company):
+ '''Returns Cost Center for Item or Item Group'''
+ return frappe.db.get_value('Item Default',
+ fieldname=['buying_cost_center'],
+ filters={
+ 'parent': for_item,
+ 'parenttype': from_doctype,
+ 'company': company
+ })
+
+def set_delivery_note_missing_values(target):
+ target.run_method('set_missing_values')
+ target.run_method('set_po_nos')
+ target.run_method('calculate_taxes_and_totals')
+
+def stock_entry_exists(pick_list_name):
+ return frappe.db.exists('Stock Entry', {
+ 'pick_list': pick_list_name
+ })
+
+def update_stock_entry_based_on_work_order(pick_list, stock_entry):
+ work_order = frappe.get_doc("Work Order", pick_list.get('work_order'))
+
+ stock_entry.work_order = work_order.name
+ stock_entry.company = work_order.company
+ stock_entry.from_bom = 1
+ stock_entry.bom_no = work_order.bom_no
+ stock_entry.use_multi_level_bom = work_order.use_multi_level_bom
+ stock_entry.fg_completed_qty = pick_list.for_qty
+ if work_order.bom_no:
+ stock_entry.inspection_required = frappe.db.get_value('BOM',
+ work_order.bom_no, 'inspection_required')
+
+ is_wip_warehouse_group = frappe.db.get_value('Warehouse', work_order.wip_warehouse, 'is_group')
+ if not (is_wip_warehouse_group and work_order.skip_transfer):
+ wip_warehouse = work_order.wip_warehouse
+ else:
+ wip_warehouse = None
+ stock_entry.to_warehouse = wip_warehouse
+
+ stock_entry.project = work_order.project
+
+ for location in pick_list.locations:
+ item = frappe._dict()
+ update_common_item_properties(item, location)
+ item.t_warehouse = wip_warehouse
+
+ stock_entry.append('items', item)
+
+ return stock_entry
+
+def update_stock_entry_based_on_material_request(pick_list, stock_entry):
+ for location in pick_list.locations:
+ target_warehouse = None
+ if location.material_request_item:
+ target_warehouse = frappe.get_value('Material Request Item',
+ location.material_request_item, 'warehouse')
+ item = frappe._dict()
+ update_common_item_properties(item, location)
+ item.t_warehouse = target_warehouse
+ stock_entry.append('items', item)
+
+ return stock_entry
+
+def update_stock_entry_items_with_no_reference(pick_list, stock_entry):
+ for location in pick_list.locations:
+ item = frappe._dict()
+ update_common_item_properties(item, location)
+
+ stock_entry.append('items', item)
+
+ return stock_entry
+
+def update_common_item_properties(item, location):
+ item.item_code = location.item_code
+ item.s_warehouse = location.warehouse
+ item.qty = location.picked_qty * location.conversion_factor
+ item.transfer_qty = location.picked_qty
+ item.uom = location.uom
+ item.conversion_factor = location.conversion_factor
+ item.stock_uom = location.stock_uom
+ item.material_request = location.material_request
+ item.serial_no = location.serial_no
+ item.batch_no = location.batch_no
+ item.material_request_item = location.material_request_item
\ No newline at end of file
diff --git a/erpnext/stock/doctype/pick_list/pick_list_dashboard.py b/erpnext/stock/doctype/pick_list/pick_list_dashboard.py
new file mode 100644
index 0000000..6e007df
--- /dev/null
+++ b/erpnext/stock/doctype/pick_list/pick_list_dashboard.py
@@ -0,0 +1,12 @@
+from __future__ import unicode_literals
+from frappe import _
+
+def get_data():
+ return {
+ 'fieldname': 'pick_list',
+ 'transactions': [
+ {
+ 'items': ['Stock Entry', 'Delivery Note']
+ },
+ ]
+ }
\ No newline at end of file
diff --git a/erpnext/stock/doctype/pick_list/test_pick_list.py b/erpnext/stock/doctype/pick_list/test_pick_list.py
new file mode 100644
index 0000000..6b4f73b
--- /dev/null
+++ b/erpnext/stock/doctype/pick_list/test_pick_list.py
@@ -0,0 +1,220 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+import frappe
+import unittest
+test_dependencies = ['Item', 'Sales Invoice', 'Stock Entry', 'Batch']
+
+from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation \
+ import EmptyStockReconciliationItemsError
+
+class TestPickList(unittest.TestCase):
+
+ def test_pick_list_picks_warehouse_for_each_item(self):
+ try:
+ frappe.get_doc({
+ 'doctype': 'Stock Reconciliation',
+ 'company': '_Test Company',
+ 'purpose': 'Opening Stock',
+ 'expense_account': 'Temporary Opening - _TC',
+ 'items': [{
+ 'item_code': '_Test Item Home Desktop 100',
+ 'warehouse': '_Test Warehouse - _TC',
+ 'valuation_rate': 100,
+ 'qty': 5
+ }]
+ }).submit()
+ except EmptyStockReconciliationItemsError:
+ pass
+
+ pick_list = frappe.get_doc({
+ 'doctype': 'Pick List',
+ 'company': '_Test Company',
+ 'customer': '_Test Customer',
+ 'items_based_on': 'Sales Order',
+ 'locations': [{
+ 'item_code': '_Test Item Home Desktop 100',
+ 'qty': 5,
+ 'stock_qty': 5,
+ 'conversion_factor': 1,
+ 'sales_order': '_T-Sales Order-1',
+ 'sales_order_item': '_T-Sales Order-1_item',
+ }]
+ })
+ pick_list.set_item_locations()
+
+ self.assertEqual(pick_list.locations[0].item_code, '_Test Item Home Desktop 100')
+ self.assertEqual(pick_list.locations[0].warehouse, '_Test Warehouse - _TC')
+ self.assertEqual(pick_list.locations[0].qty, 5)
+
+ def test_pick_list_splits_row_according_to_warhouse_availability(self):
+ try:
+ frappe.get_doc({
+ 'doctype': 'Stock Reconciliation',
+ 'company': '_Test Company',
+ 'purpose': 'Opening Stock',
+ 'expense_account': 'Temporary Opening - _TC',
+ 'items': [{
+ 'item_code': '_Test Item Warehouse Group Wise Reorder',
+ 'warehouse': '_Test Warehouse Group-C1 - _TC',
+ 'valuation_rate': 100,
+ 'qty': 5
+ }]
+ }).submit()
+ except EmptyStockReconciliationItemsError:
+ pass
+
+ try:
+ frappe.get_doc({
+ 'doctype': 'Stock Reconciliation',
+ 'company': '_Test Company',
+ 'purpose': 'Opening Stock',
+ 'expense_account': 'Temporary Opening - _TC',
+ 'items': [{
+ 'item_code': '_Test Item Warehouse Group Wise Reorder',
+ 'warehouse': '_Test Warehouse 2 - _TC',
+ 'valuation_rate': 400,
+ 'qty': 10
+ }]
+ }).submit()
+ except EmptyStockReconciliationItemsError:
+ pass
+
+ pick_list = frappe.get_doc({
+ 'doctype': 'Pick List',
+ 'company': '_Test Company',
+ 'customer': '_Test Customer',
+ 'items_based_on': 'Sales Order',
+ 'locations': [{
+ 'item_code': '_Test Item Warehouse Group Wise Reorder',
+ 'qty': 1000,
+ 'stock_qty': 1000,
+ 'conversion_factor': 1,
+ 'sales_order': '_T-Sales Order-1',
+ 'sales_order_item': '_T-Sales Order-1_item',
+ }]
+ })
+
+ pick_list.set_item_locations()
+
+ self.assertEqual(pick_list.locations[0].item_code, '_Test Item Warehouse Group Wise Reorder')
+ self.assertEqual(pick_list.locations[0].warehouse, '_Test Warehouse Group-C1 - _TC')
+ self.assertEqual(pick_list.locations[0].qty, 5)
+
+ self.assertEqual(pick_list.locations[1].item_code, '_Test Item Warehouse Group Wise Reorder')
+ self.assertEqual(pick_list.locations[1].warehouse, '_Test Warehouse 2 - _TC')
+ self.assertEqual(pick_list.locations[1].qty, 10)
+
+ def test_pick_list_shows_serial_no_for_serialized_item(self):
+
+ stock_reconciliation = frappe.get_doc({
+ 'doctype': 'Stock Reconciliation',
+ 'company': '_Test Company',
+ 'items': [{
+ 'item_code': '_Test Serialized Item',
+ 'warehouse': '_Test Warehouse - _TC',
+ 'valuation_rate': 100,
+ 'qty': 5,
+ 'serial_no': '123450\n123451\n123452\n123453\n123454'
+ }]
+ })
+
+ stock_reconciliation.submit()
+
+ pick_list = frappe.get_doc({
+ 'doctype': 'Pick List',
+ 'company': '_Test Company',
+ 'customer': '_Test Customer',
+ 'items_based_on': 'Sales Order',
+ 'locations': [{
+ 'item_code': '_Test Serialized Item',
+ 'qty': 1000,
+ 'stock_qty': 1000,
+ 'conversion_factor': 1,
+ 'sales_order': '_T-Sales Order-1',
+ 'sales_order_item': '_T-Sales Order-1_item',
+ }]
+ })
+
+ pick_list.set_item_locations()
+ self.assertEqual(pick_list.locations[0].item_code, '_Test Serialized Item')
+ self.assertEqual(pick_list.locations[0].warehouse, '_Test Warehouse - _TC')
+ self.assertEqual(pick_list.locations[0].qty, 5)
+ self.assertEqual(pick_list.locations[0].serial_no, '123450\n123451\n123452\n123453\n123454')
+
+ def test_pick_list_for_items_from_multiple_sales_orders(self):
+ try:
+ frappe.get_doc({
+ 'doctype': 'Stock Reconciliation',
+ 'company': '_Test Company',
+ 'purpose': 'Opening Stock',
+ 'expense_account': 'Temporary Opening - _TC',
+ 'items': [{
+ 'item_code': '_Test Item Home Desktop 100',
+ 'warehouse': '_Test Warehouse - _TC',
+ 'valuation_rate': 100,
+ 'qty': 10
+ }]
+ }).submit()
+ except EmptyStockReconciliationItemsError:
+ pass
+
+ sales_order = frappe.get_doc({
+ 'doctype': "Sales Order",
+ 'customer': '_Test Customer',
+ 'company': '_Test Company',
+ 'items': [{
+ 'item_code': '_Test Item Home Desktop 100',
+ 'qty': 10,
+ 'delivery_date': frappe.utils.today()
+ }],
+ })
+ sales_order.submit()
+
+ pick_list = frappe.get_doc({
+ 'doctype': 'Pick List',
+ 'company': '_Test Company',
+ 'customer': '_Test Customer',
+ 'items_based_on': 'Sales Order',
+ 'locations': [{
+ 'item_code': '_Test Item Home Desktop 100',
+ 'qty': 5,
+ 'stock_qty': 5,
+ 'conversion_factor': 1,
+ 'sales_order': '_T-Sales Order-1',
+ 'sales_order_item': '_T-Sales Order-1_item',
+ }, {
+ 'item_code': '_Test Item Home Desktop 100',
+ 'qty': 5,
+ 'stock_qty': 5,
+ 'conversion_factor': 1,
+ 'sales_order': sales_order.name,
+ 'sales_order_item': sales_order.items[0].name,
+ }]
+ })
+ pick_list.set_item_locations()
+
+ self.assertEqual(pick_list.locations[0].item_code, '_Test Item Home Desktop 100')
+ self.assertEqual(pick_list.locations[0].warehouse, '_Test Warehouse - _TC')
+ self.assertEqual(pick_list.locations[0].qty, 5)
+ self.assertEqual(pick_list.locations[0].sales_order_item, '_T-Sales Order-1_item')
+
+ self.assertEqual(pick_list.locations[1].item_code, '_Test Item Home Desktop 100')
+ self.assertEqual(pick_list.locations[1].warehouse, '_Test Warehouse - _TC')
+ self.assertEqual(pick_list.locations[1].qty, 5)
+ self.assertEqual(pick_list.locations[1].sales_order_item, sales_order.items[0].name)
+
+
+ # def test_pick_list_skips_items_in_expired_batch(self):
+ # pass
+
+ # def test_pick_list_from_sales_order(self):
+ # pass
+
+ # def test_pick_list_from_work_order(self):
+ # pass
+
+ # def test_pick_list_from_material_request(self):
+ # pass
\ No newline at end of file
diff --git a/erpnext/stock/doctype/pick_list_item/__init__.py b/erpnext/stock/doctype/pick_list_item/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/doctype/pick_list_item/__init__.py
diff --git a/erpnext/stock/doctype/pick_list_item/pick_list_item.json b/erpnext/stock/doctype/pick_list_item/pick_list_item.json
new file mode 100644
index 0000000..c7a35df
--- /dev/null
+++ b/erpnext/stock/doctype/pick_list_item/pick_list_item.json
@@ -0,0 +1,182 @@
+{
+ "creation": "2019-07-11 16:01:22.832885",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "item_code",
+ "item_name",
+ "column_break_2",
+ "description",
+ "section_break_5",
+ "warehouse",
+ "quantity_section",
+ "qty",
+ "stock_qty",
+ "picked_qty",
+ "column_break_11",
+ "uom",
+ "conversion_factor",
+ "stock_uom",
+ "serial_no_and_batch_section",
+ "serial_no",
+ "column_break_20",
+ "batch_no",
+ "column_break_15",
+ "sales_order",
+ "sales_order_item",
+ "material_request",
+ "material_request_item"
+ ],
+ "fields": [
+ {
+ "default": "1",
+ "fieldname": "qty",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Qty"
+ },
+ {
+ "fieldname": "picked_qty",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Picked Qty"
+ },
+ {
+ "fieldname": "warehouse",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Warehouse",
+ "options": "Warehouse",
+ "read_only": 1
+ },
+ {
+ "fetch_from": "item_code.item_name",
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "label": "Item Name",
+ "read_only": 1
+ },
+ {
+ "fetch_from": "item_code.description",
+ "fieldname": "description",
+ "fieldtype": "Text",
+ "label": "Description",
+ "read_only": 1
+ },
+ {
+ "depends_on": "serial_no",
+ "fieldname": "serial_no",
+ "fieldtype": "Small Text",
+ "label": "Serial No"
+ },
+ {
+ "depends_on": "batch_no",
+ "fieldname": "batch_no",
+ "fieldtype": "Link",
+ "label": "Batch No",
+ "options": "Batch"
+ },
+ {
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "section_break_5",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "stock_uom",
+ "fieldtype": "Link",
+ "label": "Stock UOM",
+ "options": "UOM",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_11",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "uom",
+ "fieldtype": "Link",
+ "label": "UOM",
+ "options": "UOM"
+ },
+ {
+ "fieldname": "conversion_factor",
+ "fieldtype": "Float",
+ "label": "UOM Conversion Factor",
+ "read_only": 1
+ },
+ {
+ "fieldname": "stock_qty",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Stock Qty",
+ "read_only": 1
+ },
+ {
+ "fieldname": "item_code",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Item",
+ "options": "Item"
+ },
+ {
+ "fieldname": "quantity_section",
+ "fieldtype": "Section Break",
+ "label": "Quantity"
+ },
+ {
+ "fieldname": "column_break_15",
+ "fieldtype": "Section Break",
+ "label": "Reference"
+ },
+ {
+ "fieldname": "sales_order",
+ "fieldtype": "Link",
+ "label": "Sales Order",
+ "options": "Sales Order",
+ "read_only": 1
+ },
+ {
+ "fieldname": "sales_order_item",
+ "fieldtype": "Data",
+ "label": "Sales Order Item",
+ "read_only": 1
+ },
+ {
+ "fieldname": "serial_no_and_batch_section",
+ "fieldtype": "Section Break",
+ "label": "Serial No and Batch"
+ },
+ {
+ "fieldname": "column_break_20",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "material_request",
+ "fieldtype": "Link",
+ "label": "Material Request",
+ "options": "Material Request",
+ "read_only": 1
+ },
+ {
+ "fieldname": "material_request_item",
+ "fieldtype": "Data",
+ "label": "Material Request Item",
+ "read_only": 1
+ }
+ ],
+ "istable": 1,
+ "modified": "2019-08-29 21:28:39.539007",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Pick List Item",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/pick_list_item/pick_list_item.py b/erpnext/stock/doctype/pick_list_item/pick_list_item.py
new file mode 100644
index 0000000..8797b8d
--- /dev/null
+++ b/erpnext/stock/doctype/pick_list_item/pick_list_item.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class PickListItem(Document):
+ pass
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index d124ae4..ab9311b 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -329,6 +329,11 @@
location = frappe.db.get_value('Serial No', serial_nos[0].name, 'location')
self.assertEquals(location, "Test Location")
+ frappe.db.set_value("Asset", asset, "purchase_receipt", "")
+ frappe.db.set_value("Purchase Receipt Item", pr.items[0].name, "asset", "")
+
+ pr.load_from_db()
+
pr.cancel()
serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name') or []
self.assertEquals(len(serial_nos), 0)
diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.js b/erpnext/stock/doctype/quality_inspection/quality_inspection.js
index aa9854a..22f29e0 100644
--- a/erpnext/stock/doctype/quality_inspection/quality_inspection.js
+++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.js
@@ -39,11 +39,12 @@
query: "erpnext.stock.doctype.quality_inspection.quality_inspection.item_query",
filters: {
"from": doctype,
- "parent": doc.reference_name
+ "parent": doc.reference_name,
+ "inspection_type": doc.inspection_type
}
- }
+ };
}
-}
+},
// Serial No based on item_code
cur_frm.fields_dict['item_serial_no'].get_query = function(doc, cdt, cdn) {
diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
index e0b7382..738c63c 100644
--- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py
+++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
@@ -63,10 +63,12 @@
mcond = get_match_cond(filters["from"])
cond, qi_condition = "", "and (quality_inspection is null or quality_inspection = '')"
- if filters.get('from') in ['Purchase Invoice Item', 'Purchase Receipt Item']:
+ if filters.get('from') in ['Purchase Invoice Item', 'Purchase Receipt Item']\
+ and filters.get("inspection_type") != "In Process":
cond = """and item_code in (select name from `tabItem` where
inspection_required_before_purchase = 1)"""
- elif filters.get('from') in ['Sales Invoice Item', 'Delivery Note Item']:
+ elif filters.get('from') in ['Sales Invoice Item', 'Delivery Note Item']\
+ and filters.get("inspection_type") != "In Process":
cond = """and item_code in (select name from `tabItem` where
inspection_required_before_delivery = 1)"""
elif filters.get('from') == 'Stock Entry Detail':
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json
index ee563cb..7bcefa0 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.json
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.json
@@ -17,6 +17,7 @@
"purchase_order",
"delivery_note_no",
"sales_invoice_no",
+ "pick_list",
"purchase_receipt_no",
"col2",
"posting_date",
@@ -354,6 +355,7 @@
"label": "Scan Barcode"
},
{
+ "allow_bulk_edit": 1,
"fieldname": "items",
"fieldtype": "Table",
"label": "Items",
@@ -613,12 +615,19 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "pick_list",
+ "fieldtype": "Link",
+ "label": "Pick List",
+ "options": "Pick List",
+ "read_only": 1
}
],
"icon": "fa fa-file-text",
"idx": 1,
"is_submittable": 1,
- "modified": "2019-07-14 17:41:39.257508",
+ "modified": "2019-09-09 11:40:05.762003",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index b530332..0825557 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -145,6 +145,10 @@
self.precision("transfer_qty", item))
def update_cost_in_project(self):
+ if (self.work_order and not frappe.db.get_value("Work Order",
+ self.work_order, "update_consumed_material_cost_in_project")):
+ return
+
if self.project:
amount = frappe.db.sql(""" select ifnull(sum(sed.amount), 0)
from
@@ -521,15 +525,21 @@
backflush_raw_materials_based_on = frappe.db.get_single_value("Buying Settings",
"backflush_raw_materials_of_subcontract_based_on")
+ qty_allowance = flt(frappe.db.get_single_value("Buying Settings",
+ "over_transfer_allowance"))
+
if (self.purpose == "Send to Subcontractor" and self.purchase_order and
backflush_raw_materials_based_on == 'BOM'):
purchase_order = frappe.get_doc("Purchase Order", self.purchase_order)
for se_item in self.items:
item_code = se_item.original_item or se_item.item_code
precision = cint(frappe.db.get_default("float_precision")) or 3
- total_allowed = sum([flt(d.required_qty) for d in purchase_order.supplied_items \
+ required_qty = sum([flt(d.required_qty) for d in purchase_order.supplied_items \
if d.rm_item_code == item_code])
- if not total_allowed:
+
+ total_allowed = required_qty + (required_qty * (qty_allowance/100))
+
+ if not required_qty:
frappe.throw(_("Item {0} not found in 'Raw Materials Supplied' table in Purchase Order {1}")
.format(se_item.item_code, self.purchase_order))
total_supplied = frappe.db.sql("""select sum(transfer_qty)
@@ -1106,6 +1116,7 @@
se_child.allow_alternative_item = item_dict[d].get("allow_alternative_item", 0)
se_child.subcontracted_item = item_dict[d].get("main_item_code")
se_child.original_item = item_dict[d].get("original_item")
+ se_child.po_detail = item_dict[d].get("po_detail")
if item_dict[d].get("idx"):
se_child.idx = item_dict[d].get("idx")
@@ -1157,7 +1168,14 @@
where po.name = poitemsup.parent
and po.name = %s""", self.purchase_order))
- #Update reserved sub contracted quantity in bin based on Supplied Item Details
+ #Update Supplied Qty in PO Supplied Items
+
+ frappe.db.sql("""UPDATE `tabPurchase Order Item Supplied` pos
+ SET pos.supplied_qty = (SELECT ifnull(sum(transfer_qty), 0) FROM `tabStock Entry Detail` sed
+ WHERE pos.name = sed.po_detail and sed.docstatus = 1)
+ WHERE pos.docstatus = 1 and pos.parent = %s""", self.purchase_order)
+
+ #Update reserved sub contracted quantity in bin based on Supplied Item Details and
for d in self.get("items"):
item_code = d.get('original_item') or d.get('item_code')
reserve_warehouse = item_wh.get(item_code)
diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
index 912a465..d86e68b 100644
--- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
+++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
@@ -59,6 +59,7 @@
"reference_section",
"against_stock_entry",
"ste_detail",
+ "po_detail",
"column_break_51",
"transferred_qty",
"reference_purchase_receipt",
@@ -480,11 +481,20 @@
"label": "Project",
"options": "Project",
"read_only": 1
+ },
+ {
+ "fieldname": "po_detail",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "PO Supplied Item",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
}
],
"idx": 1,
"istable": 1,
- "modified": "2019-07-12 11:34:53.190749",
+ "modified": "2019-08-20 14:01:02.319754",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry Detail",
diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
index ededc4d..cd05929 100644
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
@@ -152,7 +152,6 @@
for d in to_delete_records:
stock_doc = frappe.get_doc("Stock Reconciliation", d)
stock_doc.cancel()
- frappe.delete_doc("Stock Reconciliation", stock_doc.name)
for d in serial_nos + serial_nos1:
if frappe.db.exists("Serial No", d):
@@ -203,9 +202,6 @@
stock_doc = frappe.get_doc("Stock Reconciliation", d)
stock_doc.cancel()
- frappe.delete_doc("Batch", sr.items[0].batch_no)
- for d in to_delete_records:
- frappe.delete_doc("Stock Reconciliation", d)
def insert_existing_sle():
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index f1d784c..35c0bb6 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -22,7 +22,7 @@
purchase_doctypes = ['Material Request', 'Supplier Quotation', 'Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
@frappe.whitelist()
-def get_item_details(args, doc=None):
+def get_item_details(args, doc=None, overwrite_warehouse=True):
"""
args = {
"item_code": "",
@@ -44,11 +44,12 @@
"set_warehouse": ""
}
"""
+
args = process_args(args)
item = frappe.get_cached_doc("Item", args.item_code)
validate_item_details(args, item)
- out = get_basic_details(args, item)
+ out = get_basic_details(args, item, overwrite_warehouse)
get_item_tax_template(args, item, out)
out["item_tax_rate"] = get_item_tax_map(args.company, args.get("item_tax_template") if out.get("item_tax_template") is None \
@@ -178,7 +179,7 @@
throw(_("Item {0} must be a Sub-contracted Item").format(item.name))
-def get_basic_details(args, item):
+def get_basic_details(args, item, overwrite_warehouse=True):
"""
:param args: {
"item_code": "",
@@ -225,14 +226,26 @@
item_group_defaults = get_item_group_defaults(item.name, args.company)
brand_defaults = get_brand_defaults(item.name, args.company)
- warehouse = (args.get("set_warehouse") or item_defaults.get("default_warehouse") or
- item_group_defaults.get("default_warehouse") or brand_defaults.get("default_warehouse") or args.warehouse)
+ if overwrite_warehouse or not args.warehouse:
+ warehouse = (
+ args.get("set_warehouse") or
+ item_defaults.get("default_warehouse") or
+ item_group_defaults.get("default_warehouse") or
+ brand_defaults.get("default_warehouse") or
+ args.warehouse
+ )
- if not warehouse:
- defaults = frappe.defaults.get_defaults() or {}
- if defaults.get("default_warehouse") and frappe.db.exists("Warehouse",
- {'name': defaults.default_warehouse, 'company': args.company}):
- warehouse = defaults.default_warehouse
+ if not warehouse:
+ defaults = frappe.defaults.get_defaults() or {}
+ warehouse_exists = frappe.db.exists("Warehouse", {
+ 'name': defaults.default_warehouse,
+ 'company': args.company
+ })
+ if defaults.get("default_warehouse") and warehouse_exists:
+ warehouse = defaults.default_warehouse
+
+ else:
+ warehouse = args.warehouse
if args.get('doctype') == "Material Request" and not args.get('material_request_type'):
args['material_request_type'] = frappe.db.get_value('Material Request',
@@ -626,7 +639,7 @@
if not frappe.db.get_value("Price List",
{"name": args.price_list, args.transaction_type: 1, "enabled": 1}):
throw(_("Price List {0} is disabled or does not exist").format(args.price_list))
- elif not args.get("supplier"):
+ elif args.get("customer"):
throw(_("Price List not selected"))
def validate_conversion_rate(args, meta):
diff --git a/erpnext/stock/print_format/__init__.py b/erpnext/stock/print_format/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/print_format/__init__.py
diff --git a/erpnext/stock/print_format/pick_list/__init__.py b/erpnext/stock/print_format/pick_list/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/print_format/pick_list/__init__.py
diff --git a/erpnext/stock/print_format/pick_list/pick_list.json b/erpnext/stock/print_format/pick_list/pick_list.json
new file mode 100644
index 0000000..0e88d24
--- /dev/null
+++ b/erpnext/stock/print_format/pick_list/pick_list.json
@@ -0,0 +1,23 @@
+{
+ "align_labels_right": 1,
+ "creation": "2019-08-02 07:27:42.533305",
+ "custom_format": 0,
+ "disabled": 0,
+ "doc_type": "Pick List",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "format_data": "[{\"fieldname\": \"print_heading_template\", \"fieldtype\": \"Custom HTML\", \"options\": \"<div class=\\\"print-heading\\\">\\t\\t\\t\\t<h2>Pick List<br><small>{{ doc.name }}</small>\\t\\t\\t\\t</h2></div>\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"company\", \"label\": \"Company\"}, {\"print_hide\": 0, \"fieldname\": \"customer\", \"label\": \"Customer\"}, {\"fieldtype\": \"Column Break\"}, {\"print_hide\": 0, \"fieldname\": \"purpose\", \"label\": \"Purpose\"}, {\"fieldtype\": \"Section Break\", \"label\": \"\"}, {\"fieldtype\": \"Column Break\"}, {\"visible_columns\": [{\"print_hide\": 0, \"fieldname\": \"item_name\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"warehouse\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"stock_qty\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"serial_no\", \"print_width\": \"\"}, {\"print_hide\": 0, \"fieldname\": \"batch_no\", \"print_width\": \"\"}], \"print_hide\": 0, \"fieldname\": \"locations\", \"label\": \"Item Locations\"}]",
+ "idx": 0,
+ "line_breaks": 1,
+ "modified": "2019-08-30 15:58:27.807219",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Pick List",
+ "owner": "Administrator",
+ "print_format_builder": 1,
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
+ "show_section_headings": 1,
+ "standard": "Yes"
+}
\ No newline at end of file
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 5fda2a4..69a4b94 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -181,10 +181,7 @@
# rounding as per precision
self.stock_value = flt(self.stock_value, self.precision)
- if self.prev_stock_value < 0 and self.stock_value >= 0 and sle.voucher_type != 'Stock Reconciliation':
- stock_value_difference = sle.actual_qty * self.valuation_rate
- else:
- stock_value_difference = self.stock_value - self.prev_stock_value
+ stock_value_difference = self.stock_value - self.prev_stock_value
self.prev_stock_value = self.stock_value
@@ -227,9 +224,9 @@
elif actual_qty < 0:
# In case of delivery/stock issue, get average purchase rate
# of serial nos of current entry
- stock_value_change = -1 * flt(frappe.db.sql("""select sum(purchase_rate)
- from `tabSerial No` where name in (%s)""" % (", ".join(["%s"]*len(serial_no))),
- tuple(serial_no))[0][0])
+ stock_value_change = -1 * flt(frappe.get_all("Serial No",
+ fields=["sum(purchase_rate)"],
+ filters = {'name': ('in', serial_no)}, as_list=1)[0][0])
new_stock_qty = self.qty_after_transaction + actual_qty
@@ -464,16 +461,22 @@
last_valuation_rate = frappe.db.sql("""select valuation_rate
from `tabStock Ledger Entry`
- where item_code = %s and warehouse = %s
- and valuation_rate >= 0
- order by posting_date desc, posting_time desc, creation desc limit 1""", (item_code, warehouse))
+ where
+ item_code = %s
+ AND warehouse = %s
+ AND valuation_rate >= 0
+ AND NOT (voucher_no = %s AND voucher_type = %s)
+ order by posting_date desc, posting_time desc, name desc limit 1""", (item_code, warehouse, voucher_no, voucher_type))
if not last_valuation_rate:
# Get valuation rate from last sle for the item against any warehouse
last_valuation_rate = frappe.db.sql("""select valuation_rate
from `tabStock Ledger Entry`
- where item_code = %s and valuation_rate > 0
- order by posting_date desc, posting_time desc, creation desc limit 1""", item_code)
+ where
+ item_code = %s
+ AND valuation_rate > 0
+ AND NOT(voucher_no = %s AND voucher_type = %s)
+ order by posting_date desc, posting_time desc, name desc limit 1""", (item_code, voucher_no, voucher_type))
if last_valuation_rate:
return flt(last_valuation_rate[0][0]) # as there is previous records, it might come with zero rate
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 6ea3228..aec37d4 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -15,7 +15,7 @@
values = {}
conditions = ""
if warehouse:
- conditions += """ and warehouse in (
+ conditions += """ and `tabBin`.warehouse in (
select w2.name from `tabWarehouse` w1
join `tabWarehouse` w2 on
w1.name = %(warehouse)s
@@ -25,11 +25,12 @@
values['warehouse'] = warehouse
if item_code:
- conditions += " and item_code = %(item_code)s"
+ conditions += " and `tabBin`.item_code = %(item_code)s"
values['item_code'] = item_code
- query = "select sum(stock_value) from `tabBin` where 1 = 1 %s" % conditions
+ query = """select sum(stock_value) from `tabBin`, `tabItem` where 1 = 1
+ and `tabItem`.name = `tabBin`.item_code and ifnull(`tabItem`.disabled, 0) = 0 %s""" % conditions
stock_value = frappe.db.sql(query, values)
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index aec9db9..bad40cc 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -107,7 +107,7 @@
}, () => {
reset_sla.enable_primary_action();
frm.refresh();
- frappe.msgprint(__("Service Level Agreement Reset."));
+ frappe.msgprint(__("Service Level Agreement was reset."));
});
}
});
diff --git a/erpnext/support/doctype/issue/issue.json b/erpnext/support/doctype/issue/issue.json
index 1e5d5f9..222554b 100644
--- a/erpnext/support/doctype/issue/issue.json
+++ b/erpnext/support/doctype/issue/issue.json
@@ -1,384 +1,392 @@
{
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "naming_series:",
- "creation": "2013-02-01 10:36:25",
- "doctype": "DocType",
- "document_type": "Setup",
- "engine": "InnoDB",
- "field_order": [
- "subject_section",
- "naming_series",
- "subject",
- "customer",
- "raised_by",
- "cb00",
- "status",
- "priority",
- "issue_type",
- "sb_details",
- "description",
- "service_level_section",
- "service_level_agreement",
- "response_by",
- "response_by_variance",
- "reset_service_level_agreement",
- "cb",
- "agreement_fulfilled",
- "resolution_by",
- "resolution_by_variance",
- "service_level_agreement_creation",
- "response",
- "mins_to_first_response",
- "first_responded_on",
- "additional_info",
- "lead",
- "contact",
- "email_account",
- "column_break_16",
- "customer_name",
- "project",
- "company",
- "section_break_19",
- "resolution_details",
- "column_break1",
- "opening_date",
- "opening_time",
- "resolution_date",
- "content_type",
- "attachment",
- "via_customer_portal"
- ],
- "fields": [
- {
- "fieldname": "subject_section",
- "fieldtype": "Section Break",
- "label": "Subject",
- "options": "fa fa-flag"
- },
- {
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "label": "Series",
- "no_copy": 1,
- "options": "ISS-.YYYY.-",
- "print_hide": 1,
- "set_only_once": 1
- },
- {
- "bold": 1,
- "fieldname": "subject",
- "fieldtype": "Data",
- "in_global_search": 1,
- "in_standard_filter": 1,
- "label": "Subject",
- "reqd": 1
- },
- {
- "fieldname": "customer",
- "fieldtype": "Link",
- "in_global_search": 1,
- "label": "Customer",
- "oldfieldname": "customer",
- "oldfieldtype": "Link",
- "options": "Customer",
- "print_hide": 1,
- "search_index": 1
- },
- {
- "bold": 1,
- "depends_on": "eval:doc.__islocal",
- "fieldname": "raised_by",
- "fieldtype": "Data",
- "in_global_search": 1,
- "in_list_view": 1,
- "label": "Raised By (Email)",
- "oldfieldname": "raised_by",
- "oldfieldtype": "Data",
- "options": "Email"
- },
- {
- "fieldname": "cb00",
- "fieldtype": "Column Break"
- },
- {
- "default": "Open",
- "fieldname": "status",
- "fieldtype": "Select",
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Status",
- "no_copy": 1,
- "oldfieldname": "status",
- "oldfieldtype": "Select",
- "options": "Open\nReplied\nHold\nClosed",
- "search_index": 1
- },
- {
- "default": "Medium",
- "fieldname": "priority",
- "fieldtype": "Link",
- "in_standard_filter": 1,
- "label": "Priority",
- "options": "Issue Priority"
- },
- {
- "fieldname": "issue_type",
- "fieldtype": "Link",
- "label": "Issue Type",
- "options": "Issue Type"
- },
- {
- "collapsible": 1,
- "collapsible_depends_on": "eval:doc.status!=\"Closed\"",
- "fieldname": "sb_details",
- "fieldtype": "Section Break",
- "label": "Details"
- },
- {
- "bold": 1,
- "fieldname": "description",
- "fieldtype": "Text Editor",
- "in_global_search": 1,
- "label": "Description",
- "oldfieldname": "problem_description",
- "oldfieldtype": "Text"
- },
- {
- "collapsible": 1,
- "fieldname": "service_level_section",
- "fieldtype": "Section Break",
- "label": "Service Level"
- },
- {
- "fieldname": "service_level_agreement",
- "fieldtype": "Link",
- "label": "Service Level Agreement",
- "options": "Service Level Agreement"
- },
- {
- "fieldname": "response_by",
- "fieldtype": "Datetime",
- "label": "Response By",
- "read_only": 1
- },
- {
- "collapsible": 1,
- "fieldname": "cb",
- "fieldtype": "Column Break",
- "options": "fa fa-pushpin",
- "read_only": 1
- },
- {
- "fieldname": "resolution_by",
- "fieldtype": "Datetime",
- "label": "Resolution By",
- "read_only": 1
- },
- {
- "collapsible": 1,
- "fieldname": "response",
- "fieldtype": "Section Break",
- "label": "Response"
- },
- {
- "bold": 1,
- "fieldname": "mins_to_first_response",
- "fieldtype": "Float",
- "label": "Mins to First Response",
- "read_only": 1
- },
- {
- "fieldname": "first_responded_on",
- "fieldtype": "Datetime",
- "label": "First Responded On"
- },
- {
- "collapsible": 1,
- "fieldname": "additional_info",
- "fieldtype": "Section Break",
- "label": "Reference",
- "options": "fa fa-pushpin",
- "read_only": 1
- },
- {
- "fieldname": "lead",
- "fieldtype": "Link",
- "label": "Lead",
- "options": "Lead"
- },
- {
- "fieldname": "contact",
- "fieldtype": "Link",
- "label": "Contact",
- "options": "Contact"
- },
- {
- "fieldname": "email_account",
- "fieldtype": "Link",
- "label": "Email Account",
- "options": "Email Account"
- },
- {
- "fieldname": "column_break_16",
- "fieldtype": "Column Break"
- },
- {
- "bold": 1,
- "fieldname": "customer_name",
- "fieldtype": "Data",
- "label": "Customer Name",
- "oldfieldname": "customer_name",
- "oldfieldtype": "Data",
- "read_only": 1
- },
- {
- "fieldname": "project",
- "fieldtype": "Link",
- "label": "Project",
- "options": "Project"
- },
- {
- "fieldname": "company",
- "fieldtype": "Link",
- "label": "Company",
- "options": "Company",
- "print_hide": 1
- },
- {
- "collapsible": 1,
- "fieldname": "section_break_19",
- "fieldtype": "Section Break",
- "label": "Resolution"
- },
- {
- "depends_on": "eval:!doc.__islocal",
- "fieldname": "resolution_details",
- "fieldtype": "Text Editor",
- "label": "Resolution Details",
- "no_copy": 1,
- "oldfieldname": "resolution_details",
- "oldfieldtype": "Text"
- },
- {
- "depends_on": "eval:!doc.__islocal",
- "fieldname": "column_break1",
- "fieldtype": "Column Break",
- "oldfieldtype": "Column Break",
- "read_only": 1
- },
- {
- "default": "Today",
- "fieldname": "opening_date",
- "fieldtype": "Date",
- "label": "Opening Date",
- "no_copy": 1,
- "oldfieldname": "opening_date",
- "oldfieldtype": "Date",
- "read_only": 1
- },
- {
- "fieldname": "opening_time",
- "fieldtype": "Time",
- "label": "Opening Time",
- "no_copy": 1,
- "oldfieldname": "opening_time",
- "oldfieldtype": "Time",
- "read_only": 1
- },
- {
- "depends_on": "eval:!doc.__islocal",
- "fieldname": "resolution_date",
- "fieldtype": "Datetime",
- "label": "Resolution Date",
- "no_copy": 1,
- "oldfieldname": "resolution_date",
- "oldfieldtype": "Date",
- "read_only": 1
- },
- {
- "fieldname": "content_type",
- "fieldtype": "Data",
- "hidden": 1,
- "label": "Content Type"
- },
- {
- "fieldname": "attachment",
- "fieldtype": "Attach",
- "hidden": 1,
- "label": "Attachment"
- },
- {
- "default": "0",
- "fieldname": "via_customer_portal",
- "fieldtype": "Check",
- "label": "Via Customer Portal"
- },
- {
- "default": "Ongoing",
- "depends_on": "eval: doc.service_level_agreement",
- "fieldname": "agreement_fulfilled",
- "fieldtype": "Select",
- "label": "Service Level Agreement Fulfilled",
- "options": "Ongoing\nFulfilled\nFailed",
- "read_only": 1
- },
- {
- "depends_on": "eval: doc.service_level_agreement",
- "description": "in hours",
- "fieldname": "response_by_variance",
- "fieldtype": "Float",
- "label": "Response By Variance",
- "read_only": 1
- },
- {
- "depends_on": "eval: doc.service_level_agreement",
- "description": "in hours",
- "fieldname": "resolution_by_variance",
- "fieldtype": "Float",
- "label": "Resolution By Variance",
- "read_only": 1
- },
- {
- "fieldname": "service_level_agreement_creation",
- "fieldtype": "Datetime",
- "hidden": 1,
- "label": "Service Level Agreement Creation",
- "read_only": 1
- },
- {
- "depends_on": "eval: doc.service_level_agreement",
- "fieldname": "reset_service_level_agreement",
- "fieldtype": "Button",
- "label": "Reset Service Level Agreement"
- }
- ],
- "icon": "fa fa-ticket",
- "idx": 7,
- "modified": "2019-07-11 23:57:22.015881",
- "modified_by": "Administrator",
- "module": "Support",
- "name": "Issue",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Support Team",
- "share": 1,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "search_fields": "status,customer,subject,raised_by",
- "sort_field": "modified",
- "sort_order": "ASC",
- "timeline_field": "customer",
- "title_field": "subject",
- "track_changes": 1,
- "track_seen": 1
- }
\ No newline at end of file
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "naming_series:",
+ "creation": "2013-02-01 10:36:25",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "engine": "InnoDB",
+ "field_order": [
+ "subject_section",
+ "naming_series",
+ "subject",
+ "customer",
+ "raised_by",
+ "cb00",
+ "status",
+ "priority",
+ "issue_type",
+ "issue_split_from",
+ "sb_details",
+ "description",
+ "service_level_section",
+ "service_level_agreement",
+ "response_by",
+ "response_by_variance",
+ "reset_service_level_agreement",
+ "cb",
+ "agreement_fulfilled",
+ "resolution_by",
+ "resolution_by_variance",
+ "service_level_agreement_creation",
+ "response",
+ "mins_to_first_response",
+ "first_responded_on",
+ "additional_info",
+ "lead",
+ "contact",
+ "email_account",
+ "column_break_16",
+ "customer_name",
+ "project",
+ "company",
+ "section_break_19",
+ "resolution_details",
+ "column_break1",
+ "opening_date",
+ "opening_time",
+ "resolution_date",
+ "content_type",
+ "attachment",
+ "via_customer_portal"
+ ],
+ "fields": [
+ {
+ "fieldname": "subject_section",
+ "fieldtype": "Section Break",
+ "label": "Subject",
+ "options": "fa fa-flag"
+ },
+ {
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "no_copy": 1,
+ "options": "ISS-.YYYY.-",
+ "print_hide": 1,
+ "set_only_once": 1
+ },
+ {
+ "bold": 1,
+ "fieldname": "subject",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "in_standard_filter": 1,
+ "label": "Subject",
+ "reqd": 1
+ },
+ {
+ "fieldname": "customer",
+ "fieldtype": "Link",
+ "in_global_search": 1,
+ "label": "Customer",
+ "oldfieldname": "customer",
+ "oldfieldtype": "Link",
+ "options": "Customer",
+ "print_hide": 1,
+ "search_index": 1
+ },
+ {
+ "bold": 1,
+ "depends_on": "eval:doc.__islocal",
+ "fieldname": "raised_by",
+ "fieldtype": "Data",
+ "in_global_search": 1,
+ "in_list_view": 1,
+ "label": "Raised By (Email)",
+ "oldfieldname": "raised_by",
+ "oldfieldtype": "Data",
+ "options": "Email"
+ },
+ {
+ "fieldname": "cb00",
+ "fieldtype": "Column Break"
+ },
+ {
+ "default": "Open",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Status",
+ "no_copy": 1,
+ "oldfieldname": "status",
+ "oldfieldtype": "Select",
+ "options": "Open\nReplied\nHold\nClosed",
+ "search_index": 1
+ },
+ {
+ "default": "Medium",
+ "fieldname": "priority",
+ "fieldtype": "Link",
+ "in_standard_filter": 1,
+ "label": "Priority",
+ "options": "Issue Priority"
+ },
+ {
+ "fieldname": "issue_type",
+ "fieldtype": "Link",
+ "label": "Issue Type",
+ "options": "Issue Type"
+ },
+ {
+ "collapsible": 1,
+ "collapsible_depends_on": "eval:doc.status!=\"Closed\"",
+ "fieldname": "sb_details",
+ "fieldtype": "Section Break",
+ "label": "Details"
+ },
+ {
+ "bold": 1,
+ "fieldname": "description",
+ "fieldtype": "Text Editor",
+ "in_global_search": 1,
+ "label": "Description",
+ "oldfieldname": "problem_description",
+ "oldfieldtype": "Text"
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "service_level_section",
+ "fieldtype": "Section Break",
+ "label": "Service Level"
+ },
+ {
+ "fieldname": "service_level_agreement",
+ "fieldtype": "Link",
+ "label": "Service Level Agreement",
+ "options": "Service Level Agreement"
+ },
+ {
+ "fieldname": "response_by",
+ "fieldtype": "Datetime",
+ "label": "Response By",
+ "read_only": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "cb",
+ "fieldtype": "Column Break",
+ "options": "fa fa-pushpin",
+ "read_only": 1
+ },
+ {
+ "fieldname": "resolution_by",
+ "fieldtype": "Datetime",
+ "label": "Resolution By",
+ "read_only": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "response",
+ "fieldtype": "Section Break",
+ "label": "Response"
+ },
+ {
+ "bold": 1,
+ "fieldname": "mins_to_first_response",
+ "fieldtype": "Float",
+ "label": "Mins to First Response",
+ "read_only": 1
+ },
+ {
+ "fieldname": "first_responded_on",
+ "fieldtype": "Datetime",
+ "label": "First Responded On"
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "additional_info",
+ "fieldtype": "Section Break",
+ "label": "Reference",
+ "options": "fa fa-pushpin",
+ "read_only": 1
+ },
+ {
+ "fieldname": "lead",
+ "fieldtype": "Link",
+ "label": "Lead",
+ "options": "Lead"
+ },
+ {
+ "fieldname": "contact",
+ "fieldtype": "Link",
+ "label": "Contact",
+ "options": "Contact"
+ },
+ {
+ "fieldname": "email_account",
+ "fieldtype": "Link",
+ "label": "Email Account",
+ "options": "Email Account"
+ },
+ {
+ "fieldname": "column_break_16",
+ "fieldtype": "Column Break"
+ },
+ {
+ "bold": 1,
+ "fieldname": "customer_name",
+ "fieldtype": "Data",
+ "label": "Customer Name",
+ "oldfieldname": "customer_name",
+ "oldfieldtype": "Data",
+ "read_only": 1
+ },
+ {
+ "fieldname": "project",
+ "fieldtype": "Link",
+ "label": "Project",
+ "options": "Project"
+ },
+ {
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "options": "Company",
+ "print_hide": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "section_break_19",
+ "fieldtype": "Section Break",
+ "label": "Resolution"
+ },
+ {
+ "depends_on": "eval:!doc.__islocal",
+ "fieldname": "resolution_details",
+ "fieldtype": "Text Editor",
+ "label": "Resolution Details",
+ "no_copy": 1,
+ "oldfieldname": "resolution_details",
+ "oldfieldtype": "Text"
+ },
+ {
+ "depends_on": "eval:!doc.__islocal",
+ "fieldname": "column_break1",
+ "fieldtype": "Column Break",
+ "oldfieldtype": "Column Break",
+ "read_only": 1
+ },
+ {
+ "default": "Today",
+ "fieldname": "opening_date",
+ "fieldtype": "Date",
+ "label": "Opening Date",
+ "no_copy": 1,
+ "oldfieldname": "opening_date",
+ "oldfieldtype": "Date",
+ "read_only": 1
+ },
+ {
+ "fieldname": "opening_time",
+ "fieldtype": "Time",
+ "label": "Opening Time",
+ "no_copy": 1,
+ "oldfieldname": "opening_time",
+ "oldfieldtype": "Time",
+ "read_only": 1
+ },
+ {
+ "depends_on": "eval:!doc.__islocal",
+ "fieldname": "resolution_date",
+ "fieldtype": "Datetime",
+ "label": "Resolution Date",
+ "no_copy": 1,
+ "oldfieldname": "resolution_date",
+ "oldfieldtype": "Date",
+ "read_only": 1
+ },
+ {
+ "fieldname": "content_type",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Content Type"
+ },
+ {
+ "fieldname": "attachment",
+ "fieldtype": "Attach",
+ "hidden": 1,
+ "label": "Attachment"
+ },
+ {
+ "default": "0",
+ "fieldname": "via_customer_portal",
+ "fieldtype": "Check",
+ "label": "Via Customer Portal"
+ },
+ {
+ "default": "Ongoing",
+ "depends_on": "eval: doc.service_level_agreement",
+ "fieldname": "agreement_fulfilled",
+ "fieldtype": "Select",
+ "label": "Service Level Agreement Fulfilled",
+ "options": "Ongoing\nFulfilled\nFailed",
+ "read_only": 1
+ },
+ {
+ "depends_on": "eval: doc.service_level_agreement",
+ "description": "in hours",
+ "fieldname": "response_by_variance",
+ "fieldtype": "Float",
+ "label": "Response By Variance",
+ "read_only": 1
+ },
+ {
+ "depends_on": "eval: doc.service_level_agreement",
+ "description": "in hours",
+ "fieldname": "resolution_by_variance",
+ "fieldtype": "Float",
+ "label": "Resolution By Variance",
+ "read_only": 1
+ },
+ {
+ "fieldname": "service_level_agreement_creation",
+ "fieldtype": "Datetime",
+ "hidden": 1,
+ "label": "Service Level Agreement Creation",
+ "read_only": 1
+ },
+ {
+ "depends_on": "eval: doc.service_level_agreement",
+ "fieldname": "reset_service_level_agreement",
+ "fieldtype": "Button",
+ "label": "Reset Service Level Agreement"
+ },
+ {
+ "fieldname": "issue_split_from",
+ "fieldtype": "Link",
+ "label": "Issue Split From",
+ "options": "Issue",
+ "read_only": 1
+ }
+ ],
+ "icon": "fa fa-ticket",
+ "idx": 7,
+ "modified": "2019-09-11 09:03:57.465623",
+ "modified_by": "himanshu@erpnext.com",
+ "module": "Support",
+ "name": "Issue",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Support Team",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "quick_entry": 1,
+ "search_fields": "status,customer,subject,raised_by",
+ "sort_field": "modified",
+ "sort_order": "ASC",
+ "timeline_field": "customer",
+ "title_field": "subject",
+ "track_changes": 1,
+ "track_seen": 1
+}
\ No newline at end of file
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index 58e2076..b748e3f 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -117,6 +117,9 @@
replicated_issue = deepcopy(self)
replicated_issue.subject = subject
+ replicated_issue.issue_split_from = self.name
+ replicated_issue.mins_to_first_response = 0
+ replicated_issue.first_responded_on = None
replicated_issue.creation = now_datetime()
# Reset SLA
@@ -144,6 +147,14 @@
doc.reference_name = replicated_issue.name
doc.save(ignore_permissions=True)
+ frappe.get_doc({
+ "doctype": "Comment",
+ "comment_type": "Info",
+ "reference_doctype": "Issue",
+ "reference_name": replicated_issue.name,
+ "content": " - Split the Issue from <a href='#Form/Issue/{0}'>{1}</a>".format(self.name, frappe.bold(self.name)),
+ }).insert(ignore_permissions=True)
+
return replicated_issue.name
def before_insert(self):
diff --git a/erpnext/templates/generators/item/item_add_to_cart.html b/erpnext/templates/generators/item/item_add_to_cart.html
index f4a31a7..2a70d8d 100644
--- a/erpnext/templates/generators/item/item_add_to_cart.html
+++ b/erpnext/templates/generators/item/item_add_to_cart.html
@@ -27,6 +27,7 @@
{% endif %}
</div>
{% endif %}
+ {% if product_info.price and (cart_settings.allow_items_not_in_stock or product_info.in_stock) %}
<div class="mt-3">
<a href="/cart"
class="btn btn-light btn-view-in-cart {% if not product_info.qty %}hidden{% endif %}"
@@ -41,6 +42,7 @@
{{ _("Add to Cart") }}
</button>
</div>
+ {% endif %}
</div>
</div>
@@ -64,4 +66,4 @@
});
</script>
-{% endif %}
\ No newline at end of file
+{% endif %}
diff --git a/erpnext/templates/includes/footer/footer_powered.html b/erpnext/templates/includes/footer/footer_powered.html
index faf5e92..d4deaae 100644
--- a/erpnext/templates/includes/footer/footer_powered.html
+++ b/erpnext/templates/includes/footer/footer_powered.html
@@ -1 +1,3 @@
-<a href="https://erpnext.com?source=website_footer" target="_blank" class="text-muted">Powered by ERPNext</a>
+{% set domains = frappe.get_doc("Domain Settings").active_domains %}
+
+<a href="https://erpnext.com?source=website_footer" target="_blank" class="text-muted">Powered by ERPNext - ERP Software {{ ('for ' + domains[0].domain + ' Companies') if domains else '' }}</a>
diff --git a/erpnext/templates/includes/product_page.js b/erpnext/templates/includes/product_page.js
index 65949bb..90a1d86 100644
--- a/erpnext/templates/includes/product_page.js
+++ b/erpnext/templates/includes/product_page.js
@@ -32,7 +32,7 @@
if(r.message.product_info.in_stock===0) {
$(".item-stock").html("<div style='color: red'> <i class='fa fa-close'></i> {{ _("Not in stock") }}</div>");
}
- else if(r.message.product_info.in_stock===1) {
+ else if(r.message.product_info.in_stock===1 && r.message.cart_settings.show_stock_availability) {
var qty_display = "{{ _("In stock") }}";
if (r.message.product_info.show_stock_qty) {
qty_display += " ("+r.message.product_info.stock_qty+")";
diff --git a/erpnext/templates/pages/rfq.py b/erpnext/templates/pages/rfq.py
index 62ec609..67679a1 100644
--- a/erpnext/templates/pages/rfq.py
+++ b/erpnext/templates/pages/rfq.py
@@ -5,8 +5,7 @@
import frappe
from frappe import _
from frappe.utils import formatdate
-from erpnext.controllers.website_list_for_contact import (get_customers_suppliers,
- get_party_details)
+from erpnext.controllers.website_list_for_contact import get_customers_suppliers
def get_context(context):
context.no_cache = 1
@@ -23,8 +22,8 @@
doctype = frappe.form_dict.doctype
parties_doctype = 'Request for Quotation Supplier' if doctype == 'Request for Quotation' else doctype
customers, suppliers = get_customers_suppliers(parties_doctype, frappe.session.user)
- key, parties = get_party_details(customers, suppliers)
- return parties[0] if key == 'supplier' else ''
+
+ return suppliers[0] if suppliers else ''
def check_supplier_has_docname_access(supplier):
status = True