Merge branch 'develop' into remove-nonprofit
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml
index 8f93811..4d61f1f 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yaml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yaml
@@ -40,6 +40,7 @@
- HR
- projects
- support
+ - CRM
- assets
- integrations
- quality
@@ -48,6 +49,7 @@
- agriculture
- education
- non-profit
+ - other
validations:
required: true
diff --git a/.github/labeler.yml b/.github/labeler.yml
new file mode 100644
index 0000000..3aaba71
--- /dev/null
+++ b/.github/labeler.yml
@@ -0,0 +1,55 @@
+accounts:
+- erpnext/accounts/*
+- erpnext/controllers/accounts_controller.py
+- erpnext/controllers/taxes_and_totals.py
+
+stock:
+- erpnext/stock/*
+- erpnext/controllers/stock_controller.py
+- erpnext/controllers/item_variant.py
+
+assets:
+- erpnext/assets/*
+
+regional:
+- erpnext/regional/*
+
+selling:
+- erpnext/selling/*
+- erpnext/controllers/selling_controller.py
+
+buying:
+- erpnext/buying/*
+- erpnext/controllers/buying_controller.py
+
+support:
+- erpnext/support/*
+
+POS:
+- pos*
+
+ecommerce:
+- erpnext/e_commerce/*
+
+maintenance:
+- erpnext/maintenance/*
+
+manufacturing:
+- erpnext/manufacturing/*
+
+crm:
+- erpnext/crm/*
+
+HR:
+- erpnext/hr/*
+
+payroll:
+- erpnext/payroll*
+
+projects:
+- erpnext/projects/*
+
+# Any python files modifed but no test files modified
+needs-tests:
+- any: ['erpnext/**/*.py']
+ all: ['!erpnext/**/test*.py']
diff --git a/.github/workflows/docs-checker.yml b/.github/workflows/docs-checker.yml
index db46c56..b644568 100644
--- a/.github/workflows/docs-checker.yml
+++ b/.github/workflows/docs-checker.yml
@@ -12,7 +12,7 @@
- name: 'Setup Environment'
uses: actions/setup-python@v2
with:
- python-version: 3.6
+ python-version: 3.8
- name: 'Clone repo'
uses: actions/checkout@v2
diff --git a/.github/workflows/labeller.yml b/.github/workflows/labeller.yml
new file mode 100644
index 0000000..a774400
--- /dev/null
+++ b/.github/workflows/labeller.yml
@@ -0,0 +1,12 @@
+name: "Pull Request Labeler"
+on:
+ pull_request_target:
+ types: [opened, reopened]
+
+jobs:
+ triage:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/labeler@v3
+ with:
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.github/workflows/patch.yml b/.github/workflows/patch.yml
index 33a28ac..d05bbbe 100644
--- a/.github/workflows/patch.yml
+++ b/.github/workflows/patch.yml
@@ -34,7 +34,7 @@
- name: Setup Python
uses: actions/setup-python@v2
with:
- python-version: 3.7
+ python-version: 3.8
- name: Setup Node
uses: actions/setup-node@v2
diff --git a/.github/workflows/server-tests-mariadb.yml b/.github/workflows/server-tests-mariadb.yml
index 186f95e..7347a58 100644
--- a/.github/workflows/server-tests-mariadb.yml
+++ b/.github/workflows/server-tests-mariadb.yml
@@ -46,7 +46,7 @@
- name: Setup Python
uses: actions/setup-python@v2
with:
- python-version: 3.7
+ python-version: 3.8
- name: Setup Node
uses: actions/setup-node@v2
diff --git a/.github/workflows/server-tests-postgres.yml b/.github/workflows/server-tests-postgres.yml
index 3bbf6a9..77d3c1a 100644
--- a/.github/workflows/server-tests-postgres.yml
+++ b/.github/workflows/server-tests-postgres.yml
@@ -46,7 +46,7 @@
- name: Setup Python
uses: actions/setup-python@v2
with:
- python-version: 3.7
+ python-version: 3.8
- name: Setup Node
uses: actions/setup-node@v2
diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml
index d765f04..ab6a53b 100644
--- a/.github/workflows/ui-tests.yml
+++ b/.github/workflows/ui-tests.yml
@@ -36,7 +36,7 @@
- name: Setup Python
uses: actions/setup-python@v2
with:
- python-version: 3.7
+ python-version: 3.8
- uses: actions/setup-node@v2
with:
diff --git a/CODEOWNERS b/CODEOWNERS
index a4a14de..bfc2601 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -23,13 +23,13 @@
erpnext/crm/ @ruchamahabal @pateljannat
erpnext/education/ @ruchamahabal @pateljannat
-erpnext/healthcare/ @ruchamahabal @pateljannat @chillaranand
erpnext/hr/ @ruchamahabal @pateljannat
-erpnext/non_profit/ @ruchamahabal
erpnext/payroll @ruchamahabal @pateljannat
erpnext/projects/ @ruchamahabal @pateljannat
-erpnext/controllers @deepeshgarg007 @nextchamp-saqib @rohitwaghchaure @marination
+erpnext/controllers/ @deepeshgarg007 @nextchamp-saqib @rohitwaghchaure @marination @ankush
+erpnext/patches/ @deepeshgarg007 @nextchamp-saqib @marination @ankush
+erpnext/public/ @nextchamp-saqib @marination
-.github/ @surajshetty3416 @ankush
+.github/ @ankush
requirements.txt @gavindsouza
diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py
index 22c81dd..9e2cdff 100644
--- a/erpnext/accounts/deferred_revenue.py
+++ b/erpnext/accounts/deferred_revenue.py
@@ -254,11 +254,13 @@
enable_check = "enable_deferred_revenue" \
if doc.doctype=="Sales Invoice" else "enable_deferred_expense"
+ accounts_frozen_upto = frappe.get_cached_value('Accounts Settings', 'None', 'acc_frozen_upto')
+
def _book_deferred_revenue_or_expense(item, via_journal_entry, submit_journal_entry, book_deferred_entries_based_on):
start_date, end_date, last_gl_entry = get_booking_dates(doc, item, posting_date=posting_date)
if not (start_date and end_date): return
- account_currency = get_account_currency(item.expense_account)
+ account_currency = get_account_currency(item.expense_account or item.income_account)
if doc.doctype == "Sales Invoice":
against, project = doc.customer, doc.project
credit_account, debit_account = item.income_account, item.deferred_revenue_account
@@ -279,6 +281,10 @@
if not amount:
return
+ # check if books nor frozen till endate:
+ if getdate(end_date) >= getdate(accounts_frozen_upto):
+ end_date = get_last_day(add_days(accounts_frozen_upto, 1))
+
if via_journal_entry:
book_revenue_via_journal_entry(doc, credit_account, debit_account, against, amount,
base_amount, end_date, project, account_currency, item.cost_center, item, deferred_process, submit_journal_entry)
@@ -406,8 +412,6 @@
'account': credit_account,
'credit': base_amount,
'credit_in_account_currency': amount,
- 'party_type': 'Customer' if doc.doctype == 'Sales Invoice' else 'Supplier',
- 'party': against,
'account_currency': account_currency,
'reference_name': doc.name,
'reference_type': doc.doctype,
@@ -420,8 +424,6 @@
'account': debit_account,
'debit': base_amount,
'debit_in_account_currency': amount,
- 'party_type': 'Customer' if doc.doctype == 'Sales Invoice' else 'Supplier',
- 'party': against,
'account_currency': account_currency,
'reference_name': doc.name,
'reference_type': doc.doctype,
diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py
index e786d13..1403303 100644
--- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py
+++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py
@@ -16,6 +16,7 @@
from openpyxl.styles import Font
from openpyxl.utils import get_column_letter
+INVALID_VALUES = ("", None)
class BankStatementImport(DataImport):
def __init__(self, *args, **kwargs):
@@ -95,6 +96,18 @@
data_import = frappe.get_doc("Bank Statement Import", data_import_name)
data_import.export_errored_rows()
+def parse_data_from_template(raw_data):
+ data = []
+
+ for i, row in enumerate(raw_data):
+ if all(v in INVALID_VALUES for v in row):
+ # empty row
+ continue
+
+ data.append(row)
+
+ return data
+
def start_import(data_import, bank_account, import_file_path, google_sheets_url, bank, template_options):
"""This method runs in background job"""
@@ -104,7 +117,8 @@
file = import_file_path if import_file_path else google_sheets_url
import_file = ImportFile("Bank Transaction", file = file, import_type="Insert New Records")
- data = import_file.raw_data
+
+ data = parse_data_from_template(import_file.raw_data)
if import_file_path:
add_bank_account(data, bank_account)
diff --git a/erpnext/hotels/doctype/hotel_settings/__init__.py b/erpnext/accounts/doctype/currency_exchange_settings/__init__.py
similarity index 100%
rename from erpnext/hotels/doctype/hotel_settings/__init__.py
rename to erpnext/accounts/doctype/currency_exchange_settings/__init__.py
diff --git a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.js b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.js
new file mode 100644
index 0000000..6c40f2b
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.js
@@ -0,0 +1,45 @@
+// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+frappe.ui.form.on('Currency Exchange Settings', {
+ service_provider: function(frm) {
+ if (frm.doc.service_provider == "exchangerate.host") {
+ let result = ['result'];
+ let params = {
+ date: '{transaction_date}',
+ from: '{from_currency}',
+ to: '{to_currency}'
+ };
+ add_param(frm, "https://api.exchangerate.host/convert", params, result);
+ } else if (frm.doc.service_provider == "frankfurter.app") {
+ let result = ['rates', '{to_currency}'];
+ let params = {
+ base: '{from_currency}',
+ symbols: '{to_currency}'
+ };
+ add_param(frm, "https://frankfurter.app/{transaction_date}", params, result);
+ }
+ }
+});
+
+
+function add_param(frm, api, params, result) {
+ var row;
+ frm.clear_table("req_params");
+ frm.clear_table("result_key");
+
+ frm.doc.api_endpoint = api;
+
+ $.each(params, function(key, value) {
+ row = frm.add_child("req_params");
+ row.key = key;
+ row.value = value;
+ });
+
+ $.each(result, function(key, value) {
+ row = frm.add_child("result_key");
+ row.key = value;
+ });
+
+ frm.refresh_fields();
+}
diff --git a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.json b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.json
new file mode 100644
index 0000000..7921fcc
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.json
@@ -0,0 +1,126 @@
+{
+ "actions": [],
+ "creation": "2022-01-10 13:03:26.237081",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "api_details_section",
+ "service_provider",
+ "api_endpoint",
+ "url",
+ "column_break_3",
+ "help",
+ "section_break_2",
+ "req_params",
+ "column_break_4",
+ "result_key"
+ ],
+ "fields": [
+ {
+ "fieldname": "api_details_section",
+ "fieldtype": "Section Break",
+ "label": "API Details"
+ },
+ {
+ "fieldname": "api_endpoint",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "API Endpoint",
+ "read_only_depends_on": "eval: doc.service_provider != \"Custom\"",
+ "reqd": 1
+ },
+ {
+ "fieldname": "url",
+ "fieldtype": "Data",
+ "label": "Example URL",
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "help",
+ "fieldtype": "HTML",
+ "label": "Help",
+ "options": "<h3>Currency Exchange Settings Help</h3>\n<p>There are 3 variables that could be used within the endpoint, result key and in values of the parameter.</p>\n<p>Exchange rate between {from_currency} and {to_currency} on {transaction_date} is fetched by the API.</p>\n<p>Example: If your endpoint is exchange.com/2021-08-01, then, you will have to input exchange.com/{transaction_date}</p>"
+ },
+ {
+ "fieldname": "section_break_2",
+ "fieldtype": "Section Break",
+ "label": "Request Parameters"
+ },
+ {
+ "fieldname": "req_params",
+ "fieldtype": "Table",
+ "label": "Parameters",
+ "options": "Currency Exchange Settings Details",
+ "read_only_depends_on": "eval: doc.service_provider != \"Custom\"",
+ "reqd": 1
+ },
+ {
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "result_key",
+ "fieldtype": "Table",
+ "label": "Result Key",
+ "options": "Currency Exchange Settings Result",
+ "read_only_depends_on": "eval: doc.service_provider != \"Custom\"",
+ "reqd": 1
+ },
+ {
+ "fieldname": "service_provider",
+ "fieldtype": "Select",
+ "label": "Service Provider",
+ "options": "frankfurter.app\nexchangerate.host\nCustom",
+ "reqd": 1
+ }
+ ],
+ "index_web_pages_for_search": 1,
+ "issingle": 1,
+ "links": [],
+ "modified": "2022-01-10 15:51:14.521174",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Currency Exchange Settings",
+ "owner": "Administrator",
+ "permissions": [
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "role": "System Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "role": "Accounts Manager",
+ "share": 1,
+ "write": 1
+ },
+ {
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "role": "Accounts User",
+ "share": 1,
+ "write": 1
+ }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "states": [],
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py
new file mode 100644
index 0000000..e16ff3a
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.py
@@ -0,0 +1,82 @@
+# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+import frappe
+import requests
+from frappe import _
+from frappe.model.document import Document
+from frappe.utils import nowdate
+
+
+class CurrencyExchangeSettings(Document):
+ def validate(self):
+ self.set_parameters_and_result()
+ response, value = self.validate_parameters()
+ self.validate_result(response, value)
+
+ def set_parameters_and_result(self):
+ if self.service_provider == 'exchangerate.host':
+ self.set('result_key', [])
+ self.set('req_params', [])
+
+ self.api_endpoint = "https://api.exchangerate.host/convert"
+ self.append('result_key', {'key': 'result'})
+ self.append('req_params', {'key': 'date', 'value': '{transaction_date}'})
+ self.append('req_params', {'key': 'from', 'value': '{from_currency}'})
+ self.append('req_params', {'key': 'to', 'value': '{to_currency}'})
+ elif self.service_provider == 'frankfurter.app':
+ self.set('result_key', [])
+ self.set('req_params', [])
+
+ self.api_endpoint = "https://frankfurter.app/{transaction_date}"
+ self.append('result_key', {'key': 'rates'})
+ self.append('result_key', {'key': '{to_currency}'})
+ self.append('req_params', {'key': 'base', 'value': '{from_currency}'})
+ self.append('req_params', {'key': 'symbols', 'value': '{to_currency}'})
+
+ def validate_parameters(self):
+ if frappe.flags.in_test:
+ return None, None
+
+ params = {}
+ for row in self.req_params:
+ params[row.key] = row.value.format(
+ transaction_date=nowdate(),
+ to_currency='INR',
+ from_currency='USD'
+ )
+
+ api_url = self.api_endpoint.format(
+ transaction_date=nowdate(),
+ to_currency='INR',
+ from_currency='USD'
+ )
+
+ try:
+ response = requests.get(api_url, params=params)
+ except requests.exceptions.RequestException as e:
+ frappe.throw("Error: " + str(e))
+
+ response.raise_for_status()
+ value = response.json()
+
+ return response, value
+
+ def validate_result(self, response, value):
+ if frappe.flags.in_test:
+ return
+
+ try:
+ for key in self.result_key:
+ value = value[str(key.key).format(
+ transaction_date=nowdate(),
+ to_currency='INR',
+ from_currency='USD'
+ )]
+ except Exception:
+ frappe.throw("Invalid result key. Response: " + response.text)
+ if not isinstance(value, (int, float)):
+ frappe.throw(_("Returned exchange rate is neither integer not float."))
+
+ self.url = response.url
+ frappe.msgprint("Exchange rate of USD to INR is " + str(value))
diff --git a/erpnext/accounts/doctype/currency_exchange_settings/test_currency_exchange_settings.py b/erpnext/accounts/doctype/currency_exchange_settings/test_currency_exchange_settings.py
new file mode 100644
index 0000000..2778729
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings/test_currency_exchange_settings.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+import unittest
+
+
+class TestCurrencyExchangeSettings(unittest.TestCase):
+ pass
diff --git a/erpnext/hotels/__init__.py b/erpnext/accounts/doctype/currency_exchange_settings_details/__init__.py
similarity index 100%
rename from erpnext/hotels/__init__.py
rename to erpnext/accounts/doctype/currency_exchange_settings_details/__init__.py
diff --git a/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.json b/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.json
new file mode 100644
index 0000000..3093587
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.json
@@ -0,0 +1,39 @@
+{
+ "actions": [],
+ "creation": "2021-09-02 14:54:49.033512",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "key",
+ "value"
+ ],
+ "fields": [
+ {
+ "fieldname": "key",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Key",
+ "reqd": 1
+ },
+ {
+ "fieldname": "value",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Value",
+ "reqd": 1
+ }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-11-03 19:14:55.889037",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Currency Exchange Settings Details",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.py b/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.py
new file mode 100644
index 0000000..a6ad763
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+from frappe.model.document import Document
+
+
+class CurrencyExchangeSettingsDetails(Document):
+ pass
diff --git a/erpnext/hotels/report/__init__.py b/erpnext/accounts/doctype/currency_exchange_settings_result/__init__.py
similarity index 100%
rename from erpnext/hotels/report/__init__.py
rename to erpnext/accounts/doctype/currency_exchange_settings_result/__init__.py
diff --git a/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.json b/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.json
new file mode 100644
index 0000000..fff5337
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.json
@@ -0,0 +1,31 @@
+{
+ "actions": [],
+ "creation": "2021-09-03 13:17:22.088259",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "key"
+ ],
+ "fields": [
+ {
+ "fieldname": "key",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Key",
+ "reqd": 1
+ }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2021-11-03 19:14:40.054245",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Currency Exchange Settings Result",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.py b/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.py
new file mode 100644
index 0000000..1774128
--- /dev/null
+++ b/erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+from frappe.model.document import Document
+
+
+class CurrencyExchangeSettingsResult(Document):
+ pass
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js
index 957a50f..617b376 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.js
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js
@@ -31,7 +31,7 @@
if(frm.doc.docstatus==1) {
frm.add_custom_button(__('Reverse Journal Entry'), function() {
return erpnext.journal_entry.reverse_journal_entry(frm);
- }, __('Make'));
+ }, __('Actions'));
}
if (frm.doc.__islocal) {
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.json b/erpnext/accounts/doctype/journal_entry/journal_entry.json
index 20678d7..335fd35 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.json
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.json
@@ -13,6 +13,7 @@
"voucher_type",
"naming_series",
"finance_book",
+ "reversal_of",
"tax_withholding_category",
"column_break1",
"from_template",
@@ -515,13 +516,21 @@
"fieldname": "apply_tds",
"fieldtype": "Check",
"label": "Apply Tax Withholding Amount "
+ },
+ {
+ "depends_on": "eval:doc.docstatus",
+ "fieldname": "reversal_of",
+ "fieldtype": "Link",
+ "label": "Reversal Of",
+ "options": "Journal Entry",
+ "read_only": 1
}
],
"icon": "fa fa-file-text",
"idx": 176,
"is_submittable": 1,
"links": [],
- "modified": "2021-09-09 15:31:14.484029",
+ "modified": "2022-01-04 13:39:36.485954",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry",
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index ca17265..ac8ab31 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -407,13 +407,14 @@
debit_or_credit = 'Debit' if d.debit else 'Credit'
party_account = get_deferred_booking_accounts(d.reference_type, d.reference_detail_no,
debit_or_credit)
+ against_voucher = ['', against_voucher[1]]
else:
if d.reference_type == "Sales Invoice":
party_account = get_party_account_based_on_invoice_discounting(d.reference_name) or against_voucher[1]
else:
party_account = against_voucher[1]
- if (against_voucher[0] != d.party or party_account != d.account):
+ if (against_voucher[0] != cstr(d.party) or party_account != d.account):
frappe.throw(_("Row {0}: Party / Account does not match with {1} / {2} in {3} {4}")
.format(d.idx, field_dict.get(d.reference_type)[0], field_dict.get(d.reference_type)[1],
d.reference_type, d.reference_name))
@@ -478,13 +479,22 @@
def set_against_account(self):
accounts_debited, accounts_credited = [], []
- for d in self.get("accounts"):
- if flt(d.debit > 0): accounts_debited.append(d.party or d.account)
- if flt(d.credit) > 0: accounts_credited.append(d.party or d.account)
+ if self.voucher_type in ('Deferred Revenue', 'Deferred Expense'):
+ for d in self.get('accounts'):
+ if d.reference_type == 'Sales Invoice':
+ field = 'customer'
+ else:
+ field = 'supplier'
- for d in self.get("accounts"):
- if flt(d.debit > 0): d.against_account = ", ".join(list(set(accounts_credited)))
- if flt(d.credit > 0): d.against_account = ", ".join(list(set(accounts_debited)))
+ d.against_account = frappe.db.get_value(d.reference_type, d.reference_name, field)
+ else:
+ for d in self.get("accounts"):
+ if flt(d.debit > 0): accounts_debited.append(d.party or d.account)
+ if flt(d.credit) > 0: accounts_credited.append(d.party or d.account)
+
+ for d in self.get("accounts"):
+ if flt(d.debit > 0): d.against_account = ", ".join(list(set(accounts_credited)))
+ if flt(d.credit > 0): d.against_account = ", ".join(list(set(accounts_debited)))
def validate_debit_credit_amount(self):
for d in self.get('accounts'):
@@ -1157,9 +1167,8 @@
def make_reverse_journal_entry(source_name, target_doc=None):
from frappe.model.mapper import get_mapped_doc
- def update_accounts(source, target, source_parent):
- target.reference_type = "Journal Entry"
- target.reference_name = source_parent.name
+ def post_process(source, target):
+ target.reversal_of = source.name
doclist = get_mapped_doc("Journal Entry", source_name, {
"Journal Entry": {
@@ -1177,9 +1186,8 @@
"debit": "credit",
"credit_in_account_currency": "debit_in_account_currency",
"credit": "debit",
- },
- "postprocess": update_accounts,
+ }
},
- }, target_doc)
+ }, target_doc, post_process)
return doclist
diff --git a/erpnext/accounts/doctype/party_link/party_link.py b/erpnext/accounts/doctype/party_link/party_link.py
index e9f813c..031a9fa 100644
--- a/erpnext/accounts/doctype/party_link/party_link.py
+++ b/erpnext/accounts/doctype/party_link/party_link.py
@@ -2,7 +2,7 @@
# For license information, please see license.txt
import frappe
-from frappe import _
+from frappe import _, bold
from frappe.model.document import Document
@@ -13,6 +13,17 @@
title=_("Invalid Primary Role"))
existing_party_link = frappe.get_all('Party Link', {
+ 'primary_party': self.primary_party,
+ 'secondary_party': self.secondary_party
+ }, pluck="primary_role")
+ if existing_party_link:
+ frappe.throw(_('{} {} is already linked with {} {}')
+ .format(
+ self.primary_role, bold(self.primary_party),
+ self.secondary_role, bold(self.secondary_party)
+ ))
+
+ existing_party_link = frappe.get_all('Party Link', {
'primary_party': self.secondary_party
}, pluck="primary_role")
if existing_party_link:
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index c1b056b..02a144d 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -3,6 +3,7 @@
import json
+from functools import reduce
import frappe
from frappe import ValidationError, _, scrub, throw
@@ -1523,6 +1524,10 @@
pe.received_amount = received_amount
pe.letter_head = doc.get("letter_head")
+ if dt in ['Purchase Order', 'Sales Order', 'Sales Invoice', 'Purchase Invoice']:
+ pe.project = (doc.get('project') or
+ reduce(lambda prev,cur: prev or cur, [x.get('project') for x in doc.get('items')], None)) # get first non-empty project from items
+
if pe.party_type in ["Customer", "Supplier"]:
bank_account = get_party_bank_account(pe.party_type, pe.party)
pe.set("bank_account", bank_account)
@@ -1708,7 +1713,10 @@
def apply_early_payment_discount(paid_amount, received_amount, doc):
total_discount = 0
- if doc.doctype in ['Sales Invoice', 'Purchase Invoice'] and doc.payment_schedule:
+ eligible_for_payments = ['Sales Order', 'Sales Invoice', 'Purchase Order', 'Purchase Invoice']
+ has_payment_schedule = hasattr(doc, 'payment_schedule') and doc.payment_schedule
+
+ if doc.doctype in eligible_for_payments and has_payment_schedule:
for term in doc.payment_schedule:
if not term.discounted_amount and term.discount and getdate(nowdate()) <= term.discount_date:
if term.discount_type == 'Percentage':
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
index 11d59bc..134bccf 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py
@@ -353,7 +353,6 @@
if not for_validate and not self.customer:
self.customer = profile.customer
- self.ignore_pricing_rule = profile.ignore_pricing_rule
self.account_for_change_amount = profile.get('account_for_change_amount') or self.account_for_change_amount
self.set_warehouse = profile.get('warehouse') or self.set_warehouse
diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
index 7d31e0a..56479a0 100644
--- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
@@ -556,6 +556,37 @@
batch.cancel()
batch.delete()
+ def test_ignore_pricing_rule(self):
+ from erpnext.accounts.doctype.pricing_rule.test_pricing_rule import make_pricing_rule
+
+ item_price = frappe.get_doc({
+ 'doctype': 'Item Price',
+ 'item_code': '_Test Item',
+ 'price_list': '_Test Price List',
+ 'price_list_rate': '450',
+ })
+ item_price.insert()
+ pr = make_pricing_rule(selling=1, priority=5, discount_percentage=10)
+ pr.save()
+ pos_inv = create_pos_invoice(qty=1, do_not_submit=1)
+ pos_inv.items[0].rate = 300
+ pos_inv.save()
+ self.assertEquals(pos_inv.items[0].discount_percentage, 10)
+ # rate shouldn't change
+ self.assertEquals(pos_inv.items[0].rate, 405)
+
+ pos_inv.ignore_pricing_rule = 1
+ pos_inv.items[0].rate = 300
+ pos_inv.save()
+ self.assertEquals(pos_inv.ignore_pricing_rule, 1)
+ # rate should change since pricing rules are ignored
+ self.assertEquals(pos_inv.items[0].rate, 300)
+
+ item_price.delete()
+ pos_inv.delete()
+ pr.delete()
+
+
def create_pos_invoice(**args):
args = frappe._dict(args)
pos_profile = None
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index 314c894..5746a84 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -650,7 +650,7 @@
"rate": args.rate or 0.0,
"margin_rate_or_amount": args.margin_rate_or_amount or 0.0,
"condition": args.condition or '',
- "priority": 1,
+ "priority": args.priority or 1,
"discount_amount": args.discount_amount or 0.0,
"apply_multiple_pricing_rules": args.apply_multiple_pricing_rules or 0
})
@@ -676,6 +676,8 @@
if args.get(applicable_for):
doc.db_set(applicable_for, args.get(applicable_for))
+ return doc
+
def setup_pricing_rule_data():
if not frappe.db.exists('Campaign', '_Test Campaign'):
frappe.get_doc({
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index df957d2..b364218 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -505,11 +505,11 @@
# Checked both rounding_adjustment and rounded_total
# because rounded_total had value even before introcution of posting GLE based on rounded total
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
+ base_grand_total = flt(self.base_rounded_total if (self.base_rounding_adjustment and self.base_rounded_total)
+ else self.base_grand_total, self.precision("base_grand_total"))
if grand_total and not self.is_internal_transfer():
# Did not use base_grand_total to book rounding loss gle
- grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
- self.precision("grand_total"))
gl_entries.append(
self.get_gl_dict({
"account": self.credit_to,
@@ -517,8 +517,8 @@
"party": self.supplier,
"due_date": self.due_date,
"against": self.against_expense_account,
- "credit": grand_total_in_company_currency,
- "credit_in_account_currency": grand_total_in_company_currency \
+ "credit": base_grand_total,
+ "credit_in_account_currency": base_grand_total \
if self.party_account_currency==self.company_currency else grand_total,
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype,
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index 545abf7..5062c1c 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -651,7 +651,7 @@
"hide_seconds": 1,
"label": "Ignore Pricing Rule",
"no_copy": 1,
- "permlevel": 1,
+ "permlevel": 0,
"print_hide": 1
},
{
@@ -2038,7 +2038,7 @@
"link_fieldname": "consolidated_invoice"
}
],
- "modified": "2021-10-21 20:19:38.667508",
+ "modified": "2021-12-23 20:19:38.667508",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 321b453..f04e7ea 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -43,6 +43,7 @@
from erpnext.stock.doctype.batch.batch import set_batch_nos
from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so
from erpnext.stock.doctype.serial_no.serial_no import get_delivery_note_serial_no, get_serial_nos
+from erpnext.stock.utils import calculate_mapped_packed_items_return
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@@ -728,8 +729,11 @@
def update_packing_list(self):
if cint(self.update_stock) == 1:
- from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
- make_packing_list(self)
+ if cint(self.is_return) and self.return_against:
+ calculate_mapped_packed_items_return(self)
+ else:
+ from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
+ make_packing_list(self)
else:
self.set('packed_items', [])
@@ -862,11 +866,11 @@
# Checked both rounding_adjustment and rounded_total
# because rounded_total had value even before introcution of posting GLE based on rounded total
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
+ base_grand_total = flt(self.base_rounded_total if (self.base_rounding_adjustment and self.base_rounded_total)
+ else self.base_grand_total, self.precision("base_grand_total"))
+
if grand_total and not self.is_internal_transfer():
# Didnot use base_grand_total to book rounding loss gle
- grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
- self.precision("grand_total"))
-
gl_entries.append(
self.get_gl_dict({
"account": self.debit_to,
@@ -874,8 +878,8 @@
"party": self.customer,
"due_date": self.due_date,
"against": self.against_income_account,
- "debit": grand_total_in_company_currency,
- "debit_in_account_currency": grand_total_in_company_currency \
+ "debit": base_grand_total,
+ "debit_in_account_currency": base_grand_total \
if self.party_account_currency==self.company_currency else grand_total,
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype,
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index c02c80a..55e3853 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -1781,47 +1781,6 @@
check_gl_entries(self, si.name, expected_gle, "2019-01-30")
- def test_deferred_revenue_post_account_freeze_upto_by_admin(self):
- frappe.set_user("Administrator")
-
- frappe.db.set_value('Accounts Settings', None, 'acc_frozen_upto', None)
- frappe.db.set_value('Accounts Settings', None, 'frozen_accounts_modifier', None)
-
- deferred_account = create_account(account_name="Deferred Revenue",
- parent_account="Current Liabilities - _TC", company="_Test Company")
-
- item = create_item("_Test Item for Deferred Accounting")
- item.enable_deferred_revenue = 1
- item.deferred_revenue_account = deferred_account
- item.no_of_months = 12
- item.save()
-
- si = create_sales_invoice(item=item.name, posting_date="2019-01-10", do_not_save=True)
- si.items[0].enable_deferred_revenue = 1
- si.items[0].service_start_date = "2019-01-10"
- si.items[0].service_end_date = "2019-03-15"
- si.items[0].deferred_revenue_account = deferred_account
- si.save()
- si.submit()
-
- frappe.db.set_value('Accounts Settings', None, 'acc_frozen_upto', getdate('2019-01-31'))
- frappe.db.set_value('Accounts Settings', None, 'frozen_accounts_modifier', 'System Manager')
-
- pda1 = frappe.get_doc(dict(
- doctype='Process Deferred Accounting',
- posting_date=nowdate(),
- start_date="2019-01-01",
- end_date="2019-03-31",
- type="Income",
- company="_Test Company"
- ))
-
- pda1.insert()
- self.assertRaises(frappe.ValidationError, pda1.submit)
-
- frappe.db.set_value('Accounts Settings', None, 'acc_frozen_upto', None)
- frappe.db.set_value('Accounts Settings', None, 'frozen_accounts_modifier', None)
-
def test_fixed_deferred_revenue(self):
deferred_account = create_account(account_name="Deferred Revenue",
parent_account="Current Liabilities - _TC", company="_Test Company")
@@ -2233,9 +2192,9 @@
asset.load_from_db()
expected_values = [
- ["2020-06-30", 1311.48, 1311.48],
- ["2021-06-30", 20000.0, 21311.48],
- ["2021-09-30", 5041.1, 26352.58]
+ ["2020-06-30", 1366.12, 1366.12],
+ ["2021-06-30", 20000.0, 21366.12],
+ ["2021-09-30", 5041.1, 26407.22]
]
for i, schedule in enumerate(asset.schedules):
@@ -2283,12 +2242,12 @@
asset.load_from_db()
expected_values = [
- ["2020-06-30", 1311.48, 1311.48, True],
- ["2021-06-30", 20000.0, 21311.48, True],
- ["2022-06-30", 20000.0, 41311.48, False],
- ["2023-06-30", 20000.0, 61311.48, False],
- ["2024-06-30", 20000.0, 81311.48, False],
- ["2025-06-06", 18688.52, 100000.0, False]
+ ["2020-06-30", 1366.12, 1366.12, True],
+ ["2021-06-30", 20000.0, 21366.12, True],
+ ["2022-06-30", 20000.0, 41366.12, False],
+ ["2023-06-30", 20000.0, 61366.12, False],
+ ["2024-06-30", 20000.0, 81366.12, False],
+ ["2025-06-06", 18633.88, 100000.0, False]
]
for i, schedule in enumerate(asset.schedules):
@@ -2482,6 +2441,74 @@
frappe.db.set_value('Accounts Settings', None, 'over_billing_allowance', over_billing_allowance)
+ def test_multi_currency_deferred_revenue_via_journal_entry(self):
+ deferred_account = create_account(account_name="Deferred Revenue",
+ parent_account="Current Liabilities - _TC", company="_Test Company")
+
+ acc_settings = frappe.get_single('Accounts Settings')
+ acc_settings.book_deferred_entries_via_journal_entry = 1
+ acc_settings.submit_journal_entries = 1
+ acc_settings.save()
+
+ item = create_item("_Test Item for Deferred Accounting")
+ item.enable_deferred_expense = 1
+ item.deferred_revenue_account = deferred_account
+ item.save()
+
+ si = create_sales_invoice(customer='_Test Customer USD', currency='USD',
+ item=item.name, qty=1, rate=100, conversion_rate=60, do_not_save=True)
+
+ si.set_posting_time = 1
+ si.posting_date = '2019-01-01'
+ si.debit_to = '_Test Receivable USD - _TC'
+ si.items[0].enable_deferred_revenue = 1
+ si.items[0].service_start_date = "2019-01-01"
+ si.items[0].service_end_date = "2019-03-30"
+ si.items[0].deferred_expense_account = deferred_account
+ si.save()
+ si.submit()
+
+ frappe.db.set_value('Accounts Settings', None, 'acc_frozen_upto', getdate('2019-01-31'))
+
+ pda1 = frappe.get_doc(dict(
+ doctype='Process Deferred Accounting',
+ posting_date=nowdate(),
+ start_date="2019-01-01",
+ end_date="2019-03-31",
+ type="Income",
+ company="_Test Company"
+ ))
+
+ pda1.insert()
+ pda1.submit()
+
+ expected_gle = [
+ ["Sales - _TC", 0.0, 2089.89, "2019-01-28"],
+ [deferred_account, 2089.89, 0.0, "2019-01-28"],
+ ["Sales - _TC", 0.0, 1887.64, "2019-02-28"],
+ [deferred_account, 1887.64, 0.0, "2019-02-28"],
+ ["Sales - _TC", 0.0, 2022.47, "2019-03-15"],
+ [deferred_account, 2022.47, 0.0, "2019-03-15"]
+ ]
+
+ gl_entries = gl_entries = frappe.db.sql("""select account, debit, credit, posting_date
+ from `tabGL Entry`
+ where voucher_type='Journal Entry' and voucher_detail_no=%s and posting_date <= %s
+ order by posting_date asc, account asc""", (si.items[0].name, si.posting_date), as_dict=1)
+
+ for i, gle in enumerate(gl_entries):
+ self.assertEqual(expected_gle[i][0], gle.account)
+ self.assertEqual(expected_gle[i][1], gle.credit)
+ self.assertEqual(expected_gle[i][2], gle.debit)
+ self.assertEqual(getdate(expected_gle[i][3]), gle.posting_date)
+
+ acc_settings = frappe.get_single('Accounts Settings')
+ acc_settings.book_deferred_entries_via_journal_entry = 0
+ acc_settings.submit_journal_entriessubmit_journal_entries = 0
+ acc_settings.save()
+
+ frappe.db.set_value('Accounts Settings', None, 'acc_frozen_upto', None)
+
def get_sales_invoice_for_e_invoice():
si = make_sales_invoice_for_ewaybill()
si.naming_series = 'INV-2020-.#####'
diff --git a/erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.json b/erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.json
index d2c505c..e032bb3 100644
--- a/erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.json
+++ b/erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.json
@@ -28,14 +28,14 @@
{
"columns": 2,
"fieldname": "single_threshold",
- "fieldtype": "Currency",
+ "fieldtype": "Float",
"in_list_view": 1,
"label": "Single Transaction Threshold"
},
{
"columns": 3,
"fieldname": "cumulative_threshold",
- "fieldtype": "Currency",
+ "fieldtype": "Float",
"in_list_view": 1,
"label": "Cumulative Transaction Threshold"
},
@@ -59,7 +59,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2021-08-31 11:42:12.213977",
+ "modified": "2022-01-13 12:04:42.904263",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Tax Withholding Rate",
@@ -68,5 +68,6 @@
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/form_tour/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json b/erpnext/accounts/form_tour/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json
index 7de9ae1..02e30c3 100644
--- a/erpnext/accounts/form_tour/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json
+++ b/erpnext/accounts/form_tour/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json
@@ -2,15 +2,17 @@
"creation": "2021-08-24 12:28:18.044902",
"docstatus": 0,
"doctype": "Form Tour",
+ "first_document": 0,
"idx": 0,
+ "include_name_field": 0,
"is_standard": 1,
- "modified": "2021-08-24 12:28:18.044902",
+ "modified": "2022-01-18 18:32:17.102330",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges Template",
"owner": "Administrator",
"reference_doctype": "Sales Taxes and Charges Template",
- "save_on_complete": 0,
+ "save_on_complete": 1,
"steps": [
{
"description": "A name by which you will identify this template. You can change this later.",
diff --git a/erpnext/accounts/module_onboarding/accounts/accounts.json b/erpnext/accounts/module_onboarding/accounts/accounts.json
index 2e0ab43..aa7cdf7 100644
--- a/erpnext/accounts/module_onboarding/accounts/accounts.json
+++ b/erpnext/accounts/module_onboarding/accounts/accounts.json
@@ -13,16 +13,13 @@
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/accounts",
"idx": 0,
"is_complete": 0,
- "modified": "2021-08-13 11:59:35.690443",
+ "modified": "2022-01-18 18:35:52.326688",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts",
"owner": "Administrator",
"steps": [
{
- "step": "Company"
- },
- {
"step": "Chart of Accounts"
},
{
diff --git a/erpnext/accounts/onboarding_step/company/company.json b/erpnext/accounts/onboarding_step/company/company.json
deleted file mode 100644
index 4992e4d..0000000
--- a/erpnext/accounts/onboarding_step/company/company.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "action": "Go to Page",
- "action_label": "Let's Review your Company",
- "creation": "2021-06-29 14:47:42.497318",
- "description": "# Company\n\nIn ERPNext, you can also create multiple companies, and establish relationships (group/subsidiary) among them.\n\nWithin the company master, you can capture various default accounts for that Company and set crucial settings related to the accounting methodology followed for a company. \n",
- "docstatus": 0,
- "doctype": "Onboarding Step",
- "idx": 0,
- "is_complete": 0,
- "is_single": 0,
- "is_skipped": 0,
- "modified": "2021-08-13 11:43:35.767341",
- "modified_by": "Administrator",
- "name": "Company",
- "owner": "Administrator",
- "path": "app/company",
- "reference_document": "Company",
- "show_form_tour": 0,
- "show_full_form": 0,
- "title": "Review Company",
- "validate_action": 1
-}
\ No newline at end of file
diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
index 305cddb..715cd64 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
@@ -117,6 +117,11 @@
"label": __("Show Future Payments"),
"fieldtype": "Check",
},
+ {
+ "fieldname":"show_gl_balance",
+ "label": __("Show GL Balance"),
+ "fieldtype": "Check",
+ },
],
onload: function(report) {
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 3c94629..4559fa9 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
@@ -4,7 +4,8 @@
import frappe
from frappe import _, scrub
-from frappe.utils import cint
+from frappe.utils import cint, flt
+from six import iteritems
from erpnext.accounts.party import get_partywise_advanced_payment_amount
from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport
@@ -36,7 +37,10 @@
party_advance_amount = get_partywise_advanced_payment_amount(self.party_type,
self.filters.report_date, self.filters.show_future_payments, self.filters.company) or {}
- for party, party_dict in self.party_total.items():
+ if self.filters.show_gl_balance:
+ gl_balance_map = get_gl_balance(self.filters.report_date)
+
+ for party, party_dict in iteritems(self.party_total):
if party_dict.outstanding == 0:
continue
@@ -55,6 +59,10 @@
# but in summary report advance shown in separate column
row.paid -= row.advance
+ if self.filters.show_gl_balance:
+ row.gl_balance = gl_balance_map.get(party)
+ row.diff = flt(row.outstanding) - flt(row.gl_balance)
+
self.data.append(row)
def get_party_total(self, args):
@@ -114,6 +122,10 @@
self.add_column(_(credit_debit_label), fieldname='credit_note')
self.add_column(_('Outstanding Amount'), fieldname='outstanding')
+ if self.filters.show_gl_balance:
+ self.add_column(_('GL Balance'), fieldname='gl_balance')
+ self.add_column(_('Difference'), fieldname='diff')
+
self.setup_ageing_columns()
if self.party_type == "Customer":
@@ -140,3 +152,7 @@
# Add column for total due amount
self.add_column(label="Total Amount Due", fieldname='total_due')
+
+def get_gl_balance(report_date):
+ return frappe._dict(frappe.db.get_all("GL Entry", fields=['party', 'sum(debit - credit)'],
+ filters={'posting_date': ("<=", report_date), 'is_cancelled': 0}, group_by='party', as_list=1))
diff --git a/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py
index a4842c1..3a51db8 100644
--- a/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py
+++ b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py
@@ -121,20 +121,21 @@
"""
simulate future posting by creating dummy gl entries. starts from the last posting date.
"""
- if add_days(self.last_entry_date, 1) < self.period_list[-1].to_date:
- self.estimate_for_period_list = get_period_list(
- self.filters.from_fiscal_year,
- self.filters.to_fiscal_year,
- add_days(self.last_entry_date, 1),
- self.period_list[-1].to_date,
- "Date Range",
- "Monthly",
- company=self.filters.company,
- )
- for period in self.estimate_for_period_list:
- amount = self.calculate_amount(period.from_date, period.to_date)
- gle = self.make_dummy_gle(period.key, period.to_date, amount)
- self.gle_entries.append(gle)
+ if self.service_start_date != self.service_end_date:
+ if add_days(self.last_entry_date, 1) < self.period_list[-1].to_date:
+ self.estimate_for_period_list = get_period_list(
+ self.filters.from_fiscal_year,
+ self.filters.to_fiscal_year,
+ add_days(self.last_entry_date, 1),
+ self.period_list[-1].to_date,
+ "Date Range",
+ "Monthly",
+ company=self.filters.company,
+ )
+ for period in self.estimate_for_period_list:
+ amount = self.calculate_amount(period.from_date, period.to_date)
+ gle = self.make_dummy_gle(period.key, period.to_date, amount)
+ self.gle_entries.append(gle)
def calculate_item_revenue_expense_for_period(self):
"""
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js
index b296876..010284c 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.js
+++ b/erpnext/accounts/report/general_ledger/general_ledger.js
@@ -167,7 +167,7 @@
"fieldname": "include_dimensions",
"label": __("Consider Accounting Dimensions"),
"fieldtype": "Check",
- "default": 0
+ "default": 1
},
{
"fieldname": "show_opening_entries",
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py
index 385c8b2..7f27920 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.py
+++ b/erpnext/accounts/report/general_ledger/general_ledger.py
@@ -448,9 +448,11 @@
elif group_by_voucher_consolidated:
keylist = [gle.get("voucher_type"), gle.get("voucher_no"), gle.get("account")]
- for dim in accounting_dimensions:
- keylist.append(gle.get(dim))
- keylist.append(gle.get("cost_center"))
+ if filters.get("include_dimensions"):
+ for dim in accounting_dimensions:
+ keylist.append(gle.get(dim))
+ keylist.append(gle.get("cost_center"))
+
key = tuple(keylist)
if key not in consolidated_gle:
consolidated_gle.setdefault(key, gle)
@@ -547,10 +549,7 @@
"fieldname": "balance",
"fieldtype": "Float",
"width": 130
- }
- ]
-
- columns.extend([
+ },
{
"label": _("Voucher Type"),
"fieldname": "voucher_type",
@@ -584,7 +583,7 @@
"fieldname": "project",
"width": 100
}
- ])
+ ]
if filters.get("include_dimensions"):
for dim in get_accounting_dimensions(as_list = False):
@@ -594,14 +593,14 @@
"fieldname": dim.fieldname,
"width": 100
})
-
- columns.extend([
- {
+ columns.append({
"label": _("Cost Center"),
"options": "Cost Center",
"fieldname": "cost_center",
"width": 100
- },
+ })
+
+ columns.extend([
{
"label": _("Against Voucher Type"),
"fieldname": "against_voucher_type",
diff --git a/erpnext/accounts/test/test_reports.py b/erpnext/accounts/test/test_reports.py
new file mode 100644
index 0000000..78c109a
--- /dev/null
+++ b/erpnext/accounts/test/test_reports.py
@@ -0,0 +1,48 @@
+import unittest
+from typing import List, Tuple
+
+from erpnext.tests.utils import ReportFilters, ReportName, execute_script_report
+
+DEFAULT_FILTERS = {
+ "company": "_Test Company",
+ "from_date": "2010-01-01",
+ "to_date": "2030-01-01",
+ "period_start_date": "2010-01-01",
+ "period_end_date": "2030-01-01"
+}
+
+
+REPORT_FILTER_TEST_CASES: List[Tuple[ReportName, ReportFilters]] = [
+ ("General Ledger", {"group_by": "Group by Voucher (Consolidated)"} ),
+ ("General Ledger", {"group_by": "Group by Voucher (Consolidated)", "include_dimensions": 1} ),
+ ("Accounts Payable", {"range1": 30, "range2": 60, "range3": 90, "range4": 120}),
+ ("Accounts Receivable", {"range1": 30, "range2": 60, "range3": 90, "range4": 120}),
+ ("Consolidated Financial Statement", {"report": "Balance Sheet"} ),
+ ("Consolidated Financial Statement", {"report": "Profit and Loss Statement"} ),
+ ("Consolidated Financial Statement", {"report": "Cash Flow"} ),
+ ("Gross Profit", {"group_by": "Invoice"}),
+ ("Gross Profit", {"group_by": "Item Code"}),
+ ("Gross Profit", {"group_by": "Item Group"}),
+ ("Gross Profit", {"group_by": "Customer"}),
+ ("Gross Profit", {"group_by": "Customer Group"}),
+ ("Item-wise Sales Register", {}),
+ ("Item-wise Purchase Register", {}),
+ ("Sales Register", {}),
+ ("Purchase Register", {}),
+ ("Tax Detail", {"mode": "run", "report_name": "Tax Detail"},),
+]
+
+OPTIONAL_FILTERS = {}
+
+
+class TestReports(unittest.TestCase):
+ def test_execute_all_accounts_reports(self):
+ """Test that all script report in stock modules are executable with supported filters"""
+ for report, filter in REPORT_FILTER_TEST_CASES:
+ execute_script_report(
+ report_name=report,
+ module="Accounts",
+ filters=filter,
+ default_filters=DEFAULT_FILTERS,
+ optional_filters=OPTIONAL_FILTERS if filter.get("_optional") else None,
+ )
diff --git a/erpnext/accounts/workspace/accounting/accounting.json b/erpnext/accounts/workspace/accounting/accounting.json
index 33d1748..203ea20 100644
--- a/erpnext/accounts/workspace/accounting/accounting.json
+++ b/erpnext/accounts/workspace/accounting/accounting.json
@@ -5,7 +5,7 @@
"label": "Profit and Loss"
}
],
- "content": "[{\"type\": \"onboarding\", \"data\": {\"onboarding_name\":\"Accounts\", \"col\": 12}}, {\"type\": \"chart\", \"data\": {\"chart_name\": \"Profit and Loss\", \"col\": 12}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Chart of Accounts\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Sales Invoice\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Purchase Invoice\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Journal Entry\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Payment Entry\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Accounts Receivable\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"General Ledger\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Trial Balance\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Dashboard\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Accounting Masters\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"General Ledger\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Accounts Receivable\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Accounts Payable\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Reports\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Financial Statements\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Multi Currency\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Settings\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Bank Statement\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Subscription Management\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Goods and Services Tax (GST India)\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Share Management\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Cost Center and Budgeting\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Opening and Closing\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Taxes\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Profitability\", \"col\": 4}}]",
+ "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Accounts\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chart of Accounts\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"General Ledger\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Trial Balance\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"General Ledger\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Receivable\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Payable\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Bank Statement\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Goods and Services Tax (GST India)\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Taxes\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}}]",
"creation": "2020-03-02 15:41:59.515192",
"docstatus": 0,
"doctype": "Workspace",
@@ -230,6 +230,7 @@
"hidden": 0,
"is_query_report": 0,
"label": "Payment Reconciliation",
+ "link_count": 0,
"link_to": "Payment Reconciliation",
"link_type": "DocType",
"onboard": 0,
@@ -346,6 +347,7 @@
"hidden": 0,
"is_query_report": 0,
"label": "Payment Reconciliation",
+ "link_count": 0,
"link_to": "Payment Reconciliation",
"link_type": "DocType",
"onboard": 0,
@@ -527,16 +529,17 @@
"type": "Link"
},
{
- "dependencies": "GL Entry",
- "hidden": 0,
- "is_query_report": 1,
- "label": "KSA VAT Report",
- "link_to": "KSA VAT",
- "link_type": "Report",
- "onboard": 0,
- "only_for": "Saudi Arabia",
- "type": "Link"
- },
+ "dependencies": "GL Entry",
+ "hidden": 0,
+ "is_query_report": 1,
+ "label": "KSA VAT Report",
+ "link_count": 0,
+ "link_to": "KSA VAT",
+ "link_type": "Report",
+ "onboard": 0,
+ "only_for": "Saudi Arabia",
+ "type": "Link"
+ },
{
"hidden": 0,
"is_query_report": 0,
@@ -1158,15 +1161,16 @@
"type": "Link"
},
{
- "hidden": 0,
- "is_query_report": 0,
- "label": "KSA VAT Setting",
- "link_to": "KSA VAT Setting",
- "link_type": "DocType",
- "onboard": 0,
- "only_for": "Saudi Arabia",
- "type": "Link"
- },
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "KSA VAT Setting",
+ "link_count": 0,
+ "link_to": "KSA VAT Setting",
+ "link_type": "DocType",
+ "onboard": 0,
+ "only_for": "Saudi Arabia",
+ "type": "Link"
+ },
{
"hidden": 0,
"is_query_report": 0,
@@ -1220,7 +1224,7 @@
"type": "Link"
}
],
- "modified": "2021-08-27 12:15:52.872471",
+ "modified": "2022-01-13 17:25:09.835345",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting",
@@ -1229,7 +1233,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 2,
+ "sequence_id": 2.0,
"shortcuts": [
{
"label": "Chart of Accounts",
@@ -1278,4 +1282,4 @@
}
],
"title": "Accounting"
-}
+}
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json
index de06075..0a7c041 100644
--- a/erpnext/assets/doctype/asset/asset.json
+++ b/erpnext/assets/doctype/asset/asset.json
@@ -35,6 +35,7 @@
"available_for_use_date",
"column_break_23",
"gross_purchase_amount",
+ "asset_quantity",
"purchase_date",
"section_break_23",
"calculate_depreciation",
@@ -480,6 +481,12 @@
"fieldname": "section_break_36",
"fieldtype": "Section Break",
"label": "Finance Books"
+ },
+ {
+ "fieldname": "asset_quantity",
+ "fieldtype": "Int",
+ "label": "Asset Quantity",
+ "read_only_depends_on": "eval:!doc.is_existing_asset"
}
],
"idx": 72,
@@ -502,10 +509,11 @@
"link_fieldname": "asset"
}
],
- "modified": "2021-06-24 14:58:51.097908",
+ "modified": "2022-01-18 12:57:36.741192",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",
+ "naming_rule": "By \"Naming Series\" field",
"owner": "Administrator",
"permissions": [
{
@@ -542,6 +550,7 @@
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
"title_field": "asset_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index a18b03a..ac64a95 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -36,6 +36,7 @@
self.validate_asset_values()
self.validate_asset_and_reference()
self.validate_item()
+ self.validate_cost_center()
self.set_missing_values()
self.prepare_depreciation_data()
self.validate_gross_and_purchase_amount()
@@ -95,6 +96,19 @@
elif item.is_stock_item:
frappe.throw(_("Item {0} must be a non-stock item").format(self.item_code))
+ def validate_cost_center(self):
+ if not self.cost_center: return
+
+ cost_center_company = frappe.db.get_value('Cost Center', self.cost_center, 'company')
+ if cost_center_company != self.company:
+ frappe.throw(
+ _("Selected Cost Center {} doesn't belongs to {}").format(
+ frappe.bold(self.cost_center),
+ frappe.bold(self.company)
+ ),
+ title=_("Invalid Cost Center")
+ )
+
def validate_in_use_date(self):
if not self.available_for_use_date:
frappe.throw(_("Available for use date is required"))
@@ -242,8 +256,9 @@
# For first row
if has_pro_rata and not self.opening_accumulated_depreciation and n==0:
+ from_date = add_days(self.available_for_use_date, -1) # needed to calc depr amount for available_for_use_date too
depreciation_amount, days, months = self.get_pro_rata_amt(finance_book, depreciation_amount,
- self.available_for_use_date, finance_book.depreciation_start_date)
+ from_date, finance_book.depreciation_start_date)
# For first depr schedule date will be the start date
# so monthly schedule date is calculated by removing month difference between use date and start date
@@ -374,7 +389,9 @@
if from_date:
return from_date
- return self.available_for_use_date
+
+ # since depr for available_for_use_date is not yet booked
+ return add_days(self.available_for_use_date, -1)
# if it returns True, depreciation_amount will not be equal for the first and last rows
def check_is_pro_rata(self, row):
@@ -608,7 +625,17 @@
return purchase_document
def get_fixed_asset_account(self):
- return get_asset_category_account('fixed_asset_account', None, self.name, None, self.asset_category, self.company)
+ fixed_asset_account = get_asset_category_account('fixed_asset_account', None, self.name, None, self.asset_category, self.company)
+ if not fixed_asset_account:
+ frappe.throw(
+ _("Set {0} in asset category {1} for company {2}").format(
+ frappe.bold("Fixed Asset Account"),
+ frappe.bold(self.asset_category),
+ frappe.bold(self.company),
+ ),
+ title=_("Account not Found"),
+ )
+ return fixed_asset_account
def get_cwip_account(self, cwip_enabled=False):
cwip_account = None
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index 44c4ce5..b9545f4 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -134,6 +134,29 @@
pr.cancel()
self.assertEqual(asset.docstatus, 2)
+ def test_purchase_of_grouped_asset(self):
+ create_fixed_asset_item("Rack", is_grouped_asset=1)
+ pr = make_purchase_receipt(item_code="Rack", qty=3, rate=100000.0, location="Test Location")
+
+ asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name')
+ asset = frappe.get_doc('Asset', asset_name)
+ self.assertEqual(asset.asset_quantity, 3)
+ asset.calculate_depreciation = 1
+
+ month_end_date = get_last_day(nowdate())
+ purchase_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15)
+
+ asset.available_for_use_date = purchase_date
+ asset.purchase_date = purchase_date
+ 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": month_end_date
+ })
+ asset.submit()
+
def test_is_fixed_asset_set(self):
asset = create_asset(is_existing_asset = 1)
doc = frappe.new_doc('Purchase Invoice')
@@ -207,9 +230,9 @@
self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Sold")
expected_gle = (
- ("_Test Accumulated Depreciations - _TC", 20392.16, 0.0),
+ ("_Test Accumulated Depreciations - _TC", 20490.2, 0.0),
("_Test Fixed Asset - _TC", 0.0, 100000.0),
- ("_Test Gain/Loss on Asset Disposal - _TC", 54607.84, 0.0),
+ ("_Test Gain/Loss on Asset Disposal - _TC", 54509.8, 0.0),
("Debtors - _TC", 25000.0, 0.0)
)
@@ -491,10 +514,10 @@
)
expected_schedules = [
- ["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]
+ ['2030-12-31', 27616.44, 27616.44],
+ ['2031-12-31', 30000.0, 57616.44],
+ ['2032-12-31', 30000.0, 87616.44],
+ ['2033-01-30', 2383.56, 90000.0]
]
schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)]
@@ -544,10 +567,10 @@
self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0)
expected_schedules = [
- ["2030-12-31", 28493.15, 28493.15],
- ["2031-12-31", 35753.43, 64246.58],
- ["2032-12-31", 17876.71, 82123.29],
- ["2033-06-06", 5376.71, 87500.0]
+ ['2030-12-31', 28630.14, 28630.14],
+ ['2031-12-31', 35684.93, 64315.07],
+ ['2032-12-31', 17842.47, 82157.54],
+ ['2033-06-06', 5342.46, 87500.0]
]
schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)]
@@ -580,10 +603,10 @@
self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0)
expected_schedules = [
- ["2030-12-31", 11780.82, 11780.82],
- ["2031-12-31", 44109.59, 55890.41],
- ["2032-12-31", 22054.8, 77945.21],
- ["2033-07-12", 9554.79, 87500.0]
+ ["2030-12-31", 11849.32, 11849.32],
+ ["2031-12-31", 44075.34, 55924.66],
+ ["2032-12-31", 22037.67, 77962.33],
+ ["2033-07-12", 9537.67, 87500.0]
]
schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)]
@@ -621,7 +644,7 @@
asset = create_asset(
item_code = "Macbook Pro",
calculate_depreciation = 1,
- available_for_use_date = getdate("2019-12-31"),
+ available_for_use_date = getdate("2020-01-01"),
total_number_of_depreciations = 3,
expected_value_after_useful_life = 10000,
depreciation_start_date = getdate("2020-07-01"),
@@ -632,7 +655,7 @@
["2020-07-01", 15000, 15000],
["2021-07-01", 30000, 45000],
["2022-07-01", 30000, 75000],
- ["2022-12-31", 15000, 90000]
+ ["2023-01-01", 15000, 90000]
]
for i, schedule in enumerate(asset.schedules):
@@ -1109,6 +1132,7 @@
self.assertEqual(gle, expected_gle)
self.assertEqual(asset.get("value_after_depreciation"), 0)
+
def test_expected_value_change(self):
"""
tests if changing `expected_value_after_useful_life`
@@ -1130,6 +1154,15 @@
asset.reload()
self.assertEquals(asset.finance_books[0].value_after_depreciation, 98000.0)
+ def test_asset_cost_center(self):
+ asset = create_asset(is_existing_asset = 1, do_not_save=1)
+ asset.cost_center = "Main - WP"
+
+ self.assertRaises(frappe.ValidationError, asset.submit)
+
+ asset.cost_center = "Main - _TC"
+ asset.submit()
+
def create_asset_data():
if not frappe.db.exists("Asset Category", "Computers"):
create_asset_category()
@@ -1202,13 +1235,13 @@
})
asset_category.insert()
-def create_fixed_asset_item():
+def create_fixed_asset_item(item_code=None, auto_create_assets=1, is_grouped_asset=0):
meta = frappe.get_meta('Asset')
naming_series = meta.get_field("naming_series").options.splitlines()[0] or 'ACC-ASS-.YYYY.-'
try:
- frappe.get_doc({
+ item = frappe.get_doc({
"doctype": "Item",
- "item_code": "Macbook Pro",
+ "item_code": item_code or "Macbook Pro",
"item_name": "Macbook Pro",
"description": "Macbook Pro Retina Display",
"asset_category": "Computers",
@@ -1216,11 +1249,14 @@
"stock_uom": "Nos",
"is_stock_item": 0,
"is_fixed_asset": 1,
- "auto_create_assets": 1,
+ "auto_create_assets": auto_create_assets,
+ "is_grouped_asset": is_grouped_asset,
"asset_naming_series": naming_series
- }).insert()
+ })
+ item.insert()
except frappe.DuplicateEntryError:
pass
+ return item
def set_depreciation_settings_in_company():
company = frappe.get_doc("Company", "_Test Company")
diff --git a/erpnext/assets/workspace/assets/assets.json b/erpnext/assets/workspace/assets/assets.json
index 495de46..26a6609 100644
--- a/erpnext/assets/workspace/assets/assets.json
+++ b/erpnext/assets/workspace/assets/assets.json
@@ -5,7 +5,7 @@
"label": "Asset Value Analytics"
}
],
- "content": "[{\"type\": \"onboarding\", \"data\": {\"onboarding_name\":\"Assets\", \"col\": 12}}, {\"type\": \"chart\", \"data\": {\"chart_name\": \"Asset Value Analytics\", \"col\": 12}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Asset\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Asset Category\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Fixed Asset Register\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Dashboard\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Assets\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Maintenance\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Reports\", \"col\": 4}}]",
+ "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Assets\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Asset Value Analytics\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Asset\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Asset Category\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Fixed Asset Register\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Assets\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Maintenance\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]",
"creation": "2020-03-02 15:43:27.634865",
"docstatus": 0,
"doctype": "Workspace",
@@ -172,7 +172,7 @@
"type": "Link"
}
],
- "modified": "2021-08-05 12:15:54.839453",
+ "modified": "2022-01-13 17:25:41.730628",
"modified_by": "Administrator",
"module": "Assets",
"name": "Assets",
@@ -181,7 +181,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 4,
+ "sequence_id": 4.0,
"shortcuts": [
{
"label": "Asset",
diff --git a/erpnext/buying/workspace/buying/buying.json b/erpnext/buying/workspace/buying/buying.json
index 380ef36..5ad93f0 100644
--- a/erpnext/buying/workspace/buying/buying.json
+++ b/erpnext/buying/workspace/buying/buying.json
@@ -5,7 +5,7 @@
"label": "Purchase Order Trends"
}
],
- "content": "[{\"type\": \"onboarding\", \"data\": {\"onboarding_name\":\"Buying\", \"col\": 12}}, {\"type\": \"chart\", \"data\": {\"chart_name\": \"Purchase Order Trends\", \"col\": 12}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Item\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Material Request\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Purchase Order\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Purchase Analytics\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Purchase Order Analysis\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Dashboard\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Buying\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Items & Pricing\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Settings\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Supplier\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Supplier Scorecard\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Key Reports\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Other Reports\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Regional\", \"col\": 4}}]",
+ "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Buying\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Purchase Order Trends\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Material Request\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Order\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Analytics\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Order Analysis\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Buying\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Items & Pricing\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Supplier\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Supplier Scorecard\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Regional\",\"col\":4}}]",
"creation": "2020-01-28 11:50:26.195467",
"docstatus": 0,
"doctype": "Workspace",
@@ -509,7 +509,7 @@
"type": "Link"
}
],
- "modified": "2021-08-05 12:15:56.218428",
+ "modified": "2022-01-13 17:26:39.090190",
"modified_by": "Administrator",
"module": "Buying",
"name": "Buying",
@@ -518,7 +518,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 6,
+ "sequence_id": 6.0,
"shortcuts": [
{
"color": "Green",
diff --git a/erpnext/commands/__init__.py b/erpnext/commands/__init__.py
index 5931119..8e12fad 100644
--- a/erpnext/commands/__init__.py
+++ b/erpnext/commands/__init__.py
@@ -1,49 +1,10 @@
-# Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors
-# MIT License. See license.txt
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# GPL v3 License. See license.txt
import click
-import frappe
-from frappe.commands import get_site, pass_context
def call_command(cmd, context):
return click.Context(cmd, obj=context).forward(cmd)
-@click.command('make-demo')
-@click.option('--site', help='site name')
-@click.option('--domain', default='Manufacturing')
-@click.option('--days', default=100,
- help='Run the demo for so many days. Default 100')
-@click.option('--resume', default=False, is_flag=True,
- help='Continue running the demo for given days')
-@click.option('--reinstall', default=False, is_flag=True,
- help='Reinstall site before demo')
-@pass_context
-def make_demo(context, site, domain='Manufacturing', days=100,
- resume=False, reinstall=False):
- "Reinstall site and setup demo"
- from frappe.commands.site import _reinstall
- from frappe.installer import install_app
-
- site = get_site(context)
-
- if resume:
- with frappe.init_site(site):
- frappe.connect()
- from erpnext.demo import demo
- demo.simulate(days=days)
- else:
- if reinstall:
- _reinstall(site, yes=True)
- with frappe.init_site(site=site):
- frappe.connect()
- if not 'erpnext' in frappe.get_installed_apps():
- install_app('erpnext')
-
- # import needs site
- from erpnext.demo import demo
- demo.make(domain, days)
-
-commands = [
- make_demo
-]
+commands = []
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index ce5d5dc..4775f56 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -113,7 +113,7 @@
_('{0} is blocked so this transaction cannot proceed').format(supplier_name), raise_exception=1)
def validate(self):
- if not self.get('is_return'):
+ if not self.get('is_return') and not self.get('is_debit_note'):
self.validate_qty_is_not_zero()
if self.get("_action") and self._action != "update_after_submit":
@@ -185,8 +185,6 @@
frappe.throw(_("Row #{0}: Service Start Date cannot be greater than Service End Date").format(d.idx))
elif getdate(self.posting_date) > getdate(d.service_end_date):
frappe.throw(_("Row #{0}: Service End Date cannot be before Invoice Posting Date").format(d.idx))
- elif getdate(self.posting_date) > getdate(d.service_start_date):
- frappe.throw(_("Row #{0}: Service Start Date cannot be before Invoice Posting Date").format(d.idx))
def validate_invoice_documents_schedule(self):
self.validate_payment_schedule_dates()
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index a3d2502..f088b9f 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -554,10 +554,13 @@
# Check for asset naming series
if item_data.get('asset_naming_series'):
created_assets = []
-
- for qty in range(cint(d.qty)):
- asset = self.make_asset(d)
+ if item_data.get('is_grouped_asset'):
+ asset = self.make_asset(d, is_grouped_asset=True)
created_assets.append(asset)
+ else:
+ for qty in range(cint(d.qty)):
+ asset = self.make_asset(d)
+ created_assets.append(asset)
if len(created_assets) > 5:
# dont show asset form links if more than 5 assets are created
@@ -580,14 +583,18 @@
for message in messages:
frappe.msgprint(message, title="Success", indicator="green")
- def make_asset(self, row):
+ def make_asset(self, row, is_grouped_asset=False):
if not row.asset_location:
frappe.throw(_("Row {0}: Enter location for the asset item {1}").format(row.idx, row.item_code))
item_data = frappe.db.get_value('Item',
row.item_code, ['asset_naming_series', 'asset_category'], as_dict=1)
- purchase_amount = flt(row.base_rate + row.item_tax_amount)
+ if is_grouped_asset:
+ purchase_amount = flt(row.base_amount + row.item_tax_amount)
+ else:
+ purchase_amount = flt(row.base_rate + row.item_tax_amount)
+
asset = frappe.get_doc({
'doctype': 'Asset',
'item_code': row.item_code,
@@ -601,6 +608,7 @@
'calculate_depreciation': 1,
'purchase_receipt_amount': purchase_amount,
'gross_purchase_amount': purchase_amount,
+ 'asset_quantity': row.qty if is_grouped_asset else 0,
'purchase_receipt': self.name if self.doctype == 'Purchase Receipt' else None,
'purchase_invoice': self.name if self.doctype == 'Purchase Invoice' else None
})
@@ -687,7 +695,7 @@
def get_asset_item_details(asset_items):
asset_items_data = {}
- for d in frappe.get_all('Item', fields = ["name", "auto_create_assets", "asset_naming_series"],
+ for d in frappe.get_all('Item', fields = ["name", "auto_create_assets", "asset_naming_series", "is_grouped_asset"],
filters = {'name': ('in', asset_items)}):
asset_items_data.setdefault(d.name, d)
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index cc773b7..4ff851d 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -385,7 +385,7 @@
# Get incoming rate based on original item cost based on valuation method
qty = flt(d.get('stock_qty') or d.get('actual_qty'))
- if not d.incoming_rate:
+ if not (self.get("is_return") and d.incoming_rate):
d.incoming_rate = get_incoming_rate({
"item_code": d.item_code,
"warehouse": d.warehouse,
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 7073e32..b97432e 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -17,7 +17,7 @@
from erpnext.accounts.utils import get_fiscal_year
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.stock import get_warehouse_account_map
-from erpnext.stock.stock_ledger import get_items_to_be_repost, get_valuation_rate
+from erpnext.stock.stock_ledger import get_items_to_be_repost
class QualityInspectionRequiredError(frappe.ValidationError): pass
@@ -111,17 +111,6 @@
self.check_expense_account(item_row)
- # If the item does not have the allow zero valuation rate flag set
- # and ( valuation rate not mentioned in an incoming entry
- # or incoming entry not found while delivering the item),
- # try to pick valuation rate from previous sle or Item master and update in SLE
- # Otherwise, throw an exception
-
- if not sle.stock_value_difference and self.doctype != "Stock Reconciliation" \
- and not item_row.get("allow_zero_valuation_rate"):
-
- sle = self.update_stock_ledger_entries(sle)
-
# expense account/ target_warehouse / source_warehouse
if item_row.get('target_warehouse'):
warehouse = item_row.get('target_warehouse')
@@ -164,26 +153,6 @@
return frappe.flags.debit_field_precision
- def update_stock_ledger_entries(self, sle):
- sle.valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse,
- self.doctype, self.name, currency=self.company_currency, company=self.company)
-
- sle.stock_value = flt(sle.qty_after_transaction) * flt(sle.valuation_rate)
- sle.stock_value_difference = flt(sle.actual_qty) * flt(sle.valuation_rate)
-
- if sle.name:
- frappe.db.sql("""
- update
- `tabStock Ledger Entry`
- set
- stock_value = %(stock_value)s,
- valuation_rate = %(valuation_rate)s,
- stock_value_difference = %(stock_value_difference)s
- where
- name = %(name)s""", (sle))
-
- return sle
-
def get_voucher_details(self, default_expense_account, default_cost_center, sle_map):
if self.doctype == "Stock Reconciliation":
reconciliation_purpose = frappe.db.get_value(self.doctype, self.name, "purpose")
@@ -287,11 +256,7 @@
for d in self.items:
if not d.batch_no: continue
- serial_nos = [sr.name for sr in frappe.get_all("Serial No",
- {'batch_no': d.batch_no, 'status': 'Inactive'})]
-
- if serial_nos:
- frappe.db.set_value("Serial No", { 'name': ['in', serial_nos] }, "batch_no", None)
+ frappe.db.set_value("Serial No", {"batch_no": d.batch_no, "status": "Inactive"}, "batch_no", None)
d.batch_no = None
d.db_set("batch_no", None)
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 746c6fd..075e3e3 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -139,6 +139,8 @@
if not item.qty and self.doc.get("is_return"):
item.amount = flt(-1 * item.rate, item.precision("amount"))
+ elif not item.qty and self.doc.get("is_debit_note"):
+ item.amount = flt(item.rate, item.precision("amount"))
else:
item.amount = flt(item.rate * item.qty, item.precision("amount"))
@@ -594,13 +596,14 @@
if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]:
grand_total = self.doc.rounded_total or self.doc.grand_total
+ base_grand_total = self.doc.base_rounded_total or self.doc.base_grand_total
+
if self.doc.party_account_currency == self.doc.currency:
total_amount_to_pay = flt(grand_total - self.doc.total_advance
- flt(self.doc.write_off_amount), self.doc.precision("grand_total"))
else:
- total_amount_to_pay = flt(flt(grand_total *
- self.doc.conversion_rate, self.doc.precision("grand_total")) - self.doc.total_advance
- - flt(self.doc.base_write_off_amount), self.doc.precision("grand_total"))
+ total_amount_to_pay = flt(flt(base_grand_total, self.doc.precision("base_grand_total")) - self.doc.total_advance
+ - flt(self.doc.base_write_off_amount), self.doc.precision("base_grand_total"))
self.doc.round_floats_in(self.doc, ["paid_amount"])
change_amount = 0
diff --git a/erpnext/controllers/tests/test_queries.py b/erpnext/controllers/tests/test_queries.py
index 05541d1..908d78c 100644
--- a/erpnext/controllers/tests/test_queries.py
+++ b/erpnext/controllers/tests/test_queries.py
@@ -1,6 +1,8 @@
import unittest
from functools import partial
+import frappe
+
from erpnext.controllers import queries
@@ -85,3 +87,6 @@
wh = query(filters=[["Bin", "item_code", "=", "_Test Item"]])
self.assertGreaterEqual(len(wh), 1)
+
+ def test_default_uoms(self):
+ self.assertGreaterEqual(frappe.db.count("UOM", {"enabled": 1}), 10)
diff --git a/erpnext/controllers/tests/test_transaction_base.py b/erpnext/controllers/tests/test_transaction_base.py
index 13aa697..f4d3f97 100644
--- a/erpnext/controllers/tests/test_transaction_base.py
+++ b/erpnext/controllers/tests/test_transaction_base.py
@@ -4,19 +4,72 @@
class TestUtils(unittest.TestCase):
- def test_reset_default_field_value(self):
- doc = frappe.get_doc({
- "doctype": "Purchase Receipt",
- "set_warehouse": "Warehouse 1",
- })
+ def test_reset_default_field_value(self):
+ doc = frappe.get_doc({
+ "doctype": "Purchase Receipt",
+ "set_warehouse": "Warehouse 1",
+ })
- # Same values
- doc.items = [{"warehouse": "Warehouse 1"}, {"warehouse": "Warehouse 1"}, {"warehouse": "Warehouse 1"}]
- doc.reset_default_field_value("set_warehouse", "items", "warehouse")
- self.assertEqual(doc.set_warehouse, "Warehouse 1")
+ # Same values
+ doc.items = [{"warehouse": "Warehouse 1"}, {"warehouse": "Warehouse 1"}, {"warehouse": "Warehouse 1"}]
+ doc.reset_default_field_value("set_warehouse", "items", "warehouse")
+ self.assertEqual(doc.set_warehouse, "Warehouse 1")
- # Mixed values
- doc.items = [{"warehouse": "Warehouse 1"}, {"warehouse": "Warehouse 2"}, {"warehouse": "Warehouse 1"}]
- doc.reset_default_field_value("set_warehouse", "items", "warehouse")
- self.assertEqual(doc.set_warehouse, None)
+ # Mixed values
+ doc.items = [{"warehouse": "Warehouse 1"}, {"warehouse": "Warehouse 2"}, {"warehouse": "Warehouse 1"}]
+ doc.reset_default_field_value("set_warehouse", "items", "warehouse")
+ self.assertEqual(doc.set_warehouse, None)
+ def test_reset_default_field_value_in_mfg_stock_entry(self):
+ # manufacture stock entry with rows having blank source/target wh
+ se = frappe.get_doc(
+ doctype="Stock Entry",
+ purpose="Manufacture",
+ stock_entry_type="Manufacture",
+ company="_Test Company",
+ from_warehouse="_Test Warehouse - _TC",
+ to_warehouse="_Test Warehouse 1 - _TC",
+ items=[
+ frappe._dict(item_code="_Test Item", qty=1, basic_rate=200, s_warehouse="_Test Warehouse - _TC"),
+ frappe._dict(item_code="_Test FG Item", qty=4, t_warehouse="_Test Warehouse 1 - _TC", is_finished_item=1)
+ ]
+ )
+ se.save()
+
+ # default fields must be untouched
+ self.assertEqual(se.from_warehouse, "_Test Warehouse - _TC")
+ self.assertEqual(se.to_warehouse, "_Test Warehouse 1 - _TC")
+
+ se.delete()
+
+ def test_reset_default_field_value_in_transfer_stock_entry(self):
+ doc = frappe.get_doc({
+ "doctype": "Stock Entry",
+ "purpose": "Material Receipt",
+ "from_warehouse": "Warehouse 1",
+ "to_warehouse": "Warehouse 2",
+ })
+
+ # Same values
+ doc.items = [
+ {"s_warehouse": "Warehouse 1", "t_warehouse": "Warehouse 2"},
+ {"s_warehouse": "Warehouse 1", "t_warehouse": "Warehouse 2"},
+ {"s_warehouse": "Warehouse 1", "t_warehouse": "Warehouse 2"}
+ ]
+
+ doc.reset_default_field_value("from_warehouse", "items", "s_warehouse")
+ doc.reset_default_field_value("to_warehouse", "items", "t_warehouse")
+ self.assertEqual(doc.from_warehouse, "Warehouse 1")
+ self.assertEqual(doc.to_warehouse, "Warehouse 2")
+
+ # Mixed values in source wh
+ doc.items = [
+ {"s_warehouse": "Warehouse 1", "t_warehouse": "Warehouse 2"},
+ {"s_warehouse": "Warehouse 3", "t_warehouse": "Warehouse 2"},
+ {"s_warehouse": "Warehouse 1", "t_warehouse": "Warehouse 2"}
+ ]
+
+ doc.reset_default_field_value("from_warehouse", "items", "s_warehouse")
+ doc.reset_default_field_value("to_warehouse", "items", "t_warehouse")
+ self.assertEqual(doc.from_warehouse, None)
+ self.assertEqual(doc.to_warehouse, "Warehouse 2")
\ No newline at end of file
diff --git a/erpnext/crm/workspace/crm/crm.json b/erpnext/crm/workspace/crm/crm.json
index 5a63dc1..83341f5 100644
--- a/erpnext/crm/workspace/crm/crm.json
+++ b/erpnext/crm/workspace/crm/crm.json
@@ -1,10 +1,11 @@
{
"charts": [
{
- "chart_name": "Territory Wise Sales"
+ "chart_name": "Territory Wise Sales",
+ "label": "Territory Wise Sales"
}
],
- "content": "[{\"type\": \"onboarding\", \"data\": {\"onboarding_name\":\"CRM\", \"col\": 12}}, {\"type\": \"chart\", \"data\": {\"chart_name\": null, \"col\": 12}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Lead\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Opportunity\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Customer\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Sales Analytics\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Dashboard\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Sales Pipeline\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Reports\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Maintenance\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Campaign\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Settings\", \"col\": 4}}]",
+ "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"CRM\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Territory Wise Sales\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Lead\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Opportunity\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Customer\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Analytics\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Sales Pipeline\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Maintenance\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Campaign\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
"creation": "2020-01-23 14:48:30.183272",
"docstatus": 0,
"doctype": "Workspace",
@@ -144,6 +145,7 @@
"hidden": 0,
"is_query_report": 1,
"label": "Sales Pipeline Analytics",
+ "link_count": 0,
"link_to": "Sales Pipeline Analytics",
"link_type": "Report",
"onboard": 0,
@@ -153,6 +155,7 @@
"hidden": 0,
"is_query_report": 1,
"label": "Opportunity Summary by Sales Stage",
+ "link_count": 0,
"link_to": "Opportunity Summary by Sales Stage",
"link_type": "Report",
"onboard": 0,
@@ -414,7 +417,7 @@
"type": "Link"
}
],
- "modified": "2021-08-20 12:15:56.913092",
+ "modified": "2022-01-13 17:53:17.509844",
"modified_by": "Administrator",
"module": "CRM",
"name": "CRM",
@@ -423,7 +426,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 7,
+ "sequence_id": 7.0,
"shortcuts": [
{
"color": "Blue",
diff --git a/erpnext/demo/__init__.py b/erpnext/demo/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/demo/__init__.py
+++ /dev/null
diff --git a/erpnext/demo/data/account.json b/erpnext/demo/data/account.json
deleted file mode 100644
index b50b0c9..0000000
--- a/erpnext/demo/data/account.json
+++ /dev/null
@@ -1,18 +0,0 @@
-[{
- "account_name": "Debtors EUR",
- "parent_account": "Accounts Receivable",
- "account_type": "Receivable",
- "account_currency": "EUR"
-},
-{
- "account_name": "Creditors EUR",
- "parent_account": "Accounts Payable",
- "account_type": "Payable",
- "account_currency": "EUR"
-},
-{
- "account_name": "Paypal",
- "parent_account": "Bank Accounts",
- "account_type": "Bank",
- "account_currency": "EUR"
-}]
\ No newline at end of file
diff --git a/erpnext/demo/data/address.json b/erpnext/demo/data/address.json
deleted file mode 100644
index 7618c2c..0000000
--- a/erpnext/demo/data/address.json
+++ /dev/null
@@ -1,218 +0,0 @@
-[
- {
- "address_line1": "254 Theotokopoulou Str.",
- "address_type": "Office",
- "city": "Larnaka",
- "country": "Cyprus",
- "links": [{"link_doctype": "Customer", "link_name": "Adaptas"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "R Patr\u00e3o Caramelho 116",
- "address_type": "Office",
- "city": "Fajozes",
- "country": "Portugal",
- "links": [{"link_doctype": "Customer", "link_name": "Asian Fusion"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "30 Fulford Road",
- "address_type": "Office",
- "city": "PENTRE-PIOD",
- "country": "United Kingdom",
- "links": [{"link_doctype": "Customer", "link_name": "Asian Junction"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "Schoenebergerstrasse 13",
- "address_type": "Office",
- "city": "Raschau",
- "country": "Germany",
- "links": [{"link_doctype": "Customer", "link_name": "Big D Supermarkets"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "Hoheluftchaussee 43",
- "address_type": "Office",
- "city": "Kieritzsch",
- "country": "Germany",
- "links": [{"link_doctype": "Customer", "link_name": "Buttrey Food & Drug"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "R Cimo Vila 6",
- "address_type": "Office",
- "city": "Rebordosa",
- "country": "Portugal",
- "links": [{"link_doctype": "Customer", "link_name": "Chi-Chis"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "R 5 Outubro 9",
- "address_type": "Office",
- "city": "Quinta Nova S\u00e3o Domingos",
- "country": "Portugal",
- "links": [{"link_doctype": "Customer", "link_name": "Choices"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "Avenida Macambira 953",
- "address_type": "Office",
- "city": "Goi\u00e2nia",
- "country": "Brazil",
- "links": [{"link_doctype": "Customer", "link_name": "Consumers and Consumers Express"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "2342 Goyeau Ave",
- "address_type": "Office",
- "city": "Windsor",
- "country": "Canada",
- "links": [{"link_doctype": "Customer", "link_name": "Crafts Canada"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "Laukaantie 82",
- "address_type": "Office",
- "city": "KOKKOLA",
- "country": "Finland",
- "links": [{"link_doctype": "Customer", "link_name": "Endicott Shoes"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "9 Brown Street",
- "address_type": "Office",
- "city": "PETERSHAM",
- "country": "Australia",
- "links": [{"link_doctype": "Customer", "link_name": "Fayva"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "Via Donnalbina 41",
- "address_type": "Office",
- "city": "Cala Gonone",
- "country": "Italy",
- "links": [{"link_doctype": "Customer", "link_name": "Intelacard"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "Liljerum Grenadj\u00e4rtorpet 69",
- "address_type": "Office",
- "city": "TOMTEBODA",
- "country": "Sweden",
- "links": [{"link_doctype": "Customer", "link_name": "Landskip Yard Care"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "72 Bishopgate Street",
- "address_type": "Office",
- "city": "SEAHAM",
- "country": "United Kingdom",
- "links": [{"link_doctype": "Customer", "link_name": "Life Plan Counselling"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "\u03a3\u03ba\u03b1\u03c6\u03af\u03b4\u03b9\u03b1 105",
- "address_type": "Office",
- "city": "\u03a0\u0391\u03a1\u0395\u039a\u039a\u039b\u0397\u03a3\u0399\u0391",
- "country": "Cyprus",
- "links": [{"link_doctype": "Customer", "link_name": "Mr Fables"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "Mellemvej 7",
- "address_type": "Office",
- "city": "Aabybro",
- "country": "Denmark",
- "links": [{"link_doctype": "Customer", "link_name": "Nelson Brothers"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "Plougg\u00e5rdsvej 98",
- "address_type": "Office",
- "city": "Karby",
- "country": "Denmark",
- "links": [{"link_doctype": "Customer", "link_name": "Netobill"}],
- "phone": "23566775757"
- },
- {
- "address_line1": "176 Michalakopoulou Street",
- "address_type": "Office",
- "city": "Agio Georgoudi",
- "country": "Cyprus",
- "phone": "23566775757",
- "links": [{"link_doctype": "Supplier", "link_name": "Helios Air"}]
- },
- {
- "address_line1": "Fibichova 1102",
- "address_type": "Office",
- "city": "Kokor\u00edn",
- "country": "Czech Republic",
- "phone": "23566775757",
- "links": [{"link_doctype": "Supplier", "link_name": "Ks Merchandise"}]
- },
- {
- "address_line1": "Zahradn\u00ed 888",
- "address_type": "Office",
- "city": "Cecht\u00edn",
- "country": "Czech Republic",
- "phone": "23566775757",
- "links": [{"link_doctype": "Supplier", "link_name": "HomeBase"}]
- },
- {
- "address_line1": "ul. Grochowska 94",
- "address_type": "Office",
- "city": "Warszawa",
- "country": "Poland",
- "phone": "23566775757",
- "links": [{"link_doctype": "Supplier", "link_name": "Scott Ties"}]
- },
- {
- "address_line1": "Norra Esplanaden 87",
- "address_type": "Office",
- "city": "HELSINKI",
- "country": "Finland",
- "phone": "23566775757",
- "links": [{"link_doctype": "Supplier", "link_name": "Reliable Investments"}]
- },
- {
- "address_line1": "2038 Fallon Drive",
- "address_type": "Office",
- "city": "Dresden",
- "country": "Canada",
- "phone": "23566775757",
- "links": [{"link_doctype": "Supplier", "link_name": "Nan Duskin"}]
- },
- {
- "address_line1": "77 cours Franklin Roosevelt",
- "address_type": "Office",
- "city": "MARSEILLE",
- "country": "France",
- "phone": "23566775757",
- "links": [{"link_doctype": "Supplier", "link_name": "Rainbow Records"}]
- },
- {
- "address_line1": "ul. Tuwima Juliana 85",
- "address_type": "Office",
- "city": "\u0141\u00f3d\u017a",
- "country": "Poland",
- "phone": "23566775757",
- "links": [{"link_doctype": "Supplier", "link_name": "New World Realty"}]
- },
- {
- "address_line1": "Gl. Sygehusvej 41",
- "address_type": "Office",
- "city": "Narsaq",
- "country": "Greenland",
- "phone": "23566775757",
- "links": [{"link_doctype": "Supplier", "link_name": "Asiatic Solutions"}]
- },
- {
- "address_line1": "Gosposka ulica 50",
- "address_type": "Office",
- "city": "Nova Gorica",
- "country": "Slovenia",
- "phone": "23566775757",
- "links": [{"link_doctype": "Supplier", "link_name": "Eagle Hardware"}]
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/assessment_criteria.json b/erpnext/demo/data/assessment_criteria.json
deleted file mode 100644
index 8295682..0000000
--- a/erpnext/demo/data/assessment_criteria.json
+++ /dev/null
@@ -1,18 +0,0 @@
-[
- {
- "doctype": "Assessment Criteria",
- "assessment_criteria": "Aptitude"
- },
- {
- "doctype": "Assessment Criteria",
- "assessment_criteria": "Application"
- },
- {
- "doctype": "Assessment Criteria",
- "assessment_criteria": "Understanding"
- },
- {
- "doctype": "Assessment Criteria",
- "assessment_criteria": "Knowledge"
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/asset.json b/erpnext/demo/data/asset.json
deleted file mode 100644
index 44db2ae..0000000
--- a/erpnext/demo/data/asset.json
+++ /dev/null
@@ -1,58 +0,0 @@
-[
- {
- "asset_name": "Macbook Pro - 1",
- "item_code": "Computer",
- "gross_purchase_amount": 100000,
- "asset_owner": "Company",
- "available_for_use_date": "2017-01-02",
- "location": "Main Location"
- },
- {
- "asset_name": "Macbook Air - 1",
- "item_code": "Computer",
- "gross_purchase_amount": 60000,
- "asset_owner": "Company",
- "available_for_use_date": "2017-10-02",
- "location": "Avg Location"
- },
- {
- "asset_name": "Conferrence Table",
- "item_code": "Table",
- "gross_purchase_amount": 30000,
- "asset_owner": "Company",
- "available_for_use_date": "2018-10-02",
- "location": "Zany Location"
- },
- {
- "asset_name": "Lunch Table",
- "item_code": "Table",
- "gross_purchase_amount": 20000,
- "asset_owner": "Company",
- "available_for_use_date": "2018-06-02",
- "location": "Fletcher Location"
- },
- {
- "asset_name": "ERPNext",
- "item_code": "ERP",
- "gross_purchase_amount": 100000,
- "asset_owner": "Company",
- "available_for_use_date": "2018-09-02",
- "location":"Main Location"
- },
- {
- "asset_name": "Chair 1",
- "item_code": "Chair",
- "gross_purchase_amount": 10000,
- "asset_owner": "Company",
- "available_for_use_date": "2018-07-02",
- "location": "Zany Location"
- },
- {
- "asset_name": "Chair 2",
- "item_code": "Chair",
- "gross_purchase_amount": 10000,
- "asset_owner": "Company",
- "available_for_use_date": "2018-07-02",
- "location": "Avg Location"
- }
-]
diff --git a/erpnext/demo/data/asset_category.json b/erpnext/demo/data/asset_category.json
deleted file mode 100644
index 54f779d..0000000
--- a/erpnext/demo/data/asset_category.json
+++ /dev/null
@@ -1,38 +0,0 @@
-[
- {
- "asset_category_name": "Furnitures",
- "depreciation_method": "Straight Line",
- "total_number_of_depreciations": 5,
- "frequency_of_depreciation": 12,
- "accounts": [{
- "company_name": "Wind Power LLC",
- "fixed_asset_account": "Furnitures and Fixtures - WPL",
- "accumulated_depreciation_account": "Accumulated Depreciation - WPL",
- "depreciation_expense_account": "Depreciation - WPL"
- }]
- },
- {
- "asset_category_name": "Electronic Equipments",
- "depreciation_method": "Double Declining Balance",
- "total_number_of_depreciations": 10,
- "frequency_of_depreciation": 6,
- "accounts": [{
- "company_name": "Wind Power LLC",
- "fixed_asset_account": "Electronic Equipments - WPL",
- "accumulated_depreciation_account": "Accumulated Depreciation - WPL",
- "depreciation_expense_account": "Depreciation - WPL"
- }]
- },
- {
- "asset_category_name": "Softwares",
- "depreciation_method": "Straight Line",
- "total_number_of_depreciations": 10,
- "frequency_of_depreciation": 12,
- "accounts": [{
- "company_name": "Wind Power LLC",
- "fixed_asset_account": "Softwares - WPL",
- "accumulated_depreciation_account": "Accumulated Depreciation - WPL",
- "depreciation_expense_account": "Depreciation - WPL"
- }]
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/bom.json b/erpnext/demo/data/bom.json
deleted file mode 100644
index 3085435..0000000
--- a/erpnext/demo/data/bom.json
+++ /dev/null
@@ -1,180 +0,0 @@
-[
- {
- "item": "Bearing Assembly",
- "items": [
- {
- "item_code": "Base Bearing Plate",
- "qty": 1.0,
- "rate": 15.0
- },
- {
- "item_code": "Bearing Block",
- "qty": 1.0,
- "rate": 10.0
- },
- {
- "item_code": "Bearing Collar",
- "qty": 2.0,
- "rate": 20.0
- },
- {
- "item_code": "Bearing Pipe",
- "qty": 1.0,
- "rate": 15.0
- },
- {
- "item_code": "Upper Bearing Plate",
- "qty": 1.0,
- "rate": 50.0
- }
- ]
- },
- {
- "item": "Wind Mill A Series",
- "items": [
- {
- "item_code": "Base Bearing Plate",
- "qty": 1.0,
- "rate": 15.0
- },
- {
- "item_code": "Base Plate",
- "qty": 1.0,
- "rate": 20.0
- },
- {
- "item_code": "Bearing Block",
- "qty": 1.0,
- "rate": 10.0
- },
- {
- "item_code": "Bearing Pipe",
- "qty": 1.0,
- "rate": 15.0
- },
- {
- "item_code": "External Disc",
- "qty": 1.0,
- "rate": 45.0
- },
- {
- "item_code": "Shaft",
- "qty": 1.0,
- "rate": 30.0
- },
- {
- "item_code": "Wing Sheet",
- "qty": 4.0,
- "rate": 22.0
- }
- ]
- },
- {
- "item": "Wind MIll C Series",
- "items": [
- {
- "item_code": "Base Plate",
- "qty": 2.0,
- "rate": 20.0
- },
- {
- "item_code": "Internal Disc",
- "qty": 1.0,
- "rate": 33.0
- },
- {
- "item_code": "External Disc",
- "qty": 1.0,
- "rate": 45.0
- },
- {
- "item_code": "Bearing Assembly",
- "qty": 1.0,
- "rate": 130.0
- },
- {
- "item_code": "Wing Sheet",
- "qty": 3.0,
- "rate": 22.0
- }
- ]
- },
- {
- "item": "Wind Turbine-S",
- "with_operations": 1,
- "operations": [
- {
- "operation": "Prepare Frame",
- "time_in_mins": 30.0,
- "workstation": "Drilling Machine 1"
- },
- {
- "operation": "Setup Fixtures",
- "time_in_mins": 15.0,
- "workstation": "Assembly Station 1"
- },
- {
- "operation": "Assembly Operation",
- "time_in_mins": 30.0,
- "workstation": "Assembly Station 1"
- },
- {
- "operation": "Wiring",
- "time_in_mins": 20.0,
- "workstation": "Assembly Station 1"
- },
- {
- "operation": "Testing",
- "time_in_mins": 10.0,
- "workstation": "Packing and Testing Station"
- },
- {
- "operation": "Packing",
- "time_in_mins": 25.0,
- "workstation": "Packing and Testing Station"
- }
- ],
- "items": [
- {
- "item_code": "Base Bearing Plate",
- "qty": 1.0,
- "rate": 15.0
- },
- {
- "item_code": "Base Plate",
- "qty": 1.0,
- "rate": 20.0
- },
- {
- "item_code": "Bearing Collar",
- "qty": 1.0,
- "rate": 20.0
- },
- {
- "item_code": "Blade Rib",
- "qty": 1.0,
- "rate": 10.0
- },
- {
- "item_code": "Shaft",
- "qty": 1.0,
- "rate": 30.0
- },
- {
- "item_code": "Wing Sheet",
- "qty": 2.0,
- "rate": 22.0
- }
- ]
- },
- {
- "item": "Base Plate",
- "items": [
- {
- "item_code": "Base Plate Un Painted",
- "qty": 1.0,
- "rate": 16.0
- }
- ]
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/contact.json b/erpnext/demo/data/contact.json
deleted file mode 100644
index 113b561..0000000
--- a/erpnext/demo/data/contact.json
+++ /dev/null
@@ -1,164 +0,0 @@
-[
- {
- "email_id": "JanVaclavik@example.com",
- "first_name": "January",
- "last_name": "V\u00e1clav\u00edk",
- "links": [{"link_doctype": "Customer", "link_name": "Adaptas"}]
- },
- {
- "email_id": "ChidumagaTobeolisa@example.com",
- "first_name": "Chidumaga",
- "last_name": "Tobeolisa",
- "links": [{"link_doctype": "Customer", "link_name": "Asian Fusion"}]
- },
- {
- "email_id": "JanaKubanova@example.com",
- "first_name": "Jana",
- "last_name": "Kub\u00e1\u0148ov\u00e1",
- "links": [{"link_doctype": "Customer", "link_name": "Asian Junction"}]
- },
- {
- "email_id": "XuChaoXuan@example.com",
- "first_name": "\u7d39\u8431",
- "last_name": "\u4e8e",
- "links": [{"link_doctype": "Customer", "link_name": "Big D Supermarkets"}]
- },
- {
- "email_id": "OzlemVerwijmeren@example.com",
- "first_name": "\u00d6zlem",
- "last_name": "Verwijmeren",
- "links": [{"link_doctype": "Customer", "link_name": "Buttrey Food & Drug"}]
- },
- {
- "email_id": "HansRasmussen@example.com",
- "first_name": "Hans",
- "last_name": "Rasmussen",
- "links": [{"link_doctype": "Customer", "link_name": "Chi-Chis"}]
- },
- {
- "email_id": "SatomiShigeki@example.com",
- "first_name": "Satomi",
- "last_name": "Shigeki",
- "links": [{"link_doctype": "Customer", "link_name": "Choices"}]
- },
- {
- "email_id": "SimonVJessen@example.com",
- "first_name": "Simon",
- "last_name": "Jessen",
- "links": [{"link_doctype": "Customer", "link_name": "Consumers and Consumers Express"}]
- },
- {
- "email_id": "NeguaranShahsaah@example.com",
- "first_name": "\u0646\u06af\u0627\u0631\u06cc\u0646",
- "last_name": "\u0634\u0627\u0647 \u0633\u06cc\u0627\u0647",
- "links": [{"link_doctype": "Customer", "link_name": "Crafts Canada"}]
- },
- {
- "email_id": "Lom-AliBataev@example.com",
- "first_name": "Lom-Ali",
- "last_name": "Bataev",
- "links": [{"link_doctype": "Customer", "link_name": "Endicott Shoes"}]
- },
- {
- "email_id": "VanNgocTien@example.com",
- "first_name": "Ti\u00ean",
- "last_name": "V\u0103n",
- "links": [{"link_doctype": "Customer", "link_name": "Fayva"}]
- },
- {
- "email_id": "QuimeyOsorioRuelas@example.com",
- "first_name": "Quimey",
- "last_name": "Osorio",
- "links": [{"link_doctype": "Customer", "link_name": "Intelacard"}]
- },
- {
- "email_id": "EdgardaSalcedoRaya@example.com",
- "first_name": "Edgarda",
- "last_name": "Salcedo",
- "links": [{"link_doctype": "Customer", "link_name": "Landskip Yard Care"}]
- },
- {
- "email_id": "HafsteinnBjarnarsonar@example.com",
- "first_name": "Hafsteinn",
- "last_name": "Bjarnarsonar",
- "links": [{"link_doctype": "Customer", "link_name": "Life Plan Counselling"}]
- },
- {
- "email_id": "\u0434\u0430\u043d\u0438\u0438\u043b@example.com",
- "first_name": "\u0414\u0430\u043d\u0438\u0438\u043b",
- "last_name": "\u041a\u043e\u043d\u043e\u0432\u0430\u043b\u043e\u0432",
- "links": [{"link_doctype": "Customer", "link_name": "Mr Fables"}]
- },
- {
- "email_id": "SelmaMAndersen@example.com",
- "first_name": "Selma",
- "last_name": "Andersen",
- "links": [{"link_doctype": "Customer", "link_name": "Nelson Brothers"}]
- },
- {
- "email_id": "LadislavKolaja@example.com",
- "first_name": "Ladislav",
- "last_name": "Kolaja",
- "links": [{"link_doctype": "Customer", "link_name": "Netobill"}]
- },
- {
- "links": [{"link_doctype": "Supplier", "link_name": "Helios Air"}],
- "email_id": "TewoldeAbaalom@example.com",
- "first_name": "Tewolde",
- "last_name": "Abaalom"
- },
- {
- "links": [{"link_doctype": "Supplier", "link_name": "Ks Merchandise"}],
- "email_id": "LeilaFernandesRodrigues@example.com",
- "first_name": "Leila",
- "last_name": "Rodrigues"
- },
- {
- "links": [{"link_doctype": "Supplier", "link_name": "HomeBase"}],
- "email_id": "DmitryBulgakov@example.com",
- "first_name": "Dmitry",
- "last_name": "Bulgakov"
- },
- {
- "links": [{"link_doctype": "Supplier", "link_name": "Scott Ties"}],
- "email_id": "HaiducWhitfoot@example.com",
- "first_name": "Haiduc",
- "last_name": "Whitfoot"
- },
- {
- "links": [{"link_doctype": "Supplier", "link_name": "Reliable Investments"}],
- "email_id": "SesseljaPetursdottir@example.com",
- "first_name": "Sesselja",
- "last_name": "P\u00e9tursd\u00f3ttir"
- },
- {
- "links": [{"link_doctype": "Supplier", "link_name": "Nan Duskin"}],
- "email_id": "HajdarPignar@example.com",
- "first_name": "Hajdar",
- "last_name": "Pignar"
- },
- {
- "links": [{"link_doctype": "Supplier", "link_name": "Rainbow Records"}],
- "email_id": "GustavaLorenzo@example.com",
- "first_name": "Gustava",
- "last_name": "Lorenzo"
- },
- {
- "links": [{"link_doctype": "Supplier", "link_name": "New World Realty"}],
- "email_id": "BethanyWood@example.com",
- "first_name": "Bethany",
- "last_name": "Wood"
- },
- {
- "links": [{"link_doctype": "Supplier", "link_name": "Asiatic Solutions"}],
- "email_id": "GlorianaBrownlock@example.com",
- "first_name": "Gloriana",
- "last_name": "Brownlock"
- },
- {
- "links": [{"link_doctype": "Supplier", "link_name": "Eagle Hardware"}],
- "email_id": "JensonFraser@gustr.com",
- "first_name": "Jenson",
- "last_name": "Fraser"
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/course.json b/erpnext/demo/data/course.json
deleted file mode 100644
index 15728d5..0000000
--- a/erpnext/demo/data/course.json
+++ /dev/null
@@ -1,134 +0,0 @@
-[
- {
- "doctype": "Course",
- "course_name": "Communication Skiils",
- "course_code": "BCA2040",
- "department": "Information Technology"
- },
- {
- "doctype": "Course",
- "course_name": "Object Oriented Programing - C++",
- "course_code": "BCA2030",
- "department": "Information Technology"
- },
- {
- "doctype": "Course",
- "course_name": "Data Structures and Algorithm",
- "course_code": "BCA2020",
- "department": "Information Technology"
- },
- {
- "doctype": "Course",
- "course_name": "Operating System",
- "course_code": "BCA2010",
- "department": "Information Technology"
- },
- {
- "doctype": "Course",
- "course_name": "Digital Logic",
- "course_code": "BCA1040",
- "department": "Information Technology"
- },
- {
- "doctype": "Course",
- "course_name": "Basic Mathematics",
- "course_code": "BCA1030",
- "department": "Information Technology"
- },
- {
- "doctype": "Course",
- "course_name": "Programing in C",
- "course_code": "BCA1020",
- "department": "Information Technology"
- },
- {
- "doctype": "Course",
- "course_name": "Fundamentals of IT & Programing",
- "course_code": "BCA1010",
- "department": "Information Technology"
- },
- {
- "doctype": "Course",
- "course_name": "Microprocessor",
- "course_code": "MCA4010",
- "department": "Information Technology"
- },
- {
- "doctype": "Course",
- "course_name": "Probability and Statistics",
- "course_code": "MCA4020",
- "department": "Information Technology"
- },
- {
- "doctype": "Course",
- "course_name": "Programing in Java",
- "course_code": "MCA4030",
- "department": "Information Technology"
- },
- {
- "doctype": "Course",
- "course_name": "Communication Skills",
- "course_code": "BBA 101",
- "department": "Management Studies"
- },
- {
- "doctype": "Course",
- "course_name": "Organizational Behavior",
- "course_code": "BBA 102",
- "department": "Management Studies"
- },
- {
- "doctype": "Course",
- "course_name": "Business Environment",
- "course_code": "BBA 103",
- "department": "Management Studies"
- },
- {
- "doctype": "Course",
- "course_name": "Legal and Regulatory Framework",
- "course_code": "BBA 301",
- "department": "Management Studies"
- },
- {
- "doctype": "Course",
- "course_name": "Human Resource Management",
- "course_code": "BBA 302",
- "department": "Management Studies"
- },
- {
- "doctype": "Course",
- "course_name": "Advertising and Sales",
- "course_code": "BBA 304",
- "department": "Management Studies"
- },
- {
- "doctype": "Course",
- "course_name": "Entrepreneurship Management",
- "course_code": "BBA 505",
- "department": "Management Studies"
- },
- {
- "doctype": "Course",
- "course_name": "Visual Merchandising",
- "course_code": "BBR 504",
- "department": "Management Studies"
- },
- {
- "doctype": "Course",
- "course_name": "Warehouse Management",
- "course_code": "BBR 505",
- "department": "Management Studies"
- },
- {
- "doctype": "Course",
- "course_name": "Store Operations and Job Knowledge",
- "course_code": "BBR 501",
- "department": "Management Studies"
- },
- {
- "doctype": "Course",
- "course_name": "Management Development and Skills",
- "course_code": "BBA 602",
- "department": "Management Studies"
- }
-]
diff --git a/erpnext/demo/data/department.json b/erpnext/demo/data/department.json
deleted file mode 100644
index f4355ba..0000000
--- a/erpnext/demo/data/department.json
+++ /dev/null
@@ -1,30 +0,0 @@
-[
- {
- "doctype": "Department",
- "department_name": "Information Technology"
- },
- {
- "doctype": "Department",
- "department_name": "Physics"
- },
- {
- "doctype": "Department",
- "department_name": "Chemistry"
- },
- {
- "doctype": "Department",
- "department_name": "Biology"
- },
- {
- "doctype": "Department",
- "department_name": "Commerce"
- },
- {
- "doctype": "Department",
- "department_name": "English"
- },
- {
- "doctype": "Department",
- "department_name": "Management Studies"
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/drug_list.json b/erpnext/demo/data/drug_list.json
deleted file mode 100644
index 3069042..0000000
--- a/erpnext/demo/data/drug_list.json
+++ /dev/null
@@ -1,5111 +0,0 @@
-[
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Atocopherol",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Atocopherol",
- "item_group": "Drug",
- "item_name": "Atocopherol",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
-
-
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:16.577151",
- "name": "Atocopherol",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Abacavir",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Abacavir",
- "item_group": "Drug",
- "item_name": "Abacavir",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
-
-
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:16.678257",
- "name": "Abacavir",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Abciximab",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Abciximab",
- "item_group": "Drug",
- "item_name": "Abciximab",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:16.695413",
- "name": "Abciximab",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Acacia",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Acacia",
- "item_group": "Drug",
- "item_name": "Acacia",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:16.797774",
- "name": "Acacia",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Acamprosate",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Acamprosate",
- "item_group": "Drug",
- "item_name": "Acamprosate",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:16.826952",
- "name": "Acamprosate",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Acarbose",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Acarbose",
- "item_group": "Drug",
- "item_name": "Acarbose",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:16.843890",
- "name": "Acarbose",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Acebrofylline",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Acebrofylline",
- "item_group": "Drug",
- "item_name": "Acebrofylline",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:16.969984",
- "name": "Acebrofylline",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Acebrofylline (SR)",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Acebrofylline (SR)",
- "item_group": "Drug",
- "item_name": "Acebrofylline (SR)",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:16.987354",
- "name": "Acebrofylline (SR)",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Aceclofenac",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Aceclofenac",
- "item_group": "Drug",
- "item_name": "Aceclofenac",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.004369",
- "name": "Aceclofenac",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Ash",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Ash",
- "item_group": "Drug",
- "item_name": "Ash",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.021192",
- "name": "Ash",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Asparaginase",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Asparaginase",
- "item_group": "Drug",
- "item_name": "Asparaginase",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.038058",
- "name": "Asparaginase",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Aspartame",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Aspartame",
- "item_group": "Drug",
- "item_name": "Aspartame",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.054463",
- "name": "Aspartame",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Aspartic Acid",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Aspartic Acid",
- "item_group": "Drug",
- "item_name": "Aspartic Acid",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.071001",
- "name": "Aspartic Acid",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Bleomycin",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Bleomycin",
- "item_group": "Drug",
- "item_name": "Bleomycin",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.087170",
- "name": "Bleomycin",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Bleomycin Sulphate",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Bleomycin Sulphate",
- "item_group": "Drug",
- "item_name": "Bleomycin Sulphate",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.103691",
- "name": "Bleomycin Sulphate",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Blue cap contains",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Blue cap contains",
- "item_group": "Drug",
- "item_name": "Blue cap contains",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.120040",
- "name": "Blue cap contains",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Boran",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Boran",
- "item_group": "Drug",
- "item_name": "Boran",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.135964",
- "name": "Boran",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Borax",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Borax",
- "item_group": "Drug",
- "item_name": "Borax",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.152575",
- "name": "Borax",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Chlorbutanol",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Chlorbutanol",
- "item_group": "Drug",
- "item_name": "Chlorbutanol",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.168998",
- "name": "Chlorbutanol",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Chlorbutol",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Chlorbutol",
- "item_group": "Drug",
- "item_name": "Chlorbutol",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.185316",
- "name": "Chlorbutol",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Chlordiazepoxide",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Chlordiazepoxide",
- "item_group": "Drug",
- "item_name": "Chlordiazepoxide",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.208361",
- "name": "Chlordiazepoxide",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Chlordiazepoxide and Clidinium Bromide",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Chlordiazepoxide and Clidinium Bromide",
- "item_group": "Drug",
- "item_name": "Chlordiazepoxide and Clidinium Bromide",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.224341",
- "name": "Chlordiazepoxide and Clidinium Bromide",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Chlorhexidine",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Chlorhexidine",
- "item_group": "Drug",
- "item_name": "Chlorhexidine",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.240634",
- "name": "Chlorhexidine",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Chlorhexidine 40%",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Chlorhexidine 40%",
- "item_group": "Drug",
- "item_name": "Chlorhexidine 40%",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.256922",
- "name": "Chlorhexidine 40%",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Chlorhexidine Acetate",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Chlorhexidine Acetate",
- "item_group": "Drug",
- "item_name": "Chlorhexidine Acetate",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.274789",
- "name": "Chlorhexidine Acetate",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Chlorhexidine Gluconate",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Chlorhexidine Gluconate",
- "item_group": "Drug",
- "item_name": "Chlorhexidine Gluconate",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.295371",
- "name": "Chlorhexidine Gluconate",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Chlorhexidine HCL",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Chlorhexidine HCL",
- "item_group": "Drug",
- "item_name": "Chlorhexidine HCL",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.312916",
- "name": "Chlorhexidine HCL",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Chlorhexidine Hydrochloride",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Chlorhexidine Hydrochloride",
- "item_group": "Drug",
- "item_name": "Chlorhexidine Hydrochloride",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.329570",
- "name": "Chlorhexidine Hydrochloride",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Chloride",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Chloride",
- "item_group": "Drug",
- "item_name": "Chloride",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.346088",
- "name": "Chloride",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Fosfomycin Tromethamine",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Fosfomycin Tromethamine",
- "item_group": "Drug",
- "item_name": "Fosfomycin Tromethamine",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.362777",
- "name": "Fosfomycin Tromethamine",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Fosinopril",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Fosinopril",
- "item_group": "Drug",
- "item_name": "Fosinopril",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.379465",
- "name": "Fosinopril",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Iodochlorhydroxyquinoline",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Iodochlorhydroxyquinoline",
- "item_group": "Drug",
- "item_name": "Iodochlorhydroxyquinoline",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.396068",
- "name": "Iodochlorhydroxyquinoline",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Iodochlorohydroxyquinoline",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Iodochlorohydroxyquinoline",
- "item_group": "Drug",
- "item_name": "Iodochlorohydroxyquinoline",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.412734",
- "name": "Iodochlorohydroxyquinoline",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Ipratropium",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Ipratropium",
- "item_group": "Drug",
- "item_name": "Ipratropium",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.429333",
- "name": "Ipratropium",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Mebeverine hydrochloride",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Mebeverine hydrochloride",
- "item_group": "Drug",
- "item_name": "Mebeverine hydrochloride",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.445814",
- "name": "Mebeverine hydrochloride",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Mecetronium ethylsulphate",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Mecetronium ethylsulphate",
- "item_group": "Drug",
- "item_name": "Mecetronium ethylsulphate",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.461696",
- "name": "Mecetronium ethylsulphate",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Meclizine",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Meclizine",
- "item_group": "Drug",
- "item_name": "Meclizine",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.478020",
- "name": "Meclizine",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Oxaprozin",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Oxaprozin",
- "item_group": "Drug",
- "item_name": "Oxaprozin",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
-
-
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.496221",
- "name": "Oxaprozin",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Oxazepam",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Oxazepam",
- "item_group": "Drug",
- "item_name": "Oxazepam",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.511933",
- "name": "Oxazepam",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Oxcarbazepine",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Oxcarbazepine",
- "item_group": "Drug",
- "item_name": "Oxcarbazepine",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.528472",
- "name": "Oxcarbazepine",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Oxetacaine",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Oxetacaine",
- "item_group": "Drug",
- "item_name": "Oxetacaine",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.544177",
- "name": "Oxetacaine",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Oxethazaine",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Oxethazaine",
- "item_group": "Drug",
- "item_name": "Oxethazaine",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.560193",
- "name": "Oxethazaine",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Suxamethonium Chloride",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Suxamethonium Chloride",
- "item_group": "Drug",
- "item_name": "Suxamethonium Chloride",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.576447",
- "name": "Suxamethonium Chloride",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Tacrolimus",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Tacrolimus",
- "item_group": "Drug",
- "item_name": "Tacrolimus",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.593481",
- "name": "Tacrolimus",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Ubiquinol",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Ubiquinol",
- "item_group": "Drug",
- "item_name": "Ubiquinol",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.609930",
- "name": "Ubiquinol",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Vitamin B12",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Vitamin B12",
- "item_group": "Drug",
- "item_name": "Vitamin B12",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.626225",
- "name": "Vitamin B12",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Vitamin B1Hydrochloride",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Vitamin B1Hydrochloride",
- "item_group": "Drug",
- "item_name": "Vitamin B1Hydrochloride",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.642423",
- "name": "Vitamin B1Hydrochloride",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Vitamin B1Monohydrate",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Vitamin B1Monohydrate",
- "item_group": "Drug",
- "item_name": "Vitamin B1Monohydrate",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.658946",
- "name": "Vitamin B1Monohydrate",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Vitamin B2",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Vitamin B2",
- "item_group": "Drug",
- "item_name": "Vitamin B2",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.675234",
- "name": "Vitamin B2",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Vitamin B3",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Vitamin B3",
- "item_group": "Drug",
- "item_name": "Vitamin B3",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.691598",
- "name": "Vitamin B3",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Vitamin D4",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Vitamin D4",
- "item_group": "Drug",
- "item_name": "Vitamin D4",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.707840",
- "name": "Vitamin D4",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Vitamin E",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Vitamin E",
- "item_group": "Drug",
- "item_name": "Vitamin E",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.723859",
- "name": "Vitamin E",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Wheat Germ Oil",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Wheat Germ Oil",
- "item_group": "Drug",
- "item_name": "Wheat Germ Oil",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.739829",
- "name": "Wheat Germ Oil",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Wheatgrass extr",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Wheatgrass extr",
- "item_group": "Drug",
- "item_name": "Wheatgrass extr",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.757695",
- "name": "Wheatgrass extr",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Whey Protein",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Whey Protein",
- "item_group": "Drug",
- "item_name": "Whey Protein",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.774098",
- "name": "Whey Protein",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Xylometazoline",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Xylometazoline",
- "item_group": "Drug",
- "item_name": "Xylometazoline",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.790224",
- "name": "Xylometazoline",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Xylometazoline Hydrochloride",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Xylometazoline Hydrochloride",
- "item_group": "Drug",
- "item_name": "Xylometazoline Hydrochloride",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.806359",
- "name": "Xylometazoline Hydrochloride",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Yeast",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Yeast",
- "item_group": "Drug",
- "item_name": "Yeast",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.823305",
- "name": "Yeast",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Yellow Fever Vaccine",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Yellow Fever Vaccine",
- "item_group": "Drug",
- "item_name": "Yellow Fever Vaccine",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.840250",
- "name": "Yellow Fever Vaccine",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Zafirlukast",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Zafirlukast",
- "item_group": "Drug",
- "item_name": "Zafirlukast",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.856856",
- "name": "Zafirlukast",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Zaleplon",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Zaleplon",
- "item_group": "Drug",
- "item_name": "Zaleplon",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.873287",
- "name": "Zaleplon",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Zaltoprofen",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Zaltoprofen",
- "item_group": "Drug",
- "item_name": "Zaltoprofen",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.889263",
- "name": "Zaltoprofen",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- },
- {
- "asset_category": null,
- "attributes": [],
- "barcode": null,
- "brand": null,
- "buying_cost_center": null,
- "country_of_origin": null,
- "create_new_batch": 0,
- "customer_code": "",
- "customer_items": [],
- "customs_tariff_number": null,
- "default_bom": null,
- "default_material_request_type": null,
- "default_supplier": null,
- "default_warehouse": null,
- "delivered_by_supplier": 0,
- "description": "Zanamivir",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Item",
- "end_of_life": null,
- "expense_account": null,
- "gst_hsn_code": null,
- "has_batch_no": 0,
- "has_serial_no": 0,
- "has_variants": 0,
- "image": null,
- "income_account": null,
- "inspection_required_before_delivery": 0,
- "inspection_required_before_purchase": 0,
- "is_fixed_asset": 0,
- "is_purchase_item": 1,
- "is_sales_item": 1,
- "is_stock_item": 1,
- "is_sub_contracted_item": 0,
- "item_code": "Zanamivir",
- "item_group": "Drug",
- "item_name": "Zanamivir",
- "last_purchase_rate": 0.0,
- "lead_time_days": 0,
- "max_discount": 0.0,
- "min_order_qty": 0.0,
- "modified": "2017-07-06 12:53:17.905022",
- "name": "Zanamivir",
- "naming_series": null,
- "net_weight": 0.0,
- "opening_stock": 0.0,
- "quality_parameters": [],
- "reorder_levels": [],
- "route": null,
- "safety_stock": 0.0,
- "selling_cost_center": null,
- "serial_no_series": null,
- "show_in_website": 0,
- "show_variant_in_website": 0,
- "slideshow": null,
- "standard_rate": 0.0,
- "stock_uom": "Nos",
- "supplier_items": [],
- "taxes": [],
- "thumbnail": null,
- "tolerance": 0.0,
- "uoms": [
- {
- "conversion_factor": 1.0,
- "uom": "Nos"
- }
- ],
- "valuation_method": null,
- "valuation_rate": 0.0,
- "variant_based_on": null,
- "variant_of": null,
- "warranty_period": null,
- "web_long_description": null,
- "website_image": null,
- "website_item_groups": [],
- "website_specifications": [],
- "website_warehouse": null,
- "weight_uom": null,
- "weightage": 0
- }
-]
diff --git a/erpnext/demo/data/employee.json b/erpnext/demo/data/employee.json
deleted file mode 100644
index 2d2dbe8..0000000
--- a/erpnext/demo/data/employee.json
+++ /dev/null
@@ -1,92 +0,0 @@
-[
- {
- "date_of_birth": "1982-01-03",
- "date_of_joining": "2001-10-10",
- "employee_name": "Diana Prince",
- "first_name": "Diana",
- "last_name": "Prince",
- "gender": "Female",
- "user_id": "DianaPrince@example.com"
- },
- {
- "date_of_birth": "1959-02-03",
- "date_of_joining": "1976-09-16",
- "employee_name": "Zatanna Zatara",
- "gender": "Female",
- "user_id": "ZatannaZatara@example.com",
- "first_name": "Zatanna",
- "last_name": "Zatara"
- },
- {
- "date_of_birth": "1982-03-03",
- "date_of_joining": "2000-06-16",
- "employee_name": "Holly Granger",
- "gender": "Female",
- "user_id": "HollyGranger@example.com",
- "first_name": "Holly",
- "last_name": "Granger"
- },
- {
- "date_of_birth": "1945-04-04",
- "date_of_joining": "1969-07-01",
- "employee_name": "Neptunia Aquaria",
- "gender": "Female",
- "user_id": "NeptuniaAquaria@example.com",
- "first_name": "Neptunia",
- "last_name": "Aquaria"
- },
- {
- "date_of_birth": "1978-05-03",
- "date_of_joining": "1999-12-24",
- "employee_name": "Arthur Curry",
- "gender": "Male",
- "user_id": "ArthurCurry@example.com",
- "first_name": "Arthur",
- "last_name": "Curry"
- },
- {
- "date_of_birth": "1964-06-03",
- "date_of_joining": "1981-08-05",
- "employee_name": "Thalia Al Ghul",
- "gender": "Female",
- "user_id": "ThaliaAlGhul@example.com",
- "first_name": "Thalia",
- "last_name": "Al Ghul"
- },
- {
- "date_of_birth": "1982-07-03",
- "date_of_joining": "2006-06-10",
- "employee_name": "Maxwell Lord",
- "gender": "Male",
- "user_id": "MaxwellLord@example.com",
- "first_name": "Maxwell",
- "last_name": "Lord"
- },
- {
- "date_of_birth": "1969-08-03",
- "date_of_joining": "1993-10-21",
- "employee_name": "Grace Choi",
- "gender": "Female",
- "user_id": "GraceChoi@example.com",
- "first_name": "Grace",
- "last_name": "Choi"
- },
- {
- "date_of_birth": "1982-09-03",
- "date_of_joining": "2005-09-06",
- "employee_name": "Vandal Savage",
- "gender": "Male",
- "user_id": "VandalSavage@example.com",
- "first_name": "Vandal",
- "last_name": "Savage"
- },
- {
- "date_of_birth": "1985-10-03",
- "date_of_joining": "2007-12-25",
- "employee_name": "Caitlin Snow",
- "gender": "Female",
- "user_id": "CaitlinSnow@example.com",
- "first_name": "Caitlin",
- "last_name": "Snow"
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/grading_scale.json b/erpnext/demo/data/grading_scale.json
deleted file mode 100644
index 0760919..0000000
--- a/erpnext/demo/data/grading_scale.json
+++ /dev/null
@@ -1,17 +0,0 @@
-[
- {
- "doctype": "Grading Scale",
- "grading_scale_name": "Standard Grading",
- "description": "Standard Grading Scale",
- "intervals": [
- {"threshold": 100.0, "grade_code": "A", "grade_description": "Excellent"},
- {"threshold": 89.9, "grade_code": "B+", "grade_description": "Close to Excellence"},
- {"threshold": 80.0, "grade_code": "B", "grade_description": "Good"},
- {"threshold": 69.9, "grade_code": "C+", "grade_description": "Almost Good"},
- {"threshold": 60.0, "grade_code": "C", "grade_description": "Average"},
- {"threshold": 50.0, "grade_code": "D+", "grade_description": "Have to Work"},
- {"threshold": 40.0, "grade_code": "D", "grade_description": "Not met Baseline Expectations"},
- {"threshold": 0.0, "grade_code": "F", "grade_description": "Have to work a lot"}
- ]
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/instructor.json b/erpnext/demo/data/instructor.json
deleted file mode 100644
index a25d163..0000000
--- a/erpnext/demo/data/instructor.json
+++ /dev/null
@@ -1,128 +0,0 @@
-[
- {
- "doctype": "Instructor",
- "instructor_name": "Eddie Jessup",
- "naming_series": "INS/",
- "department": "Information Technology"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "William Dyer",
- "naming_series": "INS/",
- "department": "Information Technology"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Alastor Moody",
- "naming_series": "INS/",
- "department": "Information Technology"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Charles Xavier",
- "naming_series": "INS/",
- "department": "Information Technology"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Cuthbert Calculus",
- "naming_series": "INS/",
- "department": "Information Technology"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Reed Richards",
- "naming_series": "INS/",
- "department": "Information Technology"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Urban Chronotis",
- "naming_series": "INS/",
- "department": "Physics"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "River Song",
- "naming_series": "INS/",
- "department": "Physics"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Yana",
- "naming_series": "INS/",
- "department": "Physics"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Neil Lasrado",
- "naming_series": "INS/",
- "department": "Information Technology"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Deepshi Garg",
- "naming_series": "INS/",
- "department": "Chemistry"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Shubham Saxena",
- "naming_series": "INS/",
- "department": "Physics"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Rushabh Mehta",
- "naming_series": "INS/",
- "department": "Information Technology"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Umari Syed",
- "naming_series": "INS/",
- "department": "Chemistry"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Aman Singh",
- "naming_series": "INS/",
- "department": "Physics"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Nabin",
- "naming_series": "INS/",
- "department": "Chemistry"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Kanchan Chauhan",
- "naming_series": "INS/",
- "department": "Information Technology"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Valmik Jangla",
- "naming_series": "INS/",
- "department": "Chemistry"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Amit Jain",
- "naming_series": "INS/",
- "department": "Physics"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Shreyas P",
- "naming_series": "INS/",
- "department": "Chemistry"
- },
- {
- "doctype": "Instructor",
- "instructor_name": "Rohit",
- "naming_series": "INS/",
- "department": "Information Technology"
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/item.json b/erpnext/demo/data/item.json
deleted file mode 100644
index 1d4ed34..0000000
--- a/erpnext/demo/data/item.json
+++ /dev/null
@@ -1,493 +0,0 @@
-[
- {
- "item_defaults": [
- {
- "default_supplier": "Asiatic Solutions",
- "default_warehouse": "Stores"
- }
- ],
- "description": "For Upper Bearing",
- "image": "/assets/erpnext_demo/images/disc.png",
- "item_code": "Disc Collars",
- "item_group": "Raw Material",
- "item_name": "Disc Collars"
- },
- {
- "item_defaults": [
- {
- "default_supplier": "Nan Duskin",
- "default_warehouse": "Stores"
- }
- ],
- "description": "CAST IRON, MCMASTER PART NO. 3710T13",
- "image": "/assets/erpnext_demo/images/bearing.jpg",
- "item_code": "Bearing Block",
- "item_group": "Raw Material",
- "item_name": "Bearing Block"
- },
- {
- "item_defaults": [
- {
- "default_supplier": null,
- "default_warehouse": "Finished Goods"
- }
- ],
- "description": "Wind Mill C Series for Commercial Use 18ft",
- "image": "/assets/erpnext_demo/images/wind-turbine-2.png",
- "item_code": "Wind MIll C Series",
- "item_group": "Products",
- "item_name": "Wind MIll C Series"
- },
- {
- "item_defaults": [
- {
- "default_supplier": null,
- "default_warehouse": "Finished Goods"
- }
- ],
- "description": "Wind Mill A Series for Home Use 9ft",
- "image": "/assets/erpnext_demo/images/wind-turbine.png",
- "item_code": "Wind Mill A Series",
- "item_group": "Products",
- "item_name": "Wind Mill A Series"
- },
- {
- "item_defaults": [
- {
- "default_supplier": null,
- "default_warehouse": "Finished Goods"
- }
- ],
- "description": "Small Wind Turbine for Home Use\n\n\n<!-- html -->",
- "image": "/assets/erpnext_demo/images/wind-turbine-1.jpg",
- "item_code": "Wind Turbine",
- "item_group": "Products",
- "item_name": "Wind Turbine",
- "has_variants": 1,
- "has_serial_no": 1,
- "attributes": [
- {
- "attribute": "Size"
- }
- ]
- },
- {
- "item_defaults": [
- {
- "default_supplier": "HomeBase",
- "default_warehouse": "Stores"
- }
- ],
- "description": "1.5 in. Diameter x 36 in. Mild Steel Tubing",
- "image": null,
- "item_code": "Bearing Pipe",
- "item_group": "Raw Material",
- "item_name": "Bearing Pipe"
- },
- {
- "item_defaults": [
- {
- "default_supplier": "New World Realty",
- "default_warehouse": "Stores"
- }
- ],
- "description": "1/32 in. x 24 in. x 47 in. HDPE Opaque Sheet",
- "image": null,
- "item_code": "Wing Sheet",
- "item_group": "Raw Material",
- "item_name": "Wing Sheet"
- },
- {
- "item_defaults": [
- {
- "default_supplier": "Eagle Hardware",
- "default_warehouse": "Stores"
- }
- ],
- "description": "3/16 in. x 6 in. x 6 in. Low Carbon Steel Plate",
- "image": null,
- "item_code": "Upper Bearing Plate",
- "item_group": "Raw Material",
- "item_name": "Upper Bearing Plate"
- },
- {
- "item_defaults": [
- {
- "default_supplier": "Asiatic Solutions",
- "default_warehouse": "Stores"
- }
- ],
- "description": "Bearing Assembly",
- "image": null,
- "item_code": "Bearing Assembly",
- "item_group": "Sub Assemblies",
- "item_name": "Bearing Assembly"
- },
- {
- "item_defaults": [
- {
- "default_supplier": "HomeBase",
- "default_warehouse": "Stores"
- }
- ],
- "description": "3/4 in. x 2 ft. x 4 ft. Pine Plywood",
- "image": null,
- "item_code": "Base Plate",
- "item_group": "Raw Material",
- "item_name": "Base Plate",
- "is_sub_contracted_item": 1
- },
- {
- "item_defaults": [
- {
- "default_supplier": "Scott Ties",
- "default_warehouse": "Stores"
- }
- ],
- "description": "N/A",
- "image": null,
- "item_code": "Stand",
- "item_group": "Raw Material",
- "item_name": "Stand"
- },
- {
- "item_defaults": [
- {
- "default_supplier": "Eagle Hardware",
- "default_warehouse": "Stores"
- }
- ],
- "description": "1 in. x 3 in. x 1 ft. Multipurpose Al Alloy Bar",
- "image": null,
- "item_code": "Bearing Collar",
- "item_group": "Raw Material",
- "item_name": "Bearing Collar"
- },
- {
- "item_defaults": [
- {
- "default_supplier": "Eagle Hardware",
- "default_warehouse": "Stores"
- }
- ],
- "description": "1/4 in. x 6 in. x 6 in. Mild Steel Plate",
- "image": null,
- "item_code": "Base Bearing Plate",
- "item_group": "Raw Material",
- "item_name": "Base Bearing Plate"
- },
- {
- "item_defaults": [
- {
- "default_supplier": "HomeBase",
- "default_warehouse": "Stores"
- }
- ],
- "description": "15/32 in. x 4 ft. x 8 ft. 3-Ply Rtd Sheathing",
- "image": null,
- "item_code": "External Disc",
- "item_group": "Raw Material",
- "item_name": "External Disc"
- },
- {
- "item_defaults": [
- {
- "default_supplier": "Eagle Hardware",
- "default_warehouse": "Stores"
- }
- ],
- "description": "1.25 in. Diameter x 6 ft. Mild Steel Tubing",
- "image": null,
- "item_code": "Shaft",
- "item_group": "Raw Material",
- "item_name": "Shaft"
- },
- {
- "item_defaults": [
- {
- "default_supplier": "Ks Merchandise",
- "default_warehouse": "Stores"
- }
- ],
- "description": "1/2 in. x 2 ft. x 4 ft. Pine Plywood",
- "image": null,
- "item_code": "Blade Rib",
- "item_group": "Raw Material",
- "item_name": "Blade Rib"
- },
- {
- "item_defaults": [
- {
- "default_supplier": "HomeBase",
- "default_warehouse": "Stores"
- }
- ],
- "description": "For Bearing Collar",
- "image": null,
- "item_code": "Internal Disc",
- "item_group": "Raw Material",
- "item_name": "Internal Disc"
- },
- {
- "item_defaults": [
- {
- "default_supplier": null,
- "default_warehouse": "Finished Goods"
- }
- ],
- "description": "Small Wind Turbine for Home Use\n\n\n<!-- html -->\n<p>Size: Small</p>",
- "image": "/assets/erpnext_demo/images/wind-turbine-1.jpg",
- "item_code": "Wind Turbine-S",
- "item_group": "Products",
- "item_name": "Wind Turbine-S",
- "variant_of": "Wind Turbine",
- "valuation_rate": 300,
- "attributes": [
- {
- "attribute": "Size",
- "attribute_value": "Small"
- }
- ]
- },
- {
- "item_defaults": [
- {
- "default_supplier": null,
- "default_warehouse": "Finished Goods"
- }
- ],
- "description": "Small Wind Turbine for Home Use\n\n\n<!-- html -->\n<p>Size: Medium</p>",
- "image": "/assets/erpnext_demo/images/wind-turbine-1.jpg",
- "item_code": "Wind Turbine-M",
- "item_group": "Products",
- "item_name": "Wind Turbine-M",
- "variant_of": "Wind Turbine",
- "valuation_rate": 300,
- "attributes": [
- {
- "attribute": "Size",
- "attribute_value": "Medium"
- }
- ]
- },
- {
- "item_defaults": [
- {
- "default_supplier": null,
- "default_warehouse": "Finished Goods"
- }
- ],
- "description": "Small Wind Turbine for Home Use\n\n\n<!-- html -->\n<p>Size: Large</p>",
- "image": "/assets/erpnext_demo/images/wind-turbine-1.jpg",
- "item_code": "Wind Turbine-L",
- "item_group": "Products",
- "item_name": "Wind Turbine-L",
- "variant_of": "Wind Turbine",
- "valuation_rate": 300,
- "attributes": [
- {
- "attribute": "Size",
- "attribute_value": "Large"
- }
- ]
- },
- {
- "is_stock_item": 0,
- "description": "Wind Mill A Series with Spare Bearing",
- "item_code": "Wind Mill A Series with Spare Bearing",
- "item_group": "Products",
- "item_name": "Wind Mill A Series with Spare Bearing"
- },
- {
- "item_defaults": [
- {
- "default_supplier": "HomeBase",
- "default_warehouse": "Stores"
- }
- ],
- "description": "3/4 in. x 2 ft. x 4 ft. Pine Plywood",
- "image": null,
- "item_code": "Base Plate Un Painted",
- "item_group": "Raw Material",
- "item_name": "Base Plate Un Painted"
- },
- {
- "is_fixed_asset": 1,
- "asset_category": "Furnitures",
- "is_stock_item": 0,
- "description": "Table",
- "item_code": "Table",
- "item_name": "Table",
- "item_group": "Products"
- },
- {
- "is_fixed_asset": 1,
- "asset_category": "Furnitures",
- "is_stock_item": 0,
- "description": "Chair",
- "item_code": "Chair",
- "item_name": "Chair",
- "item_group": "Products"
- },
- {
- "is_fixed_asset": 1,
- "asset_category": "Electronic Equipments",
- "is_stock_item": 0,
- "description": "Computer",
- "item_code": "Computer",
- "item_name": "Computer",
- "item_group": "Products"
- },
- {
- "is_fixed_asset": 1,
- "asset_category": "Electronic Equipments",
- "is_stock_item": 0,
- "description": "Mobile",
- "item_code": "Mobile",
- "item_name": "Mobile",
- "item_group": "Products"
- },
- {
- "is_fixed_asset": 1,
- "asset_category": "Softwares",
- "is_stock_item": 0,
- "description": "ERP",
- "item_code": "ERP",
- "item_name": "ERP",
- "item_group": "All Item Groups"
- },
- {
- "is_fixed_asset": 1,
- "asset_category": "Softwares",
- "is_stock_item": 0,
- "description": "Autocad",
- "item_code": "Autocad",
- "item_name": "Autocad",
- "item_group": "All Item Groups"
- },
- {
- "is_stock_item": 1,
- "has_batch_no": 1,
- "create_new_batch": 1,
- "valuation_rate": 200,
- "item_defaults": [
- {
- "default_warehouse": "Stores"
- }
- ],
- "description": "Corrugated Box",
- "item_code": "Corrugated Box",
- "item_name": "Corrugated Box",
- "item_group": "All Item Groups"
- },
- {
- "item_defaults": [
- {
- "default_warehouse": "Finished Goods"
- }
- ],
- "is_stock_item": 1,
- "description": "OnePlus 6",
- "item_code": "OnePlus 6",
- "item_name": "OnePlus 6",
- "item_group": "Products",
- "domain": "Retail"
- },
- {
- "item_defaults": [
- {
- "default_warehouse": "Finished Goods"
- }
- ],
- "is_stock_item": 1,
- "description": "OnePlus 6T",
- "item_code": "OnePlus 6T",
- "item_name": "OnePlus 6T",
- "item_group": "Products",
- "domain": "Retail"
- },
- {
- "item_defaults": [
- {
- "default_warehouse": "Finished Goods"
- }
- ],
- "is_stock_item": 1,
- "description": "Xiaomi Poco F1",
- "item_code": "Xiaomi Poco F1",
- "item_name": "Xiaomi Poco F1",
- "item_group": "Products",
- "domain": "Retail"
- },
- {
- "item_defaults": [
- {
- "default_warehouse": "Finished Goods"
- }
- ],
- "is_stock_item": 1,
- "description": "Iphone XS",
- "item_code": "Iphone XS",
- "item_name": "Iphone XS",
- "item_group": "Products",
- "domain": "Retail"
- },
- {
- "item_defaults": [
- {
- "default_warehouse": "Finished Goods"
- }
- ],
- "is_stock_item": 1,
- "description": "Samsung Galaxy S9",
- "item_code": "Samsung Galaxy S9",
- "item_name": "Samsung Galaxy S9",
- "item_group": "Products",
- "domain": "Retail"
- },
- {
- "item_defaults": [
- {
- "default_warehouse": "Finished Goods"
- }
- ],
- "is_stock_item": 1,
- "description": "Sony Bluetooth Headphone",
- "item_code": "Sony Bluetooth Headphone",
- "item_name": "Sony Bluetooth Headphone",
- "item_group": "Products",
- "domain": "Retail"
- },
- {
- "is_stock_item": 0,
- "description": "Samsung Phone Repair",
- "item_code": "Samsung Phone Repair",
- "item_name": "Samsung Phone Repair",
- "item_group": "Services",
- "domain": "Retail"
- },
- {
- "is_stock_item": 0,
- "description": "OnePlus Phone Repair",
- "item_code": "OnePlus Phone Repair",
- "item_name": "OnePlus Phone Repair",
- "item_group": "Services",
- "domain": "Retail"
- },
- {
- "is_stock_item": 0,
- "description": "Xiaomi Phone Repair",
- "item_code": "Xiaomi Phone Repair",
- "item_name": "Xiaomi Phone Repair",
- "item_group": "Services",
- "domain": "Retail"
- },
- {
- "is_stock_item": 0,
- "description": "Apple Phone Repair",
- "item_code": "Apple Phone Repair",
- "item_name": "Apple Phone Repair",
- "item_group": "Services",
- "domain": "Retail"
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/item_education.json b/erpnext/demo/data/item_education.json
deleted file mode 100644
index 40e4701..0000000
--- a/erpnext/demo/data/item_education.json
+++ /dev/null
@@ -1,137 +0,0 @@
-[
- {
- "default_supplier": "Asiatic Solutions",
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "item_code": "Books",
- "item_group": "Raw Material",
- "item_name": "Books"
- },
- {
- "default_supplier": "HomeBase",
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "item_code": "Pencil",
- "item_group": "Raw Material",
- "item_name": "Pencil"
- },
- {
- "default_supplier": "New World Realty",
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "item_code": "Tables",
- "item_group": "Raw Material",
- "item_name": "Tables"
- },
- {
- "default_supplier": "Eagle Hardware",
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "item_code": "Chair",
- "item_group": "Raw Material",
- "item_name": "Chair"
- },
- {
- "default_supplier": "Asiatic Solutions",
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "item_code": "Black Board",
- "item_group": "Sub Assemblies",
- "item_name": "Black Board"
- },
- {
- "default_supplier": "HomeBase",
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "item_code": "Chalk",
- "item_group": "Raw Material",
- "item_name": "Chalk"
- },
- {
- "default_supplier": "HomeBase",
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "item_code": "Notepad",
- "item_group": "Raw Material",
- "item_name": "Notepad"
- },
- {
- "default_supplier": "Ks Merchandise",
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "item_code": "Uniform",
- "item_group": "Raw Material",
- "item_name": "Uniform"
- },
- {
- "is_stock_item": 0,
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "description": "Computer",
- "item_code": "Computer",
- "item_name": "Computer",
- "item_group": "Products"
- },
- {
- "is_stock_item": 0,
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "description": "Mobile",
- "item_code": "Mobile",
- "item_name": "Mobile",
- "item_group": "Products"
- },
- {
- "is_stock_item": 0,
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "description": "ERP",
- "item_code": "ERP",
- "item_name": "ERP",
- "item_group": "All Item Groups"
- },
- {
- "is_stock_item": 0,
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "description": "Autocad",
- "item_code": "Autocad",
- "item_name": "Autocad",
- "item_group": "All Item Groups"
- },
- {
- "item_defaults": [{
- "default_warehouse": "Stores",
- "company": "Whitmore College"
- }],
- "item_code": "Service",
- "item_group": "Services",
- "item_name": "Service",
- "has_variants": 0,
- "is_stock_item": 0
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/lead.json b/erpnext/demo/data/lead.json
deleted file mode 100644
index ff78877..0000000
--- a/erpnext/demo/data/lead.json
+++ /dev/null
@@ -1,127 +0,0 @@
-[
- {
- "company_name": "Zany Brainy",
- "email_id": "MartLakeman@example.com",
- "lead_name": "Mart Lakeman"
- },
- {
- "company_name": "Patterson-Fletcher",
- "email_id": "SagaLundqvist@example.com",
- "lead_name": "Saga Lundqvist"
- },
- {
- "company_name": "Griff's Hamburgers",
- "email_id": "AdnaSjoberg@example.com",
- "lead_name": "Adna Sj\u00f6berg"
- },
- {
- "company_name": "Rhodes Furniture",
- "email_id": "IdaDSvendsen@example.com",
- "lead_name": "Ida Svendsen"
- },
- {
- "company_name": "Burger Chef",
- "email_id": "EmppuHameenniemi@example.com",
- "lead_name": "Emppu H\u00e4meenniemi"
- },
- {
- "company_name": "Stratabiz",
- "email_id": "EugenioPisano@example.com",
- "lead_name": "Eugenio Pisano"
- },
- {
- "company_name": "Home Quarters Warehouse",
- "email_id": "SemharHagos@example.com",
- "lead_name": "Semhar Hagos"
- },
- {
- "company_name": "Enviro Architectural Designs",
- "email_id": "BranimiraIvankovic@example.com",
- "lead_name": "Branimira Ivankovi\u0107"
- },
- {
- "company_name": "Ideal Garden Management",
- "email_id": "ShellyLFields@example.com",
- "lead_name": "Shelly Fields"
- },
- {
- "company_name": "Listen Up",
- "email_id": "LeoMikulic@example.com",
- "lead_name": "Leo Mikuli\u0107"
- },
- {
- "company_name": "I. Magnin",
- "email_id": "DenisaJarosova@example.com",
- "lead_name": "Denisa Jaro\u0161ov\u00e1"
- },
- {
- "company_name": "First Rate Choice",
- "email_id": "JanekRutkowski@example.com",
- "lead_name": "Janek Rutkowski"
- },
- {
- "company_name": "Multi Tech Development",
- "email_id": "mm@example.com",
- "lead_name": "\u7f8e\u6708 \u5b87\u85e4"
- },
- {
- "company_name": "National Auto Parts",
- "email_id": "dd@example.com",
- "lead_name": "\u0414\u0430\u043d\u0438\u0438\u043b \u0410\u0444\u0430\u043d\u0430\u0441\u044c\u0435\u0432"
- },
- {
- "company_name": "Integra Investment Plan",
- "email_id": "ZorislavPetkovic@example.com",
- "lead_name": "Zorislav Petkovi\u0107"
- },
- {
- "company_name": "The Lawn Guru",
- "email_id": "NanaoNiwa@example.com",
- "lead_name": "Nanao Niwa"
- },
- {
- "company_name": "Buena Vista Realty Service",
- "email_id": "HreiarJorundsson@example.com",
- "lead_name": "Hrei\u00f0ar J\u00f6rundsson"
- },
- {
- "company_name": "Bountiful Harvest Health Food Store",
- "email_id": "ChuThiBichLai@example.com",
- "lead_name": "Lai Chu"
- },
- {
- "company_name": "P. Samuels Men's Clothiers",
- "email_id": "VictorAksakov@example.com",
- "lead_name": "Victor Aksakov"
- },
- {
- "company_name": "Vinyl Fever",
- "email_id": "SaidalimBisliev@example.com",
- "lead_name": "Saidalim Bisliev"
- },
- {
- "company_name": "Garden Master",
- "email_id": "TotteJakobsson@example.com",
- "lead_name": "Totte Jakobsson"
- },
- {
- "company_name": "Big Apple",
- "email_id": "NanaArmasRobles@example.com",
- "lead_name": "Nan\u00e1 Armas"
- },
- {
- "company_name": "Monk House Sales",
- "email_id": "WalerianDuda@example.com",
- "lead_name": "Walerian Duda"
- },
- {
- "company_name": "ManCharm",
- "email_id": "Moarimikashi@example.com",
- "lead_name": "Moarimikashi"
- },
- {
- "company_name": "Custom Lawn Care",
- "email_id": "DobromilDabrowski@example.com",
- "lead_name": "Dobromi\u0142 D\u0105browski"
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/location.json b/erpnext/demo/data/location.json
deleted file mode 100644
index b521aa0..0000000
--- a/erpnext/demo/data/location.json
+++ /dev/null
@@ -1,22 +0,0 @@
-[
- {
- "location_name": "Main Location",
- "latitude": 40.0,
- "longitude": 20.0
- },
- {
- "location_name": "Avg Location",
- "latitude": 63.0,
- "longitude": 99.3
- },
- {
- "location_name": "Zany Location",
- "latitude": 47.5,
- "longitude": 10.0
- },
- {
- "location_name": "Fletcher Location",
- "latitude": 100.90,
- "longitude": 80
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/operation.json b/erpnext/demo/data/operation.json
deleted file mode 100644
index 47f26d1..0000000
--- a/erpnext/demo/data/operation.json
+++ /dev/null
@@ -1,32 +0,0 @@
-[
- {
- "description": "Setup Fixtures for Assembly",
- "name": "Setup Fixtures",
- "workstation": "Assembly Station 1"
- },
- {
- "description": "Assemble Unit as per Standard Operating Procedures",
- "name": "Assembly Operation",
- "workstation": "Assembly Station 1"
- },
- {
- "description": "Final Testing Checklist",
- "name": "Testing",
- "workstation": "Packing and Testing Station"
- },
- {
- "description": "Final Packing and add Instructions",
- "name": "Packing",
- "workstation": "Packing and Testing Station"
- },
- {
- "description": "Prepare frame for assembly",
- "name": "Prepare Frame",
- "workstation": "Drilling Machine 1"
- },
- {
- "description": "Connect wires",
- "name": "Wiring",
- "workstation": "Assembly Station 1"
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/patient.json b/erpnext/demo/data/patient.json
deleted file mode 100644
index 6d95a20..0000000
--- a/erpnext/demo/data/patient.json
+++ /dev/null
@@ -1,27 +0,0 @@
-[
- {
- "patient_name": "lila",
- "gender": "Female"
- },
- {
- "patient_name": "charline",
- "gender": "Female"
- },
- {
- "patient_name": "soren",
- "last_name": "le gall",
- "gender": "Male"
- },
- {
- "patient_name": "fanny",
- "gender": "Female"
- },
- {
- "patient_name": "julie",
- "gender": "Female"
- },
- {
- "patient_name": "louka",
- "gender": "Male"
- }
-]
diff --git a/erpnext/demo/data/practitioner.json b/erpnext/demo/data/practitioner.json
deleted file mode 100644
index 39c960f..0000000
--- a/erpnext/demo/data/practitioner.json
+++ /dev/null
@@ -1,17 +0,0 @@
-[
- {
- "doctype": "Healthcare Practitioner",
- "first_name": "Eddie Jessup",
- "department": "Pathology"
- },
- {
- "doctype": "Healthcare Practitioner",
- "first_name": "Deepshi Garg",
- "department": "ENT"
- },
- {
- "doctype": "Healthcare Practitioner",
- "first_name": "Amit Jain",
- "department": "Microbiology"
- }
-]
diff --git a/erpnext/demo/data/program.json b/erpnext/demo/data/program.json
deleted file mode 100644
index 9c2ec77..0000000
--- a/erpnext/demo/data/program.json
+++ /dev/null
@@ -1,46 +0,0 @@
-[
- {
- "doctype": "Program",
- "name": "MCA",
- "program_name": "Masters of Computer Applications",
- "program_code": "MCA",
- "department": "Information Technology",
- "courses": [
- { "course": "MCA4010" },
- { "course": "MCA4020" },
- { "course": "MCA4030" }
- ]
- },
- {
- "doctype": "Program",
- "name": "BCA",
- "program_name": "Bachelor of Computer Applications",
- "program_code": "BCA",
- "department": "Information Technology",
- "courses": [
- { "course": "BCA2030" },
- { "course": "BCA1030" },
- { "course": "BCA2020" },
- { "course": "BCA1040" },
- { "course": "BCA1010" },
- { "course": "BCA2010" },
- { "course": "BCA1020" }
- ]
- },
- {
- "doctype": "Program",
- "name": "BBA",
- "program_name": "Bachelor of Business Administration",
- "program_code": "BBA",
- "department": "Management Studies",
- "courses": [
- { "course": "BBA 101" },
- { "course": "BBA 102" },
- { "course": "BBA 103" },
- { "course": "BBA 301" },
- { "course": "BBA 302" },
- { "course": "BBA 304" },
- { "course": "BBA 505" }
- ]
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/random_student_data.json b/erpnext/demo/data/random_student_data.json
deleted file mode 100644
index babcc71..0000000
--- a/erpnext/demo/data/random_student_data.json
+++ /dev/null
@@ -1,1604 +0,0 @@
-[
-{
-"first_name": "amanda",
-"last_name": "edwards",
-"image": "https://randomuser.me/api/portraits/women/55.jpg",
-"gender": "Female"
-},
-{
-"first_name": "abbie",
-"last_name": "johnston",
-"image": "https://randomuser.me/api/portraits/women/46.jpg",
-"gender": "Female"
-},
-{
-"first_name": "heather",
-"last_name": "nelson",
-"image": "https://randomuser.me/api/portraits/women/13.jpg",
-"gender": "Female"
-},
-{
-"first_name": "maxwell",
-"last_name": "gilbert",
-"image": "https://randomuser.me/api/portraits/men/56.jpg",
-"gender": "Male"
-},
-{
-"first_name": "molly",
-"last_name": "ramirez",
-"image": "https://randomuser.me/api/portraits/women/71.jpg",
-"gender": "Female"
-},
-{
-"first_name": "ian",
-"last_name": "barrett",
-"image": "https://randomuser.me/api/portraits/men/68.jpg",
-"gender": "Male"
-},
-{
-"first_name": "kim",
-"last_name": "hudson",
-"image": "https://randomuser.me/api/portraits/women/53.jpg",
-"gender": "Female"
-},
-{
-"first_name": "bruce",
-"last_name": "murray",
-"image": "https://randomuser.me/api/portraits/men/59.jpg",
-"gender": "Male"
-},
-{
-"first_name": "henry",
-"last_name": "powell",
-"image": "https://randomuser.me/api/portraits/men/88.jpg",
-"gender": "Male"
-},
-{
-"first_name": "chris",
-"last_name": "foster",
-"image": "https://randomuser.me/api/portraits/men/5.jpg",
-"gender": "Male"
-},
-{
-"first_name": "billy",
-"last_name": "kim",
-"image": "https://randomuser.me/api/portraits/men/91.jpg",
-"gender": "Male"
-},
-{
-"first_name": "samuel",
-"last_name": "harper",
-"image": "https://randomuser.me/api/portraits/men/56.jpg",
-"gender": "Male"
-},
-{
-"first_name": "jayden",
-"last_name": "kelly",
-"image": "https://randomuser.me/api/portraits/men/31.jpg",
-"gender": "Male"
-},
-{
-"first_name": "grace",
-"last_name": "berry",
-"image": "https://randomuser.me/api/portraits/women/69.jpg",
-"gender": "Female"
-},
-{
-"first_name": "ronnie",
-"last_name": "nelson",
-"image": "https://randomuser.me/api/portraits/men/83.jpg",
-"gender": "Male"
-},
-{
-"first_name": "harvey",
-"last_name": "harper",
-"image": "https://randomuser.me/api/portraits/men/68.jpg",
-"gender": "Male"
-},
-{
-"first_name": "maya",
-"last_name": "fernandez",
-"image": "https://randomuser.me/api/portraits/women/79.jpg",
-"gender": "Female"
-},
-{
-"first_name": "faith",
-"last_name": "lewis",
-"image": "https://randomuser.me/api/portraits/women/84.jpg",
-"gender": "Female"
-},
-{
-"first_name": "kirk",
-"last_name": "macrae",
-"image": "https://randomuser.me/api/portraits/men/13.jpg",
-"gender": "Male"
-},
-{
-"first_name": "tracy",
-"last_name": "holt",
-"image": "https://randomuser.me/api/portraits/women/18.jpg",
-"gender": "Female"
-},
-{
-"first_name": "mandy",
-"last_name": "dean",
-"image": "https://randomuser.me/api/portraits/women/0.jpg",
-"gender": "Female"
-},
-{
-"first_name": "sam",
-"last_name": "dunn",
-"image": "https://randomuser.me/api/portraits/women/12.jpg",
-"gender": "Female"
-},
-{
-"first_name": "zoe",
-"last_name": "fleming",
-"image": "https://randomuser.me/api/portraits/women/9.jpg",
-"gender": "Female"
-},
-{
-"first_name": "jeffrey",
-"last_name": "stewart",
-"image": "https://randomuser.me/api/portraits/men/56.jpg",
-"gender": "Male"
-},
-{
-"first_name": "dick",
-"last_name": "ryan",
-"image": "https://randomuser.me/api/portraits/men/63.jpg",
-"gender": "Male"
-},
-{
-"first_name": "carl",
-"last_name": "neal",
-"image": "https://randomuser.me/api/portraits/men/41.jpg",
-"gender": "Male"
-},
-{
-"first_name": "scarlett",
-"last_name": "ruiz",
-"image": "https://randomuser.me/api/portraits/women/24.jpg",
-"gender": "Female"
-},
-{
-"first_name": "rene",
-"last_name": "hughes",
-"image": "https://randomuser.me/api/portraits/men/3.jpg",
-"gender": "Male"
-},
-{
-"first_name": "greg",
-"last_name": "montgomery",
-"image": "https://randomuser.me/api/portraits/men/12.jpg",
-"gender": "Male"
-},
-{
-"first_name": "matt",
-"last_name": "lane",
-"image": "https://randomuser.me/api/portraits/men/85.jpg",
-"gender": "Male"
-},
-{
-"first_name": "eleanor",
-"last_name": "pearson",
-"image": "https://randomuser.me/api/portraits/women/61.jpg",
-"gender": "Female"
-},
-{
-"first_name": "theodore",
-"last_name": "burton",
-"image": "https://randomuser.me/api/portraits/men/81.jpg",
-"gender": "Male"
-},
-{
-"first_name": "jesus",
-"last_name": "hunt",
-"image": "https://randomuser.me/api/portraits/men/50.jpg",
-"gender": "Male"
-},
-{
-"first_name": "taylor",
-"last_name": "alvarez",
-"image": "https://randomuser.me/api/portraits/men/0.jpg",
-"gender": "Male"
-},
-{
-"first_name": "barbara",
-"last_name": "lucas",
-"image": "https://randomuser.me/api/portraits/women/21.jpg",
-"gender": "Female"
-},
-{
-"first_name": "nicky",
-"last_name": "simmons",
-"image": "https://randomuser.me/api/portraits/women/29.jpg",
-"gender": "Female"
-},
-{
-"first_name": "arthur",
-"last_name": "obrien",
-"image": "https://randomuser.me/api/portraits/men/11.jpg",
-"gender": "Male"
-},
-{
-"first_name": "donna",
-"last_name": "holmes",
-"image": "https://randomuser.me/api/portraits/women/33.jpg",
-"gender": "Female"
-},
-{
-"first_name": "mitchell",
-"last_name": "castro",
-"image": "https://randomuser.me/api/portraits/men/26.jpg",
-"gender": "Male"
-},
-{
-"first_name": "byron",
-"last_name": "marshall",
-"image": "https://randomuser.me/api/portraits/men/57.jpg",
-"gender": "Male"
-},
-{
-"first_name": "larry",
-"last_name": "king",
-"image": "https://randomuser.me/api/portraits/men/58.jpg",
-"gender": "Male"
-},
-{
-"first_name": "deborah",
-"last_name": "fuller",
-"image": "https://randomuser.me/api/portraits/women/50.jpg",
-"gender": "Female"
-},
-{
-"first_name": "eleanor",
-"last_name": "elliott",
-"image": "https://randomuser.me/api/portraits/women/80.jpg",
-"gender": "Female"
-},
-{
-"first_name": "derrick",
-"last_name": "shaw",
-"image": "https://randomuser.me/api/portraits/men/78.jpg",
-"gender": "Male"
-},
-{
-"first_name": "barbara",
-"last_name": "lynch",
-"image": "https://randomuser.me/api/portraits/women/15.jpg",
-"gender": "Female"
-},
-{
-"first_name": "elijah",
-"last_name": "allen",
-"image": "https://randomuser.me/api/portraits/men/43.jpg",
-"gender": "Male"
-},
-{
-"first_name": "nicholas",
-"last_name": "harper",
-"image": "https://randomuser.me/api/portraits/men/2.jpg",
-"gender": "Male"
-},
-{
-"first_name": "sofia",
-"last_name": "riley",
-"image": "https://randomuser.me/api/portraits/women/96.jpg",
-"gender": "Female"
-},
-{
-"first_name": "jar",
-"last_name": "hunt",
-"image": "https://randomuser.me/api/portraits/men/72.jpg",
-"gender": "Male"
-},
-{
-"first_name": "philip",
-"last_name": "rose",
-"image": "https://randomuser.me/api/portraits/men/16.jpg",
-"gender": "Male"
-},
-{
-"first_name": "ella",
-"last_name": "moore",
-"image": "https://randomuser.me/api/portraits/women/83.jpg",
-"gender": "Female"
-},
-{
-"first_name": "seth",
-"last_name": "tucker",
-"image": "https://randomuser.me/api/portraits/men/6.jpg",
-"gender": "Male"
-},
-{
-"first_name": "abby",
-"last_name": "gonzalez",
-"image": "https://randomuser.me/api/portraits/women/18.jpg",
-"gender": "Female"
-},
-{
-"first_name": "noah",
-"last_name": "williamson",
-"image": "https://randomuser.me/api/portraits/men/54.jpg",
-"gender": "Male"
-},
-{
-"first_name": "cathy",
-"last_name": "gray",
-"image": "https://randomuser.me/api/portraits/women/88.jpg",
-"gender": "Female"
-},
-{
-"first_name": "barb",
-"last_name": "snyder",
-"image": "https://randomuser.me/api/portraits/women/49.jpg",
-"gender": "Female"
-},
-{
-"first_name": "rosalyn",
-"last_name": "hale",
-"image": "https://randomuser.me/api/portraits/women/64.jpg",
-"gender": "Female"
-},
-{
-"first_name": "jessica",
-"last_name": "armstrong",
-"image": "https://randomuser.me/api/portraits/women/95.jpg",
-"gender": "Female"
-},
-{
-"first_name": "vicki",
-"last_name": "wheeler",
-"image": "https://randomuser.me/api/portraits/women/49.jpg",
-"gender": "Female"
-},
-{
-"first_name": "luke",
-"last_name": "fisher",
-"image": "https://randomuser.me/api/portraits/men/77.jpg",
-"gender": "Male"
-},
-{
-"first_name": "joey",
-"last_name": "wheeler",
-"image": "https://randomuser.me/api/portraits/men/50.jpg",
-"gender": "Male"
-},
-{
-"first_name": "victoria",
-"last_name": "jimenez",
-"image": "https://randomuser.me/api/portraits/women/25.jpg",
-"gender": "Female"
-},
-{
-"first_name": "daryl",
-"last_name": "patterson",
-"image": "https://randomuser.me/api/portraits/men/30.jpg",
-"gender": "Male"
-},
-{
-"first_name": "dwayne",
-"last_name": "jensen",
-"image": "https://randomuser.me/api/portraits/men/71.jpg",
-"gender": "Male"
-},
-{
-"first_name": "herbert",
-"last_name": "silva",
-"image": "https://randomuser.me/api/portraits/men/83.jpg",
-"gender": "Male"
-},
-{
-"first_name": "walter",
-"last_name": "walker",
-"image": "https://randomuser.me/api/portraits/men/91.jpg",
-"gender": "Male"
-},
-{
-"first_name": "logan",
-"last_name": "banks",
-"image": "https://randomuser.me/api/portraits/men/67.jpg",
-"gender": "Male"
-},
-{
-"first_name": "shawn",
-"last_name": "harvey",
-"image": "https://randomuser.me/api/portraits/men/87.jpg",
-"gender": "Male"
-},
-{
-"first_name": "lawrence",
-"last_name": "bradley",
-"image": "https://randomuser.me/api/portraits/men/40.jpg",
-"gender": "Male"
-},
-{
-"first_name": "jack",
-"last_name": "fleming",
-"image": "https://randomuser.me/api/portraits/men/37.jpg",
-"gender": "Male"
-},
-{
-"first_name": "jackson",
-"last_name": "boyd",
-"image": "https://randomuser.me/api/portraits/men/68.jpg",
-"gender": "Male"
-},
-{
-"first_name": "cecil",
-"last_name": "webb",
-"image": "https://randomuser.me/api/portraits/men/9.jpg",
-"gender": "Male"
-},
-{
-"first_name": "eliza",
-"last_name": "mills",
-"image": "https://randomuser.me/api/portraits/women/20.jpg",
-"gender": "Female"
-},
-{
-"first_name": "jenny",
-"last_name": "frazier",
-"image": "https://randomuser.me/api/portraits/women/61.jpg",
-"gender": "Female"
-},
-{
-"first_name": "kent",
-"last_name": "butler",
-"image": "https://randomuser.me/api/portraits/men/64.jpg",
-"gender": "Male"
-},
-{
-"first_name": "rose",
-"last_name": "perry",
-"image": "https://randomuser.me/api/portraits/women/74.jpg",
-"gender": "Female"
-},
-{
-"first_name": "jack",
-"last_name": "king",
-"image": "https://randomuser.me/api/portraits/men/60.jpg",
-"gender": "Male"
-},
-{
-"first_name": "elmer",
-"last_name": "williams",
-"image": "https://randomuser.me/api/portraits/men/26.jpg",
-"gender": "Male"
-},
-{
-"first_name": "vanessa",
-"last_name": "torres",
-"image": "https://randomuser.me/api/portraits/women/41.jpg",
-"gender": "Female"
-},
-{
-"first_name": "tyrone",
-"last_name": "coleman",
-"image": "https://randomuser.me/api/portraits/men/59.jpg",
-"gender": "Male"
-},
-{
-"first_name": "julie",
-"last_name": "bradley",
-"image": "https://randomuser.me/api/portraits/women/50.jpg",
-"gender": "Female"
-},
-{
-"first_name": "fernando",
-"last_name": "castro",
-"image": "https://randomuser.me/api/portraits/men/44.jpg",
-"gender": "Male"
-},
-{
-"first_name": "sara",
-"last_name": "craig",
-"image": "https://randomuser.me/api/portraits/women/8.jpg",
-"gender": "Female"
-},
-{
-"first_name": "steven",
-"last_name": "stone",
-"image": "https://randomuser.me/api/portraits/men/47.jpg",
-"gender": "Male"
-},
-{
-"first_name": "barb",
-"last_name": "rodriquez",
-"image": "https://randomuser.me/api/portraits/women/73.jpg",
-"gender": "Female"
-},
-{
-"first_name": "charlie",
-"last_name": "king",
-"image": "https://randomuser.me/api/portraits/men/79.jpg",
-"gender": "Male"
-},
-{
-"first_name": "jessica",
-"last_name": "davis",
-"image": "https://randomuser.me/api/portraits/women/26.jpg",
-"gender": "Female"
-},
-{
-"first_name": "lewis",
-"last_name": "watson",
-"image": "https://randomuser.me/api/portraits/men/56.jpg",
-"gender": "Male"
-},
-{
-"first_name": "charlotte",
-"last_name": "johnson",
-"image": "https://randomuser.me/api/portraits/women/46.jpg",
-"gender": "Female"
-},
-{
-"first_name": "danielle",
-"last_name": "bell",
-"image": "https://randomuser.me/api/portraits/women/54.jpg",
-"gender": "Female"
-},
-{
-"first_name": "kristin",
-"last_name": "dixon",
-"image": "https://randomuser.me/api/portraits/women/23.jpg",
-"gender": "Female"
-},
-{
-"first_name": "andrea",
-"last_name": "thompson",
-"image": "https://randomuser.me/api/portraits/women/54.jpg",
-"gender": "Female"
-},
-{
-"first_name": "ashley",
-"last_name": "andrews",
-"image": "https://randomuser.me/api/portraits/women/46.jpg",
-"gender": "Female"
-},
-{
-"first_name": "sharon",
-"last_name": "martinez",
-"image": "https://randomuser.me/api/portraits/women/6.jpg",
-"gender": "Female"
-},
-{
-"first_name": "tristan",
-"last_name": "cunningham",
-"image": "https://randomuser.me/api/portraits/men/62.jpg",
-"gender": "Male"
-},
-{
-"first_name": "carol",
-"last_name": "chavez",
-"image": "https://randomuser.me/api/portraits/women/85.jpg",
-"gender": "Female"
-},
-{
-"first_name": "lauren",
-"last_name": "hudson",
-"image": "https://randomuser.me/api/portraits/women/88.jpg",
-"gender": "Female"
-},
-{
-"first_name": "guy",
-"last_name": "robertson",
-"image": "https://randomuser.me/api/portraits/men/78.jpg",
-"gender": "Male"
-},
-{
-"first_name": "debra",
-"last_name": "long",
-"image": "https://randomuser.me/api/portraits/women/23.jpg",
-"gender": "Female"
-},
-{
-"first_name": "taylor",
-"last_name": "carpenter",
-"image": "https://randomuser.me/api/portraits/men/0.jpg",
-"gender": "Male"
-},
-{
-"first_name": "eetu",
-"last_name": "annala",
-"image": "https://randomuser.me/api/portraits/men/31.jpg",
-"gender": "Male"
-},
-{
-"first_name": "oliver",
-"last_name": "moilanen",
-"image": "https://randomuser.me/api/portraits/men/14.jpg",
-"gender": "Male"
-},
-{
-"first_name": "leo",
-"last_name": "maunu",
-"image": "https://randomuser.me/api/portraits/men/72.jpg",
-"gender": "Male"
-},
-{
-"first_name": "iiris",
-"last_name": "kalas",
-"image": "https://randomuser.me/api/portraits/women/49.jpg",
-"gender": "Female"
-},
-{
-"first_name": "aada",
-"last_name": "kinnunen",
-"image": "https://randomuser.me/api/portraits/women/64.jpg",
-"gender": "Female"
-},
-{
-"first_name": "topias",
-"last_name": "walli",
-"image": "https://randomuser.me/api/portraits/men/58.jpg",
-"gender": "Male"
-},
-{
-"first_name": "viivi",
-"last_name": "toivonen",
-"image": "https://randomuser.me/api/portraits/women/16.jpg",
-"gender": "Female"
-},
-{
-"first_name": "iina",
-"last_name": "makinen",
-"image": "https://randomuser.me/api/portraits/women/44.jpg",
-"gender": "Female"
-},
-{
-"first_name": "lumi",
-"last_name": "tuominen",
-"image": "https://randomuser.me/api/portraits/women/11.jpg",
-"gender": "Female"
-},
-{
-"first_name": "ellen",
-"last_name": "koski",
-"image": "https://randomuser.me/api/portraits/women/22.jpg",
-"gender": "Female"
-},
-{
-"first_name": "onni",
-"last_name": "laurila",
-"image": "https://randomuser.me/api/portraits/men/74.jpg",
-"gender": "Male"
-},
-{
-"first_name": "eevi",
-"last_name": "niskanen",
-"image": "https://randomuser.me/api/portraits/women/72.jpg",
-"gender": "Female"
-},
-{
-"first_name": "julius",
-"last_name": "maijala",
-"image": "https://randomuser.me/api/portraits/men/8.jpg",
-"gender": "Male"
-},
-{
-"first_name": "sofia",
-"last_name": "tuomi",
-"image": "https://randomuser.me/api/portraits/women/1.jpg",
-"gender": "Female"
-},
-{
-"first_name": "oliver",
-"last_name": "jarvela",
-"image": "https://randomuser.me/api/portraits/men/60.jpg",
-"gender": "Male"
-},
-{
-"first_name": "luukas",
-"last_name": "mikkola",
-"image": "https://randomuser.me/api/portraits/men/90.jpg",
-"gender": "Male"
-},
-{
-"first_name": "amanda",
-"last_name": "anttila",
-"image": "https://randomuser.me/api/portraits/women/65.jpg",
-"gender": "Female"
-},
-{
-"first_name": "ella",
-"last_name": "sakala",
-"image": "https://randomuser.me/api/portraits/women/79.jpg",
-"gender": "Female"
-},
-{
-"first_name": "siiri",
-"last_name": "kinnunen",
-"image": "https://randomuser.me/api/portraits/women/37.jpg",
-"gender": "Female"
-},
-{
-"first_name": "joona",
-"last_name": "korhonen",
-"image": "https://randomuser.me/api/portraits/men/87.jpg",
-"gender": "Male"
-},
-{
-"first_name": "topias",
-"last_name": "korpi",
-"image": "https://randomuser.me/api/portraits/men/75.jpg",
-"gender": "Male"
-},
-{
-"first_name": "mikael",
-"last_name": "remes",
-"image": "https://randomuser.me/api/portraits/men/89.jpg",
-"gender": "Male"
-},
-{
-"first_name": "veera",
-"last_name": "peltola",
-"image": "https://randomuser.me/api/portraits/women/69.jpg",
-"gender": "Female"
-},
-{
-"first_name": "emil",
-"last_name": "makela",
-"image": "https://randomuser.me/api/portraits/men/98.jpg",
-"gender": "Male"
-},
-{
-"first_name": "luukas",
-"last_name": "kujala",
-"image": "https://randomuser.me/api/portraits/men/83.jpg",
-"gender": "Male"
-},
-{
-"first_name": "eemil",
-"last_name": "honkala",
-"image": "https://randomuser.me/api/portraits/men/85.jpg",
-"gender": "Male"
-},
-{
-"first_name": "peetu",
-"last_name": "kalm",
-"image": "https://randomuser.me/api/portraits/men/17.jpg",
-"gender": "Male"
-},
-{
-"first_name": "eemeli",
-"last_name": "lehtonen",
-"image": "https://randomuser.me/api/portraits/men/55.jpg",
-"gender": "Male"
-},
-{
-"first_name": "viivi",
-"last_name": "koistinen",
-"image": "https://randomuser.me/api/portraits/women/53.jpg",
-"gender": "Female"
-},
-{
-"first_name": "elli",
-"last_name": "savela",
-"image": "https://randomuser.me/api/portraits/women/77.jpg",
-"gender": "Female"
-},
-{
-"first_name": "venla",
-"last_name": "walli",
-"image": "https://randomuser.me/api/portraits/women/52.jpg",
-"gender": "Female"
-},
-{
-"first_name": "amanda",
-"last_name": "wuollet",
-"image": "https://randomuser.me/api/portraits/women/11.jpg",
-"gender": "Female"
-},
-{
-"first_name": "valtteri",
-"last_name": "hokkanen",
-"image": "https://randomuser.me/api/portraits/men/30.jpg",
-"gender": "Male"
-},
-{
-"first_name": "veera",
-"last_name": "maki",
-"image": "https://randomuser.me/api/portraits/women/34.jpg",
-"gender": "Female"
-},
-{
-"first_name": "kerttu",
-"last_name": "maunu",
-"image": "https://randomuser.me/api/portraits/women/1.jpg",
-"gender": "Female"
-},
-{
-"first_name": "nella",
-"last_name": "hanka",
-"image": "https://randomuser.me/api/portraits/women/70.jpg",
-"gender": "Female"
-},
-{
-"first_name": "iiris",
-"last_name": "hakala",
-"image": "https://randomuser.me/api/portraits/women/33.jpg",
-"gender": "Female"
-},
-{
-"first_name": "viivi",
-"last_name": "ojala",
-"image": "https://randomuser.me/api/portraits/women/69.jpg",
-"gender": "Female"
-},
-{
-"first_name": "iina",
-"last_name": "peura",
-"image": "https://randomuser.me/api/portraits/women/22.jpg",
-"gender": "Female"
-},
-{
-"first_name": "samuel",
-"last_name": "mattila",
-"image": "https://randomuser.me/api/portraits/men/88.jpg",
-"gender": "Male"
-},
-{
-"first_name": "julius",
-"last_name": "kumpula",
-"image": "https://randomuser.me/api/portraits/men/26.jpg",
-"gender": "Male"
-},
-{
-"first_name": "nooa",
-"last_name": "haapala",
-"image": "https://randomuser.me/api/portraits/men/77.jpg",
-"gender": "Male"
-},
-{
-"first_name": "elias",
-"last_name": "leppo",
-"image": "https://randomuser.me/api/portraits/men/50.jpg",
-"gender": "Male"
-},
-{
-"first_name": "niklas",
-"last_name": "elo",
-"image": "https://randomuser.me/api/portraits/men/64.jpg",
-"gender": "Male"
-},
-{
-"first_name": "olivia",
-"last_name": "nurmi",
-"image": "https://randomuser.me/api/portraits/women/82.jpg",
-"gender": "Female"
-},
-{
-"first_name": "milja",
-"last_name": "lassila",
-"image": "https://randomuser.me/api/portraits/women/47.jpg",
-"gender": "Female"
-},
-{
-"first_name": "daniel",
-"last_name": "kalas",
-"image": "https://randomuser.me/api/portraits/men/53.jpg",
-"gender": "Male"
-},
-{
-"first_name": "enni",
-"last_name": "ramo",
-"image": "https://randomuser.me/api/portraits/women/18.jpg",
-"gender": "Female"
-},
-{
-"first_name": "matilda",
-"last_name": "salmi",
-"image": "https://randomuser.me/api/portraits/women/84.jpg",
-"gender": "Female"
-},
-{
-"first_name": "valtteri",
-"last_name": "wirta",
-"image": "https://randomuser.me/api/portraits/men/26.jpg",
-"gender": "Male"
-},
-{
-"first_name": "julius",
-"last_name": "maijala",
-"image": "https://randomuser.me/api/portraits/men/39.jpg",
-"gender": "Male"
-},
-{
-"first_name": "kerttu",
-"last_name": "peltola",
-"image": "https://randomuser.me/api/portraits/women/39.jpg",
-"gender": "Female"
-},
-{
-"first_name": "aada",
-"last_name": "kokko",
-"image": "https://randomuser.me/api/portraits/women/26.jpg",
-"gender": "Female"
-},
-{
-"first_name": "elsa",
-"last_name": "niska",
-"image": "https://randomuser.me/api/portraits/women/26.jpg",
-"gender": "Female"
-},
-{
-"first_name": "ella",
-"last_name": "kalm",
-"image": "https://randomuser.me/api/portraits/women/61.jpg",
-"gender": "Female"
-},
-{
-"first_name": "lilja",
-"last_name": "heinonen",
-"image": "https://randomuser.me/api/portraits/women/65.jpg",
-"gender": "Female"
-},
-{
-"first_name": "akseli",
-"last_name": "laakso",
-"image": "https://randomuser.me/api/portraits/men/64.jpg",
-"gender": "Male"
-},
-{
-"first_name": "lotta",
-"last_name": "saarela",
-"image": "https://randomuser.me/api/portraits/women/69.jpg",
-"gender": "Female"
-},
-{
-"first_name": "leo",
-"last_name": "polon",
-"image": "https://randomuser.me/api/portraits/men/5.jpg",
-"gender": "Male"
-},
-{
-"first_name": "aleksi",
-"last_name": "wuollet",
-"image": "https://randomuser.me/api/portraits/men/87.jpg",
-"gender": "Male"
-},
-{
-"first_name": "eemil",
-"last_name": "kalas",
-"image": "https://randomuser.me/api/portraits/men/6.jpg",
-"gender": "Male"
-},
-{
-"first_name": "emmi",
-"last_name": "koistinen",
-"image": "https://randomuser.me/api/portraits/women/66.jpg",
-"gender": "Female"
-},
-{
-"first_name": "väinö",
-"last_name": "halla",
-"image": "https://randomuser.me/api/portraits/men/65.jpg",
-"gender": "Male"
-},
-{
-"first_name": "eemil",
-"last_name": "heikkila",
-"image": "https://randomuser.me/api/portraits/men/18.jpg",
-"gender": "Male"
-},
-{
-"first_name": "amanda",
-"last_name": "lakso",
-"image": "https://randomuser.me/api/portraits/women/29.jpg",
-"gender": "Female"
-},
-{
-"first_name": "vilho",
-"last_name": "kivela",
-"image": "https://randomuser.me/api/portraits/men/19.jpg",
-"gender": "Male"
-},
-{
-"first_name": "peppi",
-"last_name": "lehtinen",
-"image": "https://randomuser.me/api/portraits/women/80.jpg",
-"gender": "Female"
-},
-{
-"first_name": "onni",
-"last_name": "lehtinen",
-"image": "https://randomuser.me/api/portraits/men/0.jpg",
-"gender": "Male"
-},
-{
-"first_name": "onni",
-"last_name": "ahonen",
-"image": "https://randomuser.me/api/portraits/men/49.jpg",
-"gender": "Male"
-},
-{
-"first_name": "venla",
-"last_name": "ranta",
-"image": "https://randomuser.me/api/portraits/women/0.jpg",
-"gender": "Female"
-},
-{
-"first_name": "ronja",
-"last_name": "korhonen",
-"image": "https://randomuser.me/api/portraits/women/69.jpg",
-"gender": "Female"
-},
-{
-"first_name": "emmi",
-"last_name": "niva",
-"image": "https://randomuser.me/api/portraits/women/65.jpg",
-"gender": "Female"
-},
-{
-"first_name": "oskari",
-"last_name": "leppanen",
-"image": "https://randomuser.me/api/portraits/men/43.jpg",
-"gender": "Male"
-},
-{
-"first_name": "arttu",
-"last_name": "heinonen",
-"image": "https://randomuser.me/api/portraits/men/94.jpg",
-"gender": "Male"
-},
-{
-"first_name": "toivo",
-"last_name": "makela",
-"image": "https://randomuser.me/api/portraits/men/23.jpg",
-"gender": "Male"
-},
-{
-"first_name": "otto",
-"last_name": "leino",
-"image": "https://randomuser.me/api/portraits/men/51.jpg",
-"gender": "Male"
-},
-{
-"first_name": "milla",
-"last_name": "kokko",
-"image": "https://randomuser.me/api/portraits/women/66.jpg",
-"gender": "Female"
-},
-{
-"first_name": "konsta",
-"last_name": "lehto",
-"image": "https://randomuser.me/api/portraits/men/29.jpg",
-"gender": "Male"
-},
-{
-"first_name": "eeli",
-"last_name": "heikkinen",
-"image": "https://randomuser.me/api/portraits/men/50.jpg",
-"gender": "Male"
-},
-{
-"first_name": "matilda",
-"last_name": "tanner",
-"image": "https://randomuser.me/api/portraits/women/2.jpg",
-"gender": "Female"
-},
-{
-"first_name": "elias",
-"last_name": "kivisto",
-"image": "https://randomuser.me/api/portraits/men/40.jpg",
-"gender": "Male"
-},
-{
-"first_name": "akseli",
-"last_name": "wirta",
-"image": "https://randomuser.me/api/portraits/men/90.jpg",
-"gender": "Male"
-},
-{
-"first_name": "leevi",
-"last_name": "kallio",
-"image": "https://randomuser.me/api/portraits/men/89.jpg",
-"gender": "Male"
-},
-{
-"first_name": "emilia",
-"last_name": "pelto",
-"image": "https://randomuser.me/api/portraits/women/0.jpg",
-"gender": "Female"
-},
-{
-"first_name": "niilo",
-"last_name": "keranen",
-"image": "https://randomuser.me/api/portraits/men/29.jpg",
-"gender": "Male"
-},
-{
-"first_name": "mikael",
-"last_name": "wainio",
-"image": "https://randomuser.me/api/portraits/men/85.jpg",
-"gender": "Male"
-},
-{
-"first_name": "elias",
-"last_name": "saksa",
-"image": "https://randomuser.me/api/portraits/men/53.jpg",
-"gender": "Male"
-},
-{
-"first_name": "aatu",
-"last_name": "erkkila",
-"image": "https://randomuser.me/api/portraits/men/6.jpg",
-"gender": "Male"
-},
-{
-"first_name": "arttu",
-"last_name": "jarvela",
-"image": "https://randomuser.me/api/portraits/men/49.jpg",
-"gender": "Male"
-},
-{
-"first_name": "matilda",
-"last_name": "lassila",
-"image": "https://randomuser.me/api/portraits/women/46.jpg",
-"gender": "Female"
-},
-{
-"first_name": "alisa",
-"last_name": "waara",
-"image": "https://randomuser.me/api/portraits/women/67.jpg",
-"gender": "Female"
-},
-{
-"first_name": "emilia",
-"last_name": "saksa",
-"image": "https://randomuser.me/api/portraits/women/66.jpg",
-"gender": "Female"
-},
-{
-"first_name": "valtteri",
-"last_name": "tikkanen",
-"image": "https://randomuser.me/api/portraits/men/88.jpg",
-"gender": "Male"
-},
-{
-"first_name": "konsta",
-"last_name": "rantala",
-"image": "https://randomuser.me/api/portraits/men/50.jpg",
-"gender": "Male"
-},
-{
-"first_name": "minttu",
-"last_name": "murto",
-"image": "https://randomuser.me/api/portraits/women/14.jpg",
-"gender": "Female"
-},
-{
-"first_name": "vilma",
-"last_name": "hatala",
-"image": "https://randomuser.me/api/portraits/women/60.jpg",
-"gender": "Female"
-},
-{
-"first_name": "anni",
-"last_name": "linna",
-"image": "https://randomuser.me/api/portraits/women/59.jpg",
-"gender": "Female"
-},
-{
-"first_name": "niklas",
-"last_name": "hautala",
-"image": "https://randomuser.me/api/portraits/men/7.jpg",
-"gender": "Male"
-},
-{
-"first_name": "niilo",
-"last_name": "lehtinen",
-"image": "https://randomuser.me/api/portraits/men/54.jpg",
-"gender": "Male"
-},
-{
-"first_name": "oona",
-"last_name": "saarinen",
-"image": "https://randomuser.me/api/portraits/women/71.jpg",
-"gender": "Female"
-},
-{
-"first_name": "constance",
-"last_name": "marie",
-"image": "https://randomuser.me/api/portraits/women/40.jpg",
-"gender": "Female"
-},
-{
-"first_name": "charles",
-"last_name": "pierre",
-"image": "https://randomuser.me/api/portraits/men/96.jpg",
-"gender": "Male"
-},
-{
-"first_name": "bérénice",
-"last_name": "leclerc",
-"image": "https://randomuser.me/api/portraits/women/39.jpg",
-"gender": "Female"
-},
-{
-"first_name": "clémence",
-"last_name": "arnaud",
-"image": "https://randomuser.me/api/portraits/women/48.jpg",
-"gender": "Female"
-},
-{
-"first_name": "melvin",
-"last_name": "lemoine",
-"image": "https://randomuser.me/api/portraits/men/47.jpg",
-"gender": "Male"
-},
-{
-"first_name": "marceau",
-"last_name": "joly",
-"image": "https://randomuser.me/api/portraits/men/56.jpg",
-"gender": "Male"
-},
-{
-"first_name": "garance",
-"last_name": "mathieu",
-"image": "https://randomuser.me/api/portraits/women/87.jpg",
-"gender": "Female"
-},
-{
-"first_name": "angèle",
-"last_name": "perrin",
-"image": "https://randomuser.me/api/portraits/women/88.jpg",
-"gender": "Female"
-},
-{
-"first_name": "pauline",
-"last_name": "simon",
-"image": "https://randomuser.me/api/portraits/women/82.jpg",
-"gender": "Female"
-},
-{
-"first_name": "apolline",
-"last_name": "laurent",
-"image": "https://randomuser.me/api/portraits/women/27.jpg",
-"gender": "Female"
-},
-{
-"first_name": "luca",
-"last_name": "lefevre",
-"image": "https://randomuser.me/api/portraits/men/40.jpg",
-"gender": "Male"
-},
-{
-"first_name": "bastien",
-"last_name": "roger",
-"image": "https://randomuser.me/api/portraits/men/73.jpg",
-"gender": "Male"
-},
-{
-"first_name": "marie",
-"last_name": "rodriguez",
-"image": "https://randomuser.me/api/portraits/women/18.jpg",
-"gender": "Female"
-},
-{
-"first_name": "tristan",
-"last_name": "renaud",
-"image": "https://randomuser.me/api/portraits/men/41.jpg",
-"gender": "Male"
-},
-{
-"first_name": "eva",
-"last_name": "philippe",
-"image": "https://randomuser.me/api/portraits/women/26.jpg",
-"gender": "Female"
-},
-{
-"first_name": "coline",
-"last_name": "dufour",
-"image": "https://randomuser.me/api/portraits/women/64.jpg",
-"gender": "Female"
-},
-{
-"first_name": "marilou",
-"last_name": "adam",
-"image": "https://randomuser.me/api/portraits/women/53.jpg",
-"gender": "Female"
-},
-{
-"first_name": "lia",
-"last_name": "renard",
-"image": "https://randomuser.me/api/portraits/women/88.jpg",
-"gender": "Female"
-},
-{
-"first_name": "timothee",
-"last_name": "rolland",
-"image": "https://randomuser.me/api/portraits/men/75.jpg",
-"gender": "Male"
-},
-{
-"first_name": "hélèna",
-"last_name": "boyer",
-"image": "https://randomuser.me/api/portraits/women/8.jpg",
-"gender": "Female"
-},
-{
-"first_name": "mélody",
-"last_name": "andre",
-"image": "https://randomuser.me/api/portraits/women/75.jpg",
-"gender": "Female"
-},
-{
-"first_name": "jeanne",
-"last_name": "duval",
-"image": "https://randomuser.me/api/portraits/women/44.jpg",
-"gender": "Female"
-},
-{
-"first_name": "elias",
-"last_name": "dupont",
-"image": "https://randomuser.me/api/portraits/men/60.jpg",
-"gender": "Male"
-},
-{
-"first_name": "estelle",
-"last_name": "bernard",
-"image": "https://randomuser.me/api/portraits/women/23.jpg",
-"gender": "Female"
-},
-{
-"first_name": "roxane",
-"last_name": "garnier",
-"image": "https://randomuser.me/api/portraits/women/14.jpg",
-"gender": "Female"
-},
-{
-"first_name": "maëva",
-"last_name": "guerin",
-"image": "https://randomuser.me/api/portraits/women/44.jpg",
-"gender": "Female"
-},
-{
-"first_name": "liam",
-"last_name": "carpentier",
-"image": "https://randomuser.me/api/portraits/men/41.jpg",
-"gender": "Male"
-},
-{
-"first_name": "théo",
-"last_name": "gaillard",
-"image": "https://randomuser.me/api/portraits/men/40.jpg",
-"gender": "Male"
-},
-{
-"first_name": "angelina",
-"last_name": "clement",
-"image": "https://randomuser.me/api/portraits/women/53.jpg",
-"gender": "Female"
-},
-{
-"first_name": "emma",
-"last_name": "bertrand",
-"image": "https://randomuser.me/api/portraits/women/86.jpg",
-"gender": "Female"
-},
-{
-"first_name": "charles",
-"last_name": "rolland",
-"image": "https://randomuser.me/api/portraits/men/14.jpg",
-"gender": "Male"
-},
-{
-"first_name": "nolan",
-"last_name": "gautier",
-"image": "https://randomuser.me/api/portraits/men/6.jpg",
-"gender": "Male"
-},
-{
-"first_name": "agathe",
-"last_name": "menard",
-"image": "https://randomuser.me/api/portraits/women/69.jpg",
-"gender": "Female"
-},
-{
-"first_name": "gaëtan",
-"last_name": "leclerc",
-"image": "https://randomuser.me/api/portraits/men/60.jpg",
-"gender": "Male"
-},
-{
-"first_name": "clarisse",
-"last_name": "lemaire",
-"image": "https://randomuser.me/api/portraits/women/21.jpg",
-"gender": "Female"
-},
-{
-"first_name": "samuel",
-"last_name": "garnier",
-"image": "https://randomuser.me/api/portraits/men/16.jpg",
-"gender": "Male"
-},
-{
-"first_name": "eden",
-"last_name": "fontai",
-"image": "https://randomuser.me/api/portraits/women/17.jpg",
-"gender": "Female"
-},
-{
-"first_name": "maëva",
-"last_name": "pierre",
-"image": "https://randomuser.me/api/portraits/women/19.jpg",
-"gender": "Female"
-},
-{
-"first_name": "thomas",
-"last_name": "barbier",
-"image": "https://randomuser.me/api/portraits/men/31.jpg",
-"gender": "Male"
-},
-{
-"first_name": "lily",
-"last_name": "lefebvre",
-"image": "https://randomuser.me/api/portraits/women/76.jpg",
-"gender": "Female"
-},
-{
-"first_name": "lise",
-"last_name": "perez",
-"image": "https://randomuser.me/api/portraits/women/74.jpg",
-"gender": "Female"
-},
-{
-"first_name": "mila",
-"last_name": "moulin",
-"image": "https://randomuser.me/api/portraits/women/43.jpg",
-"gender": "Female"
-},
-{
-"first_name": "dylan",
-"last_name": "picard",
-"image": "https://randomuser.me/api/portraits/men/37.jpg",
-"gender": "Male"
-},
-{
-"first_name": "amandine",
-"last_name": "rodriguez",
-"image": "https://randomuser.me/api/portraits/women/65.jpg",
-"gender": "Female"
-},
-{
-"first_name": "diego",
-"last_name": "girard",
-"image": "https://randomuser.me/api/portraits/men/84.jpg",
-"gender": "Male"
-},
-{
-"first_name": "elouan",
-"last_name": "garnier",
-"image": "https://randomuser.me/api/portraits/men/94.jpg",
-"gender": "Male"
-},
-{
-"first_name": "apolline",
-"last_name": "fleury",
-"image": "https://randomuser.me/api/portraits/women/65.jpg",
-"gender": "Female"
-},
-{
-"first_name": "coline",
-"last_name": "menard",
-"image": "https://randomuser.me/api/portraits/women/83.jpg",
-"gender": "Female"
-},
-{
-"first_name": "maëly",
-"last_name": "le gall",
-"image": "https://randomuser.me/api/portraits/women/60.jpg",
-"gender": "Female"
-},
-{
-"first_name": "justin",
-"last_name": "robert",
-"image": "https://randomuser.me/api/portraits/men/20.jpg",
-"gender": "Male"
-},
-{
-"first_name": "ryan",
-"last_name": "faure",
-"image": "https://randomuser.me/api/portraits/men/16.jpg",
-"gender": "Male"
-},
-{
-"first_name": "ninon",
-"last_name": "brunet",
-"image": "https://randomuser.me/api/portraits/women/68.jpg",
-"gender": "Female"
-},
-{
-"first_name": "tessa",
-"last_name": "garnier",
-"image": "https://randomuser.me/api/portraits/women/54.jpg",
-"gender": "Female"
-},
-{
-"first_name": "ryan",
-"last_name": "bonnet",
-"image": "https://randomuser.me/api/portraits/men/28.jpg",
-"gender": "Male"
-},
-{
-"first_name": "aurélien",
-"last_name": "andre",
-"image": "https://randomuser.me/api/portraits/men/29.jpg",
-"gender": "Male"
-},
-{
-"first_name": "clément",
-"last_name": "dumas",
-"image": "https://randomuser.me/api/portraits/men/10.jpg",
-"gender": "Male"
-},
-{
-"first_name": "alexis",
-"last_name": "fournier",
-"image": "https://randomuser.me/api/portraits/men/83.jpg",
-"gender": "Male"
-},
-{
-"first_name": "valentin",
-"last_name": "lecomte",
-"image": "https://randomuser.me/api/portraits/men/44.jpg",
-"gender": "Male"
-},
-{
-"first_name": "florian",
-"last_name": "olivier",
-"image": "https://randomuser.me/api/portraits/men/36.jpg",
-"gender": "Male"
-},
-{
-"first_name": "ewen",
-"last_name": "lefebvre",
-"image": "https://randomuser.me/api/portraits/men/32.jpg",
-"gender": "Male"
-},
-{
-"first_name": "titouan",
-"last_name": "charles",
-"image": "https://randomuser.me/api/portraits/men/59.jpg",
-"gender": "Male"
-},
-{
-"first_name": "lila",
-"last_name": "aubert",
-"image": "https://randomuser.me/api/portraits/women/6.jpg",
-"gender": "Female"
-},
-{
-"first_name": "charline",
-"last_name": "caron",
-"image": "https://randomuser.me/api/portraits/women/49.jpg",
-"gender": "Female"
-},
-{
-"first_name": "soren",
-"last_name": "le gall",
-"image": "https://randomuser.me/api/portraits/men/77.jpg",
-"gender": "Male"
-},
-{
-"first_name": "fanny",
-"last_name": "louis",
-"image": "https://randomuser.me/api/portraits/women/90.jpg",
-"gender": "Female"
-},
-{
-"first_name": "julie",
-"last_name": "adam",
-"image": "https://randomuser.me/api/portraits/women/34.jpg",
-"gender": "Female"
-},
-{
-"first_name": "louka",
-"last_name": "boyer",
-"image": "https://randomuser.me/api/portraits/men/98.jpg",
-"gender": "Male"
-}
-]
diff --git a/erpnext/demo/data/room.json b/erpnext/demo/data/room.json
deleted file mode 100644
index 82f0868..0000000
--- a/erpnext/demo/data/room.json
+++ /dev/null
@@ -1,122 +0,0 @@
-[
- {
- "doctype": "Room",
- "room_name": "Lecture Hall 1",
- "room_number": "101",
- "seating_capacity": 80
- },
- {
- "doctype": "Room",
- "room_name": "Lecture Hall 2",
- "room_number": "102",
- "seating_capacity": 80
- },
- {
- "doctype": "Room",
- "room_name": "Lecture Hall 3",
- "room_number": "103",
- "seating_capacity": 80
- },
- {
- "doctype": "Room",
- "room_name": "Lecture Hall 4",
- "room_number": "104",
- "seating_capacity": 80
- },
- {
- "doctype": "Room",
- "room_name": "Lecture Hall 4",
- "room_number": "104",
- "seating_capacity": 80
- },
- {
- "doctype": "Room",
- "room_name": "Lecture Hall 5",
- "room_number": "201",
- "seating_capacity": 120
- },
- {
- "doctype": "Room",
- "room_name": "Lecture Hall 6",
- "room_number": "202",
- "seating_capacity": 120
- },
- {
- "doctype": "Room",
- "room_name": "Lecture Hall 7",
- "room_number": "203",
- "seating_capacity": 120
- },
- {
- "doctype": "Room",
- "room_name": "Computer Lab 1",
- "room_number": "301",
- "seating_capacity": 40
- },
- {
- "doctype": "Room",
- "room_name": "Computer Lab 2",
- "room_number": "302",
- "seating_capacity": 60
- },
- {
- "doctype": "Room",
- "room_name": "Seminar Hall 1",
- "room_number": "303",
- "seating_capacity": 240
- },
- {
- "doctype": "Room",
- "room_name": "Auditorium",
- "room_number": "400",
- "seating_capacity": 450
- },
- {
- "doctype": "Room",
- "room_name": "Exam hall 1",
- "room_number": "560",
- "seating_capacity": 70
- },
- {
- "doctype": "Room",
- "room_name": "Exam hall 2",
- "room_number": "561",
- "seating_capacity": 70
- },
- {
- "doctype": "Room",
- "room_name": "Exam hall 2",
- "room_number": "562",
- "seating_capacity": 70
- },
- {
- "doctype": "Room",
- "room_name": "Exam hall 3",
- "room_number": "563",
- "seating_capacity": 70
- },
- {
- "doctype": "Room",
- "room_name": "Exam hall 4",
- "room_number": "564",
- "seating_capacity": 70
- },
- {
- "doctype": "Room",
- "room_name": "Exam hall 5",
- "room_number": "565",
- "seating_capacity": 70
- },
- {
- "doctype": "Room",
- "room_name": "Exam hall 6",
- "room_number": "566",
- "seating_capacity": 70
- },
- {
- "doctype": "Room",
- "room_name": "Exam hall 7",
- "room_number": "567",
- "seating_capacity": 70
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/student_batch_name.json b/erpnext/demo/data/student_batch_name.json
deleted file mode 100644
index ef3f18d..0000000
--- a/erpnext/demo/data/student_batch_name.json
+++ /dev/null
@@ -1,10 +0,0 @@
-[
- {
- "doctype": "Student Batch Name",
- "batch_name": "Section-A"
- },
- {
- "doctype": "Student Batch Name",
- "batch_name": "Section-B"
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/data/user.json b/erpnext/demo/data/user.json
deleted file mode 100644
index 9ee5e78..0000000
--- a/erpnext/demo/data/user.json
+++ /dev/null
@@ -1,112 +0,0 @@
-[
- {
- "email": "test_demo@erpnext.com",
- "first_name": "Test",
- "last_name": "User"
- },
- {
- "email": "DianaPrince@example.com",
- "first_name": "Diana",
- "last_name": "Prince"
- },
- {
- "email": "ZatannaZatara@example.com",
- "first_name": "Zatanna",
- "last_name": "Zatara"
- },
- {
- "email": "HollyGranger@example.com",
- "first_name": "Holly",
- "last_name": "Granger"
- },
- {
- "email": "NeptuniaAquaria@example.com",
- "first_name": "Neptunia",
- "last_name": "Aquaria"
- },
- {
- "email": "ArthurCurry@example.com",
- "first_name": "Arthur",
- "last_name": "Curry"
- },
- {
- "email": "ThaliaAlGhul@example.com",
- "first_name": "Thalia",
- "last_name": "Al Ghul"
- },
- {
- "email": "MaxwellLord@example.com",
- "first_name": "Maxwell",
- "last_name": "Lord"
- },
- {
- "email": "GraceChoi@example.com",
- "first_name": "Grace",
- "last_name": "Choi"
- },
- {
- "email": "VandalSavage@example.com",
- "first_name": "Vandal",
- "last_name": "Savage"
- },
- {
- "email": "CaitlinSnow@example.com",
- "first_name": "Caitlin",
- "last_name": "Snow"
- },
- {
- "email": "RipHunter@example.com",
- "first_name": "Rip",
- "last_name": "Hunter"
- },
- {
- "email": "NicholasFury@example.com",
- "first_name": "Nicholas",
- "last_name": "Fury"
- },
- {
- "email": "PeterParker@example.com",
- "first_name": "Peter",
- "last_name": "Parker"
- },
- {
- "email": "JohnConstantine@example.com",
- "first_name": "John",
- "last_name": "Constantine"
- },
- {
- "email": "HalJordan@example.com",
- "first_name": "Hal",
- "last_name": "Jordan"
- },
- {
- "email": "VictorStone@example.com",
- "first_name": "Victor",
- "last_name": "Stone"
- },
- {
- "email": "BruceWayne@example.com",
- "first_name": "Bruce",
- "last_name": "Wayne"
- },
- {
- "email": "ClarkKent@example.com",
- "first_name": "Clark",
- "last_name": "Kent"
- },
- {
- "email": "BarryAllen@example.com",
- "first_name": "Barry",
- "last_name": "Allen"
- },
- {
- "email": "KaraZorEl@example.com",
- "first_name": "Kara",
- "last_name": "Zor El"
- },
- {
- "email": "demo@erpnext.com",
- "first_name": "Demo",
- "last_name": "User"
- }
-]
\ No newline at end of file
diff --git a/erpnext/demo/demo.py b/erpnext/demo/demo.py
deleted file mode 100644
index 4a18a99..0000000
--- a/erpnext/demo/demo.py
+++ /dev/null
@@ -1,97 +0,0 @@
-import sys
-
-import frappe
-import frappe.utils
-
-import erpnext
-from erpnext.demo.setup import education, manufacture, retail, setup_data
-from erpnext.demo.user import accounts
-from erpnext.demo.user import education as edu
-from erpnext.demo.user import fixed_asset, hr, manufacturing, projects, purchase, sales, stock
-
-"""
-Make a demo
-
-1. Start with a fresh account
-
-bench --site demo.erpnext.dev reinstall
-
-2. Install Demo
-
-bench --site demo.erpnext.dev execute erpnext.demo.demo.make
-
-3. If Demo breaks, to continue
-
-bench --site demo.erpnext.dev execute erpnext.demo.demo.simulate
-
-"""
-
-def make(domain='Manufacturing', days=100):
- frappe.flags.domain = domain
- frappe.flags.mute_emails = True
- setup_data.setup(domain)
- if domain== 'Manufacturing':
- manufacture.setup_data()
- elif domain == "Retail":
- retail.setup_data()
- elif domain== 'Education':
- education.setup_data()
-
- site = frappe.local.site
- frappe.destroy()
- frappe.init(site)
- frappe.connect()
-
- simulate(domain, days)
-
-def simulate(domain='Manufacturing', days=100):
- runs_for = frappe.flags.runs_for or days
- frappe.flags.company = erpnext.get_default_company()
- frappe.flags.mute_emails = True
-
- if not frappe.flags.start_date:
- # start date = 100 days back
- frappe.flags.start_date = frappe.utils.add_days(frappe.utils.nowdate(),
- -1 * runs_for)
-
- current_date = frappe.utils.getdate(frappe.flags.start_date)
-
- # continue?
- demo_last_date = frappe.db.get_global('demo_last_date')
- if demo_last_date:
- current_date = frappe.utils.add_days(frappe.utils.getdate(demo_last_date), 1)
-
- # run till today
- if not runs_for:
- runs_for = frappe.utils.date_diff(frappe.utils.nowdate(), current_date)
- # runs_for = 100
-
- fixed_asset.work()
- for i in range(runs_for):
- sys.stdout.write("\rSimulating {0}: Day {1}".format(
- current_date.strftime("%Y-%m-%d"), i))
- sys.stdout.flush()
- frappe.flags.current_date = current_date
- if current_date.weekday() in (5, 6):
- current_date = frappe.utils.add_days(current_date, 1)
- continue
- try:
- hr.work()
- purchase.work()
- stock.work()
- accounts.work()
- projects.run_projects(current_date)
- sales.work(domain)
- # run_messages()
-
- if domain=='Manufacturing':
- manufacturing.work()
- elif domain=='Education':
- edu.work()
-
- except Exception:
- frappe.db.set_global('demo_last_date', current_date)
- raise
- finally:
- current_date = frappe.utils.add_days(current_date, 1)
- frappe.db.commit()
diff --git a/erpnext/demo/domains.py b/erpnext/demo/domains.py
deleted file mode 100644
index 346787e..0000000
--- a/erpnext/demo/domains.py
+++ /dev/null
@@ -1,20 +0,0 @@
-data = {
- 'Manufacturing': {
- 'company_name': 'Wind Power LLC'
- },
- 'Retail': {
- 'company_name': 'Mobile Next',
- },
- 'Distribution': {
- 'company_name': 'Soltice Hardware',
- },
- 'Services': {
- 'company_name': 'Acme Consulting'
- },
- 'Education': {
- 'company_name': 'Whitmore College'
- },
- 'Non Profit': {
- 'company_name': 'Erpnext Foundation'
- }
-}
diff --git a/erpnext/demo/setup/__init__.py b/erpnext/demo/setup/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/demo/setup/__init__.py
+++ /dev/null
diff --git a/erpnext/demo/setup/education.py b/erpnext/demo/setup/education.py
deleted file mode 100644
index eb833f4..0000000
--- a/erpnext/demo/setup/education.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-import json
-import random
-from datetime import datetime
-
-import frappe
-from frappe.utils.make_random import get_random
-
-from erpnext.demo.setup.setup_data import import_json
-
-
-def setup_data():
- frappe.flags.mute_emails = True
- make_masters()
- setup_item()
- make_student_applicants()
- make_student_group()
- make_fees_category()
- make_fees_structure()
- make_assessment_groups()
- frappe.db.commit()
- frappe.clear_cache()
-
-def make_masters():
- import_json("Room")
- import_json("Department")
- import_json("Instructor")
- import_json("Course")
- import_json("Program")
- import_json("Student Batch Name")
- import_json("Assessment Criteria")
- import_json("Grading Scale")
- frappe.db.commit()
-
-def setup_item():
- items = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'item_education.json')).read())
- for i in items:
- item = frappe.new_doc('Item')
- item.update(i)
- item.min_order_qty = random.randint(10, 30)
- item.item_defaults[0].default_warehouse = frappe.get_all('Warehouse',
- filters={'warehouse_name': item.item_defaults[0].default_warehouse}, limit=1)[0].name
- item.insert()
-
-def make_student_applicants():
- blood_group = ["A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-"]
- male_names = []
- female_names = []
-
- file_path = get_json_path("Random Student Data")
- with open(file_path, "r") as open_file:
- random_student_data = json.loads(open_file.read())
- count = 1
-
- for d in random_student_data:
- if d.get('gender') == "Male":
- male_names.append(d.get('first_name').title())
-
- if d.get('gender') == "Female":
- female_names.append(d.get('first_name').title())
-
- for idx, d in enumerate(random_student_data):
- student_applicant = frappe.new_doc("Student Applicant")
- student_applicant.first_name = d.get('first_name').title()
- student_applicant.last_name = d.get('last_name').title()
- student_applicant.image = d.get('image')
- student_applicant.gender = d.get('gender')
- student_applicant.program = get_random("Program")
- student_applicant.blood_group = random.choice(blood_group)
- year = random.randint(1990, 1998)
- month = random.randint(1, 12)
- day = random.randint(1, 28)
- student_applicant.date_of_birth = datetime(year, month, day)
- student_applicant.mother_name = random.choice(female_names) + " " + d.get('last_name').title()
- student_applicant.father_name = random.choice(male_names) + " " + d.get('last_name').title()
- if student_applicant.gender == "Male":
- student_applicant.middle_name = random.choice(male_names)
- else:
- student_applicant.middle_name = random.choice(female_names)
- student_applicant.student_email_id = d.get('first_name') + "_" + \
- student_applicant.middle_name + "_" + d.get('last_name') + "@example.com"
- if count <5:
- student_applicant.insert()
- frappe.db.commit()
- else:
- student_applicant.submit()
- frappe.db.commit()
- count+=1
-
-def make_student_group():
- for term in frappe.db.get_list("Academic Term"):
- for program in frappe.db.get_list("Program"):
- sg_tool = frappe.new_doc("Student Group Creation Tool")
- sg_tool.academic_year = "2017-18"
- sg_tool.academic_term = term.name
- sg_tool.program = program.name
- for d in sg_tool.get_courses():
- d = frappe._dict(d)
- student_group = frappe.new_doc("Student Group")
- student_group.student_group_name = d.student_group_name
- student_group.group_based_on = d.group_based_on
- student_group.program = program.name
- student_group.course = d.course
- student_group.batch = d.batch
- student_group.academic_term = term.name
- student_group.academic_year = "2017-18"
- student_group.save()
- frappe.db.commit()
-
-def make_fees_category():
- fee_type = ["Tuition Fee", "Hostel Fee", "Logistics Fee",
- "Medical Fee", "Mess Fee", "Security Deposit"]
-
- fee_desc = {"Tuition Fee" : "Curricular activities which includes books, notebooks and faculty charges" ,
- "Hostel Fee" : "Stay of students in institute premises",
- "Logistics Fee" : "Lodging boarding of the students" ,
- "Medical Fee" : "Medical welfare of the students",
- "Mess Fee" : "Food and beverages for your ward",
- "Security Deposit" : "In case your child is found to have damaged institutes property"
- }
-
- for i in fee_type:
- fee_category = frappe.new_doc("Fee Category")
- fee_category.category_name = i
- fee_category.description = fee_desc[i]
- fee_category.insert()
- frappe.db.commit()
-
-def make_fees_structure():
- for d in frappe.db.get_list("Program"):
- program = frappe.get_doc("Program", d.name)
- for academic_term in ["2017-18 (Semester 1)", "2017-18 (Semester 2)", "2017-18 (Semester 3)"]:
- fee_structure = frappe.new_doc("Fee Structure")
- fee_structure.program = d.name
- fee_structure.academic_term = random.choice(frappe.db.get_list("Academic Term")).name
- for j in range(1,4):
- temp = {"fees_category": random.choice(frappe.db.get_list("Fee Category")).name , "amount" : random.randint(500,1000)}
- fee_structure.append("components", temp)
- fee_structure.insert()
- program.append("fees", {"academic_term": academic_term, "fee_structure": fee_structure.name, "amount": fee_structure.total_amount})
- program.save()
- frappe.db.commit()
-
-def make_assessment_groups():
- for year in frappe.db.get_list("Academic Year"):
- ag = frappe.new_doc('Assessment Group')
- ag.assessment_group_name = year.name
- ag.parent_assessment_group = "All Assessment Groups"
- ag.is_group = 1
- ag.insert()
- for term in frappe.db.get_list("Academic Term", filters = {"academic_year": year.name}):
- ag1 = frappe.new_doc('Assessment Group')
- ag1.assessment_group_name = term.name
- ag1.parent_assessment_group = ag.name
- ag1.is_group = 1
- ag1.insert()
- for assessment_group in ['Term I', 'Term II']:
- ag2 = frappe.new_doc('Assessment Group')
- ag2.assessment_group_name = ag1.name + " " + assessment_group
- ag2.parent_assessment_group = ag1.name
- ag2.insert()
- frappe.db.commit()
-
-
-def get_json_path(doctype):
- return frappe.get_app_path('erpnext', 'demo', 'data', frappe.scrub(doctype) + '.json')
-
-def weighted_choice(weights):
- totals = []
- running_total = 0
-
- for w in weights:
- running_total += w
- totals.append(running_total)
-
- rnd = random.random() * running_total
- for i, total in enumerate(totals):
- if rnd < total:
- return i
diff --git a/erpnext/demo/setup/manufacture.py b/erpnext/demo/setup/manufacture.py
deleted file mode 100644
index fe1a1fb..0000000
--- a/erpnext/demo/setup/manufacture.py
+++ /dev/null
@@ -1,140 +0,0 @@
-import json
-import random
-
-import frappe
-from frappe.utils import add_days, nowdate
-
-from erpnext.demo.domains import data
-from erpnext.demo.setup.setup_data import import_json
-
-
-def setup_data():
- import_json("Location")
- import_json("Asset Category")
- setup_item()
- setup_workstation()
- setup_asset()
- import_json('Operation')
- setup_item_price()
- show_item_groups_in_website()
- import_json('BOM', submit=True)
- frappe.db.commit()
- frappe.clear_cache()
-
-def setup_workstation():
- workstations = [u'Drilling Machine 1', u'Lathe 1', u'Assembly Station 1', u'Assembly Station 2', u'Packing and Testing Station']
- for w in workstations:
- frappe.get_doc({
- "doctype": "Workstation",
- "workstation_name": w,
- "holiday_list": frappe.get_all("Holiday List")[0].name,
- "hour_rate_consumable": int(random.random() * 20),
- "hour_rate_electricity": int(random.random() * 10),
- "hour_rate_labour": int(random.random() * 40),
- "hour_rate_rent": int(random.random() * 10),
- "working_hours": [
- {
- "enabled": 1,
- "start_time": "8:00:00",
- "end_time": "15:00:00"
- }
- ]
- }).insert()
-
-def show_item_groups_in_website():
- """set show_in_website=1 for Item Groups"""
- products = frappe.get_doc("Item Group", "Products")
- products.show_in_website = 1
- products.route = 'products'
- products.save()
-
-def setup_asset():
- assets = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'asset.json')).read())
- for d in assets:
- asset = frappe.new_doc('Asset')
- asset.update(d)
- asset.purchase_date = add_days(nowdate(), -random.randint(20, 1500))
- asset.next_depreciation_date = add_days(asset.purchase_date, 30)
- asset.warehouse = "Stores - WPL"
- asset.set_missing_values()
- asset.make_depreciation_schedule()
- asset.flags.ignore_validate = True
- asset.flags.ignore_mandatory = True
- asset.save()
- asset.submit()
-
-def setup_item():
- items = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'item.json')).read())
- for i in items:
- item = frappe.new_doc('Item')
- item.update(i)
- if hasattr(item, 'item_defaults') and item.item_defaults[0].default_warehouse:
- item.item_defaults[0].company = data.get("Manufacturing").get('company_name')
- warehouse = frappe.get_all('Warehouse', filters={'warehouse_name': item.item_defaults[0].default_warehouse}, limit=1)
- if warehouse:
- item.item_defaults[0].default_warehouse = warehouse[0].name
- item.insert()
-
-def setup_product_bundle():
- frappe.get_doc({
- 'doctype': 'Product Bundle',
- 'new_item_code': 'Wind Mill A Series with Spare Bearing',
- 'items': [
- {'item_code': 'Wind Mill A Series', 'qty': 1},
- {'item_code': 'Bearing Collar', 'qty': 1},
- {'item_code': 'Bearing Assembly', 'qty': 1},
- ]
- }).insert()
-
-def setup_item_price():
- frappe.db.sql("delete from `tabItem Price`")
-
- standard_selling = {
- "Base Bearing Plate": 28,
- "Base Plate": 21,
- "Bearing Assembly": 300,
- "Bearing Block": 14,
- "Bearing Collar": 103.6,
- "Bearing Pipe": 63,
- "Blade Rib": 46.2,
- "Disc Collars": 42,
- "External Disc": 56,
- "Internal Disc": 70,
- "Shaft": 340,
- "Stand": 400,
- "Upper Bearing Plate": 300,
- "Wind Mill A Series": 320,
- "Wind Mill A Series with Spare Bearing": 750,
- "Wind MIll C Series": 400,
- "Wind Turbine": 400,
- "Wing Sheet": 30.8
- }
-
- standard_buying = {
- "Base Bearing Plate": 20,
- "Base Plate": 28,
- "Base Plate Un Painted": 16,
- "Bearing Block": 13,
- "Bearing Collar": 96.4,
- "Bearing Pipe": 55,
- "Blade Rib": 38,
- "Disc Collars": 34,
- "External Disc": 50,
- "Internal Disc": 60,
- "Shaft": 250,
- "Stand": 300,
- "Upper Bearing Plate": 200,
- "Wing Sheet": 25
- }
-
- for price_list in ("standard_buying", "standard_selling"):
- for item, rate in locals().get(price_list).items():
- frappe.get_doc({
- "doctype": "Item Price",
- "price_list": price_list.replace("_", " ").title(),
- "item_code": item,
- "selling": 1 if price_list=="standard_selling" else 0,
- "buying": 1 if price_list=="standard_buying" else 0,
- "price_list_rate": rate,
- "currency": "USD"
- }).insert()
diff --git a/erpnext/demo/setup/retail.py b/erpnext/demo/setup/retail.py
deleted file mode 100644
index 0469264..0000000
--- a/erpnext/demo/setup/retail.py
+++ /dev/null
@@ -1,62 +0,0 @@
-import json
-
-import frappe
-
-from erpnext.demo.domains import data
-
-
-def setup_data():
- setup_item()
- setup_item_price()
- frappe.db.commit()
- frappe.clear_cache()
-
-def setup_item():
- items = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'item.json')).read())
- for i in items:
- if not i.get("domain") == "Retail": continue
- item = frappe.new_doc('Item')
- item.update(i)
- if hasattr(item, 'item_defaults') and item.item_defaults[0].default_warehouse:
- item.item_defaults[0].company = data.get("Retail").get('company_name')
- warehouse = frappe.get_all('Warehouse', filters={'warehouse_name': item.item_defaults[0].default_warehouse}, limit=1)
- if warehouse:
- item.item_defaults[0].default_warehouse = warehouse[0].name
- item.insert()
-
-def setup_item_price():
- frappe.db.sql("delete from `tabItem Price`")
-
- standard_selling = {
- "OnePlus 6": 579,
- "OnePlus 6T": 600,
- "Xiaomi Poco F1": 300,
- "Iphone XS": 999,
- "Samsung Galaxy S9": 720,
- "Sony Bluetooth Headphone": 99,
- "Xiaomi Phone Repair": 10,
- "Samsung Phone Repair": 20,
- "OnePlus Phone Repair": 15,
- "Apple Phone Repair": 30,
- }
-
- standard_buying = {
- "OnePlus 6": 300,
- "OnePlus 6T": 350,
- "Xiaomi Poco F1": 200,
- "Iphone XS": 600,
- "Samsung Galaxy S9": 500,
- "Sony Bluetooth Headphone": 69
- }
-
- for price_list in ("standard_buying", "standard_selling"):
- for item, rate in locals().get(price_list).items():
- frappe.get_doc({
- "doctype": "Item Price",
- "price_list": price_list.replace("_", " ").title(),
- "item_code": item,
- "selling": 1 if price_list=="standard_selling" else 0,
- "buying": 1 if price_list=="standard_buying" else 0,
- "price_list_rate": rate,
- "currency": "USD"
- }).insert()
diff --git a/erpnext/demo/setup/setup_data.py b/erpnext/demo/setup/setup_data.py
deleted file mode 100644
index 7137c6e..0000000
--- a/erpnext/demo/setup/setup_data.py
+++ /dev/null
@@ -1,447 +0,0 @@
-import json
-import random
-
-import frappe
-from frappe import _
-from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
-from frappe.utils import cstr, flt, now_datetime, random_string
-from frappe.utils.make_random import add_random_children, get_random
-from frappe.utils.nestedset import get_root_of
-
-import erpnext
-from erpnext.demo.domains import data
-
-
-def setup(domain):
- frappe.flags.in_demo = 1
- complete_setup(domain)
- setup_demo_page()
- setup_fiscal_year()
- setup_holiday_list()
- setup_user()
- setup_employee()
- setup_user_roles(domain)
- setup_role_permissions()
- setup_custom_field_for_domain()
-
- employees = frappe.get_all('Employee', fields=['name', 'date_of_joining'])
-
- # monthly salary
- setup_salary_structure(employees[:5], 0)
-
- # based on timesheet
- setup_salary_structure(employees[5:], 1)
-
- setup_leave_allocation()
- setup_customer()
- setup_supplier()
- setup_warehouse()
- import_json('Address')
- import_json('Contact')
- import_json('Lead')
- setup_currency_exchange()
- #setup_mode_of_payment()
- setup_account_to_expense_type()
- setup_budget()
- setup_pos_profile()
-
- frappe.db.commit()
- frappe.clear_cache()
-
-def complete_setup(domain='Manufacturing'):
- print("Complete Setup...")
- from frappe.desk.page.setup_wizard.setup_wizard import setup_complete
-
- if not frappe.get_all('Company', limit=1):
- setup_complete({
- "full_name": "Test User",
- "email": "test_demo@erpnext.com",
- "company_tagline": 'Awesome Products and Services',
- "password": "demo",
- "fy_start_date": "2015-01-01",
- "fy_end_date": "2015-12-31",
- "bank_account": "National Bank",
- "domains": [domain],
- "company_name": data.get(domain).get('company_name'),
- "chart_of_accounts": "Standard",
- "company_abbr": ''.join([d[0] for d in data.get(domain).get('company_name').split()]).upper(),
- "currency": 'USD',
- "timezone": 'America/New_York',
- "country": 'United States',
- "language": "english"
- })
-
- company = erpnext.get_default_company()
-
- if company:
- company_doc = frappe.get_doc("Company", company)
- company_doc.db_set('default_payroll_payable_account',
- frappe.db.get_value('Account', dict(account_name='Payroll Payable')))
-
-def setup_demo_page():
- # home page should always be "start"
- website_settings = frappe.get_doc("Website Settings", "Website Settings")
- website_settings.home_page = "demo"
- website_settings.save()
-
-def setup_fiscal_year():
- fiscal_year = None
- for year in range(2010, now_datetime().year + 1, 1):
- try:
- fiscal_year = frappe.get_doc({
- "doctype": "Fiscal Year",
- "year": cstr(year),
- "year_start_date": "{0}-01-01".format(year),
- "year_end_date": "{0}-12-31".format(year)
- }).insert()
- except frappe.DuplicateEntryError:
- pass
-
- # set the last fiscal year (current year) as default
- if fiscal_year:
- fiscal_year.set_as_default()
-
-def setup_holiday_list():
- """Setup Holiday List for the current year"""
- year = now_datetime().year
- holiday_list = frappe.get_doc({
- "doctype": "Holiday List",
- "holiday_list_name": str(year),
- "from_date": "{0}-01-01".format(year),
- "to_date": "{0}-12-31".format(year),
- })
- holiday_list.insert()
- holiday_list.weekly_off = "Saturday"
- holiday_list.get_weekly_off_dates()
- holiday_list.weekly_off = "Sunday"
- holiday_list.get_weekly_off_dates()
- holiday_list.save()
-
- frappe.set_value("Company", erpnext.get_default_company(), "default_holiday_list", holiday_list.name)
-
-
-def setup_user():
- frappe.db.sql('delete from tabUser where name not in ("Guest", "Administrator")')
- for u in json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'user.json')).read()):
- user = frappe.new_doc("User")
- user.update(u)
- user.flags.no_welcome_mail = True
- user.new_password = 'Demo1234567!!!'
- user.insert()
-
-def setup_employee():
- frappe.db.set_value("HR Settings", None, "emp_created_by", "Naming Series")
- frappe.db.commit()
-
- for d in frappe.get_all('Salary Component'):
- salary_component = frappe.get_doc('Salary Component', d.name)
- salary_component.append('accounts', dict(
- company=erpnext.get_default_company(),
- account=frappe.get_value('Account', dict(account_name=('like', 'Salary%')))
- ))
- salary_component.save()
-
- import_json('Employee')
- holiday_list = frappe.db.get_value("Holiday List", {"holiday_list_name": str(now_datetime().year)}, 'name')
- frappe.db.sql('''update tabEmployee set holiday_list={0}'''.format(holiday_list))
-
-def setup_salary_structure(employees, salary_slip_based_on_timesheet=0):
- ss = frappe.new_doc('Salary Structure')
- ss.name = "Sample Salary Structure - " + random_string(5)
- ss.salary_slip_based_on_timesheet = salary_slip_based_on_timesheet
-
- if salary_slip_based_on_timesheet:
- ss.salary_component = 'Basic'
- ss.hour_rate = flt(random.random() * 10, 2)
- else:
- ss.payroll_frequency = 'Monthly'
-
- ss.payment_account = frappe.get_value('Account',
- {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
-
- ss.append('earnings', {
- 'salary_component': 'Basic',
- "abbr":'B',
- 'formula': 'base*.2',
- 'amount_based_on_formula': 1,
- "idx": 1
- })
- ss.append('deductions', {
- 'salary_component': 'Income Tax',
- "abbr":'IT',
- 'condition': 'base > 10000',
- 'formula': 'base*.1',
- "idx": 1
- })
- ss.insert()
- ss.submit()
-
- for e in employees:
- sa = frappe.new_doc("Salary Structure Assignment")
- sa.employee = e.name
- sa.salary_structure = ss.name
- sa.from_date = "2015-01-01"
- sa.base = random.random() * 10000
- sa.insert()
- sa.submit()
-
- return ss
-
-def setup_user_roles(domain):
- user = frappe.get_doc('User', 'demo@erpnext.com')
- user.add_roles('HR User', 'HR Manager', 'Accounts User', 'Accounts Manager',
- 'Stock User', 'Stock Manager', 'Sales User', 'Sales Manager', 'Purchase User',
- 'Purchase Manager', 'Projects User', 'Manufacturing User', 'Manufacturing Manager',
- 'Support Team')
-
- if domain == "Education":
- user.add_roles('Academics User')
-
- if not frappe.db.get_global('demo_hr_user'):
- user = frappe.get_doc('User', 'CaitlinSnow@example.com')
- user.add_roles('HR User', 'HR Manager', 'Accounts User')
- frappe.db.set_global('demo_hr_user', user.name)
- update_employee_department(user.name, 'Human Resources')
- for d in frappe.get_all('User Permission', filters={"user": "CaitlinSnow@example.com"}):
- frappe.delete_doc('User Permission', d.name)
-
- if not frappe.db.get_global('demo_sales_user_1'):
- user = frappe.get_doc('User', 'VandalSavage@example.com')
- user.add_roles('Sales User')
- update_employee_department(user.name, 'Sales')
- frappe.db.set_global('demo_sales_user_1', user.name)
-
- if not frappe.db.get_global('demo_sales_user_2'):
- user = frappe.get_doc('User', 'GraceChoi@example.com')
- user.add_roles('Sales User', 'Sales Manager', 'Accounts User')
- update_employee_department(user.name, 'Sales')
- frappe.db.set_global('demo_sales_user_2', user.name)
-
- if not frappe.db.get_global('demo_purchase_user'):
- user = frappe.get_doc('User', 'MaxwellLord@example.com')
- user.add_roles('Purchase User', 'Purchase Manager', 'Accounts User', 'Stock User')
- update_employee_department(user.name, 'Purchase')
- frappe.db.set_global('demo_purchase_user', user.name)
-
- if not frappe.db.get_global('demo_manufacturing_user'):
- user = frappe.get_doc('User', 'NeptuniaAquaria@example.com')
- user.add_roles('Manufacturing User', 'Stock Manager', 'Stock User', 'Purchase User', 'Accounts User')
- update_employee_department(user.name, 'Production')
- frappe.db.set_global('demo_manufacturing_user', user.name)
-
- if not frappe.db.get_global('demo_stock_user'):
- user = frappe.get_doc('User', 'HollyGranger@example.com')
- user.add_roles('Manufacturing User', 'Stock User', 'Purchase User', 'Accounts User')
- update_employee_department(user.name, 'Production')
- frappe.db.set_global('demo_stock_user', user.name)
-
- if not frappe.db.get_global('demo_accounts_user'):
- user = frappe.get_doc('User', 'BarryAllen@example.com')
- user.add_roles('Accounts User', 'Accounts Manager', 'Sales User', 'Purchase User')
- update_employee_department(user.name, 'Accounts')
- frappe.db.set_global('demo_accounts_user', user.name)
-
- if not frappe.db.get_global('demo_projects_user'):
- user = frappe.get_doc('User', 'PeterParker@example.com')
- user.add_roles('HR User', 'Projects User')
- update_employee_department(user.name, 'Management')
- frappe.db.set_global('demo_projects_user', user.name)
-
- if domain == "Education":
- if not frappe.db.get_global('demo_education_user'):
- user = frappe.get_doc('User', 'ArthurCurry@example.com')
- user.add_roles('Academics User')
- update_employee_department(user.name, 'Management')
- frappe.db.set_global('demo_education_user', user.name)
-
- #Add Expense Approver
- user = frappe.get_doc('User', 'ClarkKent@example.com')
- user.add_roles('Expense Approver')
-
-def setup_leave_allocation():
- year = now_datetime().year
- for employee in frappe.get_all('Employee', fields=['name']):
- leave_types = frappe.get_all("Leave Type", fields=['name', 'max_continuous_days_allowed'])
- for leave_type in leave_types:
- if not leave_type.max_continuous_days_allowed:
- leave_type.max_continuous_days_allowed = 10
-
- leave_allocation = frappe.get_doc({
- "doctype": "Leave Allocation",
- "employee": employee.name,
- "from_date": "{0}-01-01".format(year),
- "to_date": "{0}-12-31".format(year),
- "leave_type": leave_type.name,
- "new_leaves_allocated": random.randint(1, int(leave_type.max_continuous_days_allowed))
- })
- leave_allocation.insert()
- leave_allocation.submit()
- frappe.db.commit()
-
-def setup_customer():
- customers = [u'Asian Junction', u'Life Plan Counselling', u'Two Pesos', u'Mr Fables', u'Intelacard', u'Big D Supermarkets', u'Adaptas', u'Nelson Brothers', u'Landskip Yard Care', u'Buttrey Food & Drug', u'Fayva', u'Asian Fusion', u'Crafts Canada', u'Consumers and Consumers Express', u'Netobill', u'Choices', u'Chi-Chis', u'Red Food', u'Endicott Shoes', u'Hind Enterprises']
- for c in customers:
- frappe.get_doc({
- "doctype": "Customer",
- "customer_name": c,
- "customer_group": "Commercial",
- "customer_type": random.choice(["Company", "Individual"]),
- "territory": "Rest Of The World"
- }).insert()
-
-def setup_supplier():
- suppliers = [u'Helios Air', u'Ks Merchandise', u'HomeBase', u'Scott Ties', u'Reliable Investments', u'Nan Duskin', u'Rainbow Records', u'New World Realty', u'Asiatic Solutions', u'Eagle Hardware', u'Modern Electricals']
- for s in suppliers:
- frappe.get_doc({
- "doctype": "Supplier",
- "supplier_name": s,
- "supplier_group": random.choice(["Services", "Raw Material"]),
- }).insert()
-
-def setup_warehouse():
- w = frappe.new_doc('Warehouse')
- w.warehouse_name = 'Supplier'
- w.insert()
-
-def setup_currency_exchange():
- frappe.get_doc({
- 'doctype': 'Currency Exchange',
- 'from_currency': 'EUR',
- 'to_currency': 'USD',
- 'exchange_rate': 1.13
- }).insert()
-
- frappe.get_doc({
- 'doctype': 'Currency Exchange',
- 'from_currency': 'CNY',
- 'to_currency': 'USD',
- 'exchange_rate': 0.16
- }).insert()
-
-def setup_mode_of_payment():
- company_abbr = frappe.get_cached_value('Company', erpnext.get_default_company(), "abbr")
- account_dict = {'Cash': 'Cash - '+ company_abbr , 'Bank': 'National Bank - '+ company_abbr}
- for payment_mode in frappe.get_all('Mode of Payment', fields = ["name", "type"]):
- if payment_mode.type:
- mop = frappe.get_doc('Mode of Payment', payment_mode.name)
- mop.append('accounts', {
- 'company': erpnext.get_default_company(),
- 'default_account': account_dict.get(payment_mode.type)
- })
- mop.save(ignore_permissions=True)
-
-def setup_account():
- frappe.flags.in_import = True
- data = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data',
- 'account.json')).read())
- for d in data:
- doc = frappe.new_doc('Account')
- doc.update(d)
- doc.parent_account = frappe.db.get_value('Account', {'account_name': doc.parent_account})
- doc.insert()
-
- frappe.flags.in_import = False
-
-def setup_account_to_expense_type():
- company_abbr = frappe.get_cached_value('Company', erpnext.get_default_company(), "abbr")
- expense_types = [{'name': _('Calls'), "account": "Sales Expenses - "+ company_abbr},
- {'name': _('Food'), "account": "Entertainment Expenses - "+ company_abbr},
- {'name': _('Medical'), "account": "Utility Expenses - "+ company_abbr},
- {'name': _('Others'), "account": "Miscellaneous Expenses - "+ company_abbr},
- {'name': _('Travel'), "account": "Travel Expenses - "+ company_abbr}]
-
- for expense_type in expense_types:
- doc = frappe.get_doc("Expense Claim Type", expense_type["name"])
- doc.append("accounts", {
- "company" : erpnext.get_default_company(),
- "default_account" : expense_type["account"]
- })
- doc.save(ignore_permissions=True)
-
-def setup_budget():
- fiscal_years = frappe.get_all("Fiscal Year", order_by="year_start_date")[-2:]
-
- for fy in fiscal_years:
- budget = frappe.new_doc("Budget")
- budget.cost_center = get_random("Cost Center")
- budget.fiscal_year = fy.name
- budget.action_if_annual_budget_exceeded = "Warn"
- expense_ledger_count = frappe.db.count("Account", {"is_group": "0", "root_type": "Expense"})
-
- add_random_children(budget, "accounts", rows=random.randint(10, expense_ledger_count),
- randomize = {
- "account": ("Account", {"is_group": "0", "root_type": "Expense"})
- }, unique="account")
-
- for d in budget.accounts:
- d.budget_amount = random.randint(5, 100) * 10000
-
- budget.save()
- budget.submit()
-
-def setup_pos_profile():
- company_abbr = frappe.get_cached_value('Company', erpnext.get_default_company(), "abbr")
- pos = frappe.new_doc('POS Profile')
- pos.user = frappe.db.get_global('demo_accounts_user')
- pos.name = "Demo POS Profile"
- pos.naming_series = 'SINV-'
- pos.update_stock = 0
- pos.write_off_account = 'Cost of Goods Sold - '+ company_abbr
- pos.write_off_cost_center = 'Main - '+ company_abbr
- pos.customer_group = get_root_of('Customer Group')
- pos.territory = get_root_of('Territory')
-
- pos.append('payments', {
- 'mode_of_payment': frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name'),
- 'amount': 0.0,
- 'default': 1
- })
-
- pos.insert()
-
-def setup_role_permissions():
- role_permissions = {'Batch': ['Accounts User', 'Item Manager']}
- for doctype, roles in role_permissions.items():
- for role in roles:
- if not frappe.db.get_value('Custom DocPerm',
- {'parent': doctype, 'role': role}):
- frappe.get_doc({
- 'doctype': 'Custom DocPerm',
- 'role': role,
- 'read': 1,
- 'write': 1,
- 'create': 1,
- 'delete': 1,
- 'parent': doctype
- }).insert(ignore_permissions=True)
-
-def import_json(doctype, submit=False, values=None):
- frappe.flags.in_import = True
- data = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data',
- frappe.scrub(doctype) + '.json')).read())
- for d in data:
- doc = frappe.new_doc(doctype)
- doc.update(d)
- doc.insert()
- if submit:
- doc.submit()
-
- frappe.db.commit()
-
- frappe.flags.in_import = False
-
-def update_employee_department(user_id, department):
- employee = frappe.db.get_value('Employee', {"user_id": user_id}, 'name')
- department = frappe.db.get_value('Department', {'department_name': department}, 'name')
- frappe.db.set_value('Employee', employee, 'department', department)
-
-def setup_custom_field_for_domain():
- field = {
- "Item": [
- dict(fieldname='domain', label='Domain',
- fieldtype='Select', hidden=1, default="Manufacturing",
- options="Manufacturing\nService\nDistribution\nRetail"
- )
- ]
- }
- create_custom_fields(field)
diff --git a/erpnext/demo/user/__init__.py b/erpnext/demo/user/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/demo/user/__init__.py
+++ /dev/null
diff --git a/erpnext/demo/user/accounts.py b/erpnext/demo/user/accounts.py
deleted file mode 100644
index 273a3f9..0000000
--- a/erpnext/demo/user/accounts.py
+++ /dev/null
@@ -1,127 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-
-import random
-
-import frappe
-from frappe.desk import query_report
-from frappe.utils import random_string
-from frappe.utils.make_random import get_random
-
-import erpnext
-from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry_against_invoice
-from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
-from erpnext.accounts.doctype.payment_request.payment_request import (
- make_payment_entry,
- make_payment_request,
-)
-from erpnext.demo.user.sales import make_sales_order
-from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice
-from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice
-
-
-def work():
- frappe.set_user(frappe.db.get_global('demo_accounts_user'))
-
- if random.random() <= 0.6:
- report = "Ordered Items to be Billed"
- for so in list(set([r[0] for r in query_report.run(report)["result"]
- if r[0]!="Total"]))[:random.randint(1, 5)]:
- try:
- si = frappe.get_doc(make_sales_invoice(so))
- si.posting_date = frappe.flags.current_date
- for d in si.get("items"):
- if not d.income_account:
- d.income_account = "Sales - {}".format(frappe.get_cached_value('Company', si.company, 'abbr'))
- si.insert()
- si.submit()
- frappe.db.commit()
- except frappe.ValidationError:
- pass
-
- if random.random() <= 0.6:
- report = "Received Items to be Billed"
- for pr in list(set([r[0] for r in query_report.run(report)["result"]
- if r[0]!="Total"]))[:random.randint(1, 5)]:
- try:
- pi = frappe.get_doc(make_purchase_invoice(pr))
- pi.posting_date = frappe.flags.current_date
- pi.bill_no = random_string(6)
- pi.insert()
- pi.submit()
- frappe.db.commit()
- except frappe.ValidationError:
- pass
-
-
- if random.random() < 0.5:
- make_payment_entries("Sales Invoice", "Accounts Receivable")
-
- if random.random() < 0.5:
- make_payment_entries("Purchase Invoice", "Accounts Payable")
-
- if random.random() < 0.4:
- #make payment request against sales invoice
- sales_invoice_name = get_random("Sales Invoice", filters={"docstatus": 1})
- if sales_invoice_name:
- si = frappe.get_doc("Sales Invoice", sales_invoice_name)
- if si.outstanding_amount > 0:
- payment_request = make_payment_request(dt="Sales Invoice", dn=si.name, recipient_id=si.contact_email,
- submit_doc=True, mute_email=True, use_dummy_message=True)
-
- payment_entry = frappe.get_doc(make_payment_entry(payment_request.name))
- payment_entry.posting_date = frappe.flags.current_date
- payment_entry.submit()
-
- make_pos_invoice()
-
-def make_payment_entries(ref_doctype, report):
-
- outstanding_invoices = frappe.get_all(ref_doctype, fields=["name"],
- filters={
- "company": erpnext.get_default_company(),
- "outstanding_amount": (">", 0.0)
- })
-
- # make Payment Entry
- for inv in outstanding_invoices[:random.randint(1, 2)]:
- pe = get_payment_entry(ref_doctype, inv.name)
- pe.posting_date = frappe.flags.current_date
- pe.reference_no = random_string(6)
- pe.reference_date = frappe.flags.current_date
- pe.insert()
- pe.submit()
- frappe.db.commit()
- outstanding_invoices.remove(inv)
-
- # make payment via JV
- for inv in outstanding_invoices[:1]:
- jv = frappe.get_doc(get_payment_entry_against_invoice(ref_doctype, inv.name))
- jv.posting_date = frappe.flags.current_date
- jv.cheque_no = random_string(6)
- jv.cheque_date = frappe.flags.current_date
- jv.insert()
- jv.submit()
- frappe.db.commit()
-
-def make_pos_invoice():
- make_sales_order()
-
- for data in frappe.get_all('Sales Order', fields=["name"],
- filters = [["per_billed", "<", "100"]]):
- si = frappe.get_doc(make_sales_invoice(data.name))
- si.is_pos =1
- si.posting_date = frappe.flags.current_date
- for d in si.get("items"):
- if not d.income_account:
- d.income_account = "Sales - {}".format(frappe.get_cached_value('Company', si.company, 'abbr'))
- si.set_missing_values()
- make_payment_entries_for_pos_invoice(si)
- si.insert()
- si.submit()
-
-def make_payment_entries_for_pos_invoice(si):
- for data in si.payments:
- data.amount = si.outstanding_amount
- return
diff --git a/erpnext/demo/user/education.py b/erpnext/demo/user/education.py
deleted file mode 100644
index 47519c1..0000000
--- a/erpnext/demo/user/education.py
+++ /dev/null
@@ -1,123 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-
-import random
-from datetime import timedelta
-
-import frappe
-from frappe.utils import cstr
-from frappe.utils.make_random import get_random
-
-from erpnext.education.api import (
- collect_fees,
- enroll_student,
- get_course,
- get_fee_schedule,
- get_student_group_students,
- make_attendance_records,
-)
-
-
-def work():
- frappe.set_user(frappe.db.get_global('demo_education_user'))
- for d in range(20):
- approve_random_student_applicant()
- enroll_random_student(frappe.flags.current_date)
- # if frappe.flags.current_date.weekday()== 0:
- # make_course_schedule(frappe.flags.current_date, frappe.utils.add_days(frappe.flags.current_date, 5))
- mark_student_attendance(frappe.flags.current_date)
- # make_assessment_plan()
- make_fees()
-
-def approve_random_student_applicant():
- random_student = get_random("Student Applicant", {"application_status": "Applied"})
- if random_student:
- status = ["Approved", "Rejected"]
- frappe.db.set_value("Student Applicant", random_student, "application_status", status[weighted_choice([9,3])])
-
-def enroll_random_student(current_date):
- batch = ["Section-A", "Section-B"]
- random_student = get_random("Student Applicant", {"application_status": "Approved"})
- if random_student:
- enrollment = enroll_student(random_student)
- enrollment.academic_year = get_random("Academic Year")
- enrollment.enrollment_date = current_date
- enrollment.student_batch_name = batch[weighted_choice([9,3])]
- fee_schedule = get_fee_schedule(enrollment.program)
- for fee in fee_schedule:
- enrollment.append("fees", fee)
- enrolled_courses = get_course(enrollment.program)
- for course in enrolled_courses:
- enrollment.append("courses", course)
- enrollment.submit()
- frappe.db.commit()
- assign_student_group(enrollment.student, enrollment.student_name, enrollment.program,
- enrolled_courses, enrollment.student_batch_name)
-
-def assign_student_group(student, student_name, program, courses, batch):
- course_list = [d["course"] for d in courses]
- for d in frappe.get_list("Student Group", fields=("name"), filters={"program": program, "course":("in", course_list), "disabled": 0}):
- student_group = frappe.get_doc("Student Group", d.name)
- student_group.append("students", {"student": student, "student_name": student_name,
- "group_roll_number":len(student_group.students)+1, "active":1})
- student_group.save()
- student_batch = frappe.get_list("Student Group", fields=("name"), filters={"program": program, "group_based_on":"Batch", "batch":batch, "disabled": 0})[0]
- student_batch_doc = frappe.get_doc("Student Group", student_batch.name)
- student_batch_doc.append("students", {"student": student, "student_name": student_name,
- "group_roll_number":len(student_batch_doc.students)+1, "active":1})
- student_batch_doc.save()
- frappe.db.commit()
-
-def mark_student_attendance(current_date):
- status = ["Present", "Absent"]
- for d in frappe.db.get_list("Student Group", filters={"group_based_on": "Batch", "disabled": 0}):
- students = get_student_group_students(d.name)
- for stud in students:
- make_attendance_records(stud.student, stud.student_name, status[weighted_choice([9,4])], None, d.name, current_date)
-
-def make_fees():
- for d in range(1,10):
- random_fee = get_random("Fees", {"paid_amount": 0})
- collect_fees(random_fee, frappe.db.get_value("Fees", random_fee, "outstanding_amount"))
-
-def make_assessment_plan(date):
- for d in range(1,4):
- random_group = get_random("Student Group", {"group_based_on": "Course", "disabled": 0}, True)
- doc = frappe.new_doc("Assessment Plan")
- doc.student_group = random_group.name
- doc.course = random_group.course
- doc.assessment_group = get_random("Assessment Group", {"is_group": 0, "parent": "2017-18 (Semester 2)"})
- doc.grading_scale = get_random("Grading Scale")
- doc.maximum_assessment_score = 100
-
-def make_course_schedule(start_date, end_date):
- for d in frappe.db.get_list("Student Group"):
- cs = frappe.new_doc("Scheduling Tool")
- cs.student_group = d.name
- cs.room = get_random("Room")
- cs.instructor = get_random("Instructor")
- cs.course_start_date = cstr(start_date)
- cs.course_end_date = cstr(end_date)
- day = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
- for x in range(3):
- random_day = random.choice(day)
- cs.day = random_day
- cs.from_time = timedelta(hours=(random.randrange(7, 17,1)))
- cs.to_time = cs.from_time + timedelta(hours=1)
- cs.schedule_course()
- day.remove(random_day)
-
-
-def weighted_choice(weights):
- totals = []
- running_total = 0
-
- for w in weights:
- running_total += w
- totals.append(running_total)
-
- rnd = random.random() * running_total
- for i, total in enumerate(totals):
- if rnd < total:
- return i
diff --git a/erpnext/demo/user/fixed_asset.py b/erpnext/demo/user/fixed_asset.py
deleted file mode 100644
index 72cd420..0000000
--- a/erpnext/demo/user/fixed_asset.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-
-import frappe
-from frappe.utils.make_random import get_random
-
-from erpnext.assets.doctype.asset.asset import make_sales_invoice
-from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset
-
-
-def work():
- frappe.set_user(frappe.db.get_global('demo_accounts_user'))
-
- # Enable booking asset depreciation entry automatically
- frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1)
-
- # post depreciation entries as on today
- post_depreciation_entries()
-
- # scrap a random asset
- frappe.db.set_value("Company", "Wind Power LLC", "disposal_account", "Gain/Loss on Asset Disposal - WPL")
-
- asset = get_random_asset()
- scrap_asset(asset.name)
-
- # Sell a random asset
- sell_an_asset()
-
-
-def sell_an_asset():
- asset = get_random_asset()
- si = make_sales_invoice(asset.name, asset.item_code, "Wind Power LLC")
- si.customer = get_random("Customer")
- si.get("items")[0].rate = asset.value_after_depreciation * 0.8 \
- if asset.value_after_depreciation else asset.gross_purchase_amount * 0.9
- si.save()
- si.submit()
-
-
-def get_random_asset():
- return frappe.db.sql(""" select name, item_code, value_after_depreciation, gross_purchase_amount
- from `tabAsset`
- where docstatus=1 and status not in ("Scrapped", "Sold") order by rand() limit 1""", as_dict=1)[0]
diff --git a/erpnext/demo/user/hr.py b/erpnext/demo/user/hr.py
deleted file mode 100644
index f84a853..0000000
--- a/erpnext/demo/user/hr.py
+++ /dev/null
@@ -1,223 +0,0 @@
-import datetime
-import random
-
-import frappe
-from frappe.utils import add_days, get_last_day, getdate, random_string
-from frappe.utils.make_random import get_random
-
-import erpnext
-from erpnext.hr.doctype.expense_claim.expense_claim import make_bank_entry
-from erpnext.hr.doctype.expense_claim.test_expense_claim import get_payable_account
-from erpnext.hr.doctype.leave_application.leave_application import (
- AttendanceAlreadyMarkedError,
- OverlapError,
- get_leave_balance_on,
-)
-from erpnext.projects.doctype.timesheet.test_timesheet import make_timesheet
-from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_sales_invoice
-
-
-def work():
- frappe.set_user(frappe.db.get_global('demo_hr_user'))
- year, month = frappe.flags.current_date.strftime("%Y-%m").split("-")
- setup_department_approvers()
- mark_attendance()
- make_leave_application()
-
- # payroll entry
- if not frappe.db.sql('select name from `tabSalary Slip` where month(adddate(start_date, interval 1 month))=month(curdate())'):
- # based on frequency
- payroll_entry = get_payroll_entry()
- payroll_entry.salary_slip_based_on_timesheet = 0
- payroll_entry.save()
- payroll_entry.create_salary_slips()
- payroll_entry.submit_salary_slips()
- payroll_entry.make_accrual_jv_entry()
- payroll_entry.submit()
- # payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date,
- # reference_number=random_string(10))
-
- # based on timesheet
- payroll_entry = get_payroll_entry()
- payroll_entry.salary_slip_based_on_timesheet = 1
- payroll_entry.save()
- payroll_entry.create_salary_slips()
- payroll_entry.submit_salary_slips()
- payroll_entry.make_accrual_jv_entry()
- payroll_entry.submit()
- # payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date,
- # reference_number=random_string(10))
-
- if frappe.db.get_global('demo_hr_user'):
- make_timesheet_records()
-
- #expense claim
- expense_claim = frappe.new_doc("Expense Claim")
- expense_claim.extend('expenses', get_expenses())
- expense_claim.employee = get_random("Employee")
- expense_claim.company = frappe.flags.company
- expense_claim.payable_account = get_payable_account(expense_claim.company)
- expense_claim.posting_date = frappe.flags.current_date
- expense_claim.expense_approver = frappe.db.get_global('demo_hr_user')
- expense_claim.save()
-
- rand = random.random()
-
- if rand < 0.4:
- update_sanctioned_amount(expense_claim)
- expense_claim.approval_status = 'Approved'
- expense_claim.submit()
-
- if random.randint(0, 1):
- #make journal entry against expense claim
- je = frappe.get_doc(make_bank_entry("Expense Claim", expense_claim.name))
- je.posting_date = frappe.flags.current_date
- je.cheque_no = random_string(10)
- je.cheque_date = frappe.flags.current_date
- je.flags.ignore_permissions = 1
- je.submit()
-
-def get_payroll_entry():
- # process payroll for previous month
- payroll_entry = frappe.new_doc("Payroll Entry")
- payroll_entry.company = frappe.flags.company
- payroll_entry.payroll_frequency = 'Monthly'
-
- # select a posting date from the previous month
- payroll_entry.posting_date = get_last_day(getdate(frappe.flags.current_date) - datetime.timedelta(days=10))
- payroll_entry.payment_account = frappe.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
-
- payroll_entry.set_start_end_dates()
- return payroll_entry
-
-def get_expenses():
- expenses = []
- expese_types = frappe.db.sql("""select ect.name, eca.default_account from `tabExpense Claim Type` ect,
- `tabExpense Claim Account` eca where eca.parent=ect.name
- and eca.company=%s """, frappe.flags.company,as_dict=1)
-
- for expense_type in expese_types[:random.randint(1,4)]:
- claim_amount = random.randint(1,20)*10
-
- expenses.append({
- "expense_date": frappe.flags.current_date,
- "expense_type": expense_type.name,
- "default_account": expense_type.default_account or "Miscellaneous Expenses - WPL",
- "amount": claim_amount,
- "sanctioned_amount": claim_amount
- })
-
- return expenses
-
-def update_sanctioned_amount(expense_claim):
- for expense in expense_claim.expenses:
- sanctioned_amount = random.randint(1,20)*10
-
- if sanctioned_amount < expense.amount:
- expense.sanctioned_amount = sanctioned_amount
-
-def get_timesheet_based_salary_slip_employee():
- sal_struct = frappe.db.sql("""
- select name from `tabSalary Structure`
- where salary_slip_based_on_timesheet = 1
- and docstatus != 2""")
- if sal_struct:
- employees = frappe.db.sql("""
- select employee from `tabSalary Structure Assignment`
- where salary_structure IN %(sal_struct)s""", {"sal_struct": sal_struct}, as_dict=True)
- return employees
- else:
- return []
-
-def make_timesheet_records():
- employees = get_timesheet_based_salary_slip_employee()
- for e in employees:
- ts = make_timesheet(e.employee, simulate = True, billable = 1, activity_type=get_random("Activity Type"), company=frappe.flags.company)
- frappe.db.commit()
-
- rand = random.random()
- if rand >= 0.3:
- make_salary_slip_for_timesheet(ts.name)
-
- rand = random.random()
- if rand >= 0.2:
- make_sales_invoice_for_timesheet(ts.name)
-
-def make_salary_slip_for_timesheet(name):
- salary_slip = make_salary_slip(name)
- salary_slip.insert()
- salary_slip.submit()
- frappe.db.commit()
-
-def make_sales_invoice_for_timesheet(name):
- sales_invoice = make_sales_invoice(name)
- sales_invoice.customer = get_random("Customer")
- sales_invoice.append('items', {
- 'item_code': get_random("Item", {"has_variants": 0, "is_stock_item": 0,
- "is_fixed_asset": 0}),
- 'qty': 1,
- 'rate': 1000
- })
- sales_invoice.flags.ignore_permissions = 1
- sales_invoice.set_missing_values()
- sales_invoice.calculate_taxes_and_totals()
- sales_invoice.insert()
- sales_invoice.submit()
- frappe.db.commit()
-
-def make_leave_application():
- allocated_leaves = frappe.get_all("Leave Allocation", fields=['employee', 'leave_type'])
-
- for allocated_leave in allocated_leaves:
- leave_balance = get_leave_balance_on(allocated_leave.employee, allocated_leave.leave_type, frappe.flags.current_date,
- consider_all_leaves_in_the_allocation_period=True)
- if leave_balance != 0:
- if leave_balance == 1:
- to_date = frappe.flags.current_date
- else:
- to_date = add_days(frappe.flags.current_date, random.randint(0, leave_balance-1))
-
- leave_application = frappe.get_doc({
- "doctype": "Leave Application",
- "employee": allocated_leave.employee,
- "from_date": frappe.flags.current_date,
- "to_date": to_date,
- "leave_type": allocated_leave.leave_type,
- })
- try:
- leave_application.insert()
- leave_application.submit()
- frappe.db.commit()
- except (OverlapError, AttendanceAlreadyMarkedError):
- frappe.db.rollback()
-
-def mark_attendance():
- attendance_date = frappe.flags.current_date
- for employee in frappe.get_all('Employee', fields=['name'], filters = {'status': 'Active'}):
-
- if not frappe.db.get_value("Attendance", {"employee": employee.name, "attendance_date": attendance_date}):
- attendance = frappe.get_doc({
- "doctype": "Attendance",
- "employee": employee.name,
- "attendance_date": attendance_date
- })
-
- leave = frappe.db.sql("""select name from `tabLeave Application`
- where employee = %s and %s between from_date and to_date
- and docstatus = 1""", (employee.name, attendance_date))
-
- if leave:
- attendance.status = "Absent"
- else:
- attendance.status = "Present"
- attendance.save()
- attendance.submit()
- frappe.db.commit()
-
-def setup_department_approvers():
- for d in frappe.get_all('Department', filters={'department_name': ['!=', 'All Departments']}):
- doc = frappe.get_doc('Department', d.name)
- doc.append("leave_approvers", {'approver': frappe.session.user})
- doc.append("expense_approvers", {'approver': frappe.session.user})
- doc.flags.ignore_mandatory = True
- doc.save()
diff --git a/erpnext/demo/user/manufacturing.py b/erpnext/demo/user/manufacturing.py
deleted file mode 100644
index 6b61776..0000000
--- a/erpnext/demo/user/manufacturing.py
+++ /dev/null
@@ -1,123 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-
-import random
-from datetime import timedelta
-
-import frappe
-from frappe.desk import query_report
-from frappe.utils.make_random import how_many
-
-import erpnext
-from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record
-
-
-def work():
- if random.random() < 0.3: return
-
- frappe.set_user(frappe.db.get_global('demo_manufacturing_user'))
- if not frappe.get_all('Sales Order'): return
-
- ppt = frappe.new_doc("Production Plan")
- ppt.company = erpnext.get_default_company()
- # ppt.use_multi_level_bom = 1 #refactored
- ppt.get_items_from = "Sales Order"
- # ppt.purchase_request_for_warehouse = "Stores - WPL" # refactored
- ppt.run_method("get_open_sales_orders")
- if not ppt.get("sales_orders"): return
- ppt.run_method("get_items")
- ppt.run_method("raise_material_requests")
- ppt.save()
- ppt.submit()
- ppt.run_method("raise_work_orders")
- frappe.db.commit()
-
- # submit work orders
- for pro in frappe.db.get_values("Work Order", {"docstatus": 0}, "name"):
- b = frappe.get_doc("Work Order", pro[0])
- b.wip_warehouse = "Work in Progress - WPL"
- b.submit()
- frappe.db.commit()
-
- # submit material requests
- for pro in frappe.db.get_values("Material Request", {"docstatus": 0}, "name"):
- b = frappe.get_doc("Material Request", pro[0])
- b.submit()
- frappe.db.commit()
-
- # stores -> wip
- if random.random() < 0.4:
- for pro in query_report.run("Open Work Orders")["result"][:how_many("Stock Entry for WIP")]:
- make_stock_entry_from_pro(pro[0], "Material Transfer for Manufacture")
-
- # wip -> fg
- if random.random() < 0.4:
- for pro in query_report.run("Work Orders in Progress")["result"][:how_many("Stock Entry for FG")]:
- make_stock_entry_from_pro(pro[0], "Manufacture")
-
- for bom in frappe.get_all('BOM', fields=['item'], filters = {'with_operations': 1}):
- pro_order = make_wo_order_test_record(item=bom.item, qty=2,
- source_warehouse="Stores - WPL", wip_warehouse = "Work in Progress - WPL",
- fg_warehouse = "Stores - WPL", company = erpnext.get_default_company(),
- stock_uom = frappe.db.get_value('Item', bom.item, 'stock_uom'),
- planned_start_date = frappe.flags.current_date)
-
- # submit job card
- if random.random() < 0.4:
- submit_job_cards()
-
-def make_stock_entry_from_pro(pro_id, purpose):
- from erpnext.manufacturing.doctype.work_order.work_order import make_stock_entry
- from erpnext.stock.doctype.stock_entry.stock_entry import (
- DuplicateEntryForWorkOrderError,
- IncorrectValuationRateError,
- OperationsNotCompleteError,
- )
- from erpnext.stock.stock_ledger import NegativeStockError
-
- try:
- st = frappe.get_doc(make_stock_entry(pro_id, purpose))
- st.posting_date = frappe.flags.current_date
- st.fiscal_year = str(frappe.flags.current_date.year)
- for d in st.get("items"):
- d.cost_center = "Main - " + frappe.get_cached_value('Company', st.company, 'abbr')
- st.insert()
- frappe.db.commit()
- st.submit()
- frappe.db.commit()
- except (NegativeStockError, IncorrectValuationRateError, DuplicateEntryForWorkOrderError,
- OperationsNotCompleteError):
- frappe.db.rollback()
-
-def submit_job_cards():
- work_orders = frappe.get_all("Work Order", ["name", "creation"], {"docstatus": 1, "status": "Not Started"})
- work_order = random.choice(work_orders)
- # for work_order in work_orders:
- start_date = work_order.creation
- work_order = frappe.get_doc("Work Order", work_order.name)
- job = frappe.get_all("Job Card", ["name", "operation", "work_order"],
- {"docstatus": 0, "work_order": work_order.name})
-
- if not job: return
- job_map = {}
- for d in job:
- job_map[d.operation] = frappe.get_doc("Job Card", d.name)
-
- for operation in work_order.operations:
- job = job_map[operation.operation]
- job_time_log = frappe.new_doc("Job Card Time Log")
- job_time_log.from_time = start_date
- minutes = operation.get("time_in_mins")
- job_time_log.time_in_mins = random.randint(int(minutes/2), minutes)
- job_time_log.to_time = job_time_log.from_time + \
- timedelta(minutes=job_time_log.time_in_mins)
- job_time_log.parent = job.name
- job_time_log.parenttype = 'Job Card'
- job_time_log.parentfield = 'time_logs'
- job_time_log.completed_qty = work_order.qty
- job_time_log.save(ignore_permissions=True)
- job.time_logs.append(job_time_log)
- job.save(ignore_permissions=True)
- job.submit()
- start_date = job_time_log.to_time
diff --git a/erpnext/demo/user/projects.py b/erpnext/demo/user/projects.py
deleted file mode 100644
index 1203be4..0000000
--- a/erpnext/demo/user/projects.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-
-import frappe
-from frappe.utils import flt
-from frappe.utils.make_random import get_random
-
-import erpnext
-from erpnext.demo.user.hr import make_sales_invoice_for_timesheet
-from erpnext.projects.doctype.timesheet.test_timesheet import make_timesheet
-
-
-def run_projects(current_date):
- frappe.set_user(frappe.db.get_global('demo_projects_user'))
- if frappe.db.get_global('demo_projects_user'):
- make_project(current_date)
- make_timesheet_for_projects(current_date)
- close_tasks(current_date)
-
-def make_timesheet_for_projects(current_date ):
- for data in frappe.get_all("Task", ["name", "project"], {"status": "Open", "exp_end_date": ("<", current_date)}):
- employee = get_random("Employee")
- ts = make_timesheet(employee, simulate = True, billable = 1, company = erpnext.get_default_company(),
- activity_type=get_random("Activity Type"), project=data.project, task =data.name)
-
- if flt(ts.total_billable_amount) > 0.0:
- make_sales_invoice_for_timesheet(ts.name)
- frappe.db.commit()
-
-def close_tasks(current_date):
- for task in frappe.get_all("Task", ["name"], {"status": "Open", "exp_end_date": ("<", current_date)}):
- task = frappe.get_doc("Task", task.name)
- task.status = "Completed"
- task.save()
-
-def make_project(current_date):
- if not frappe.db.exists('Project',
- "New Product Development " + current_date.strftime("%Y-%m-%d")):
- project = frappe.get_doc({
- "doctype": "Project",
- "project_name": "New Product Development " + current_date.strftime("%Y-%m-%d"),
- })
- project.insert()
diff --git a/erpnext/demo/user/purchase.py b/erpnext/demo/user/purchase.py
deleted file mode 100644
index 61f081c..0000000
--- a/erpnext/demo/user/purchase.py
+++ /dev/null
@@ -1,180 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-
-import json
-import random
-
-import frappe
-from frappe.desk import query_report
-from frappe.utils.make_random import get_random, how_many
-
-import erpnext
-from erpnext.accounts.party import get_party_account_currency
-from erpnext.buying.doctype.request_for_quotation.request_for_quotation import (
- make_supplier_quotation_from_rfq,
-)
-from erpnext.exceptions import InvalidCurrency
-from erpnext.setup.utils import get_exchange_rate
-from erpnext.stock.doctype.material_request.material_request import make_request_for_quotation
-
-
-def work():
- frappe.set_user(frappe.db.get_global('demo_purchase_user'))
-
- if random.random() < 0.6:
- report = "Items To Be Requested"
- for row in query_report.run(report)["result"][:random.randint(1, 5)]:
- item_code, qty = row[0], abs(row[-1])
-
- mr = make_material_request(item_code, qty)
-
- if random.random() < 0.6:
- for mr in frappe.get_all('Material Request',
- filters={'material_request_type': 'Purchase', 'status': 'Open'},
- limit=random.randint(1,6)):
- if not frappe.get_all('Request for Quotation',
- filters={'material_request': mr.name}, limit=1):
- rfq = make_request_for_quotation(mr.name)
- rfq.transaction_date = frappe.flags.current_date
- add_suppliers(rfq)
- rfq.save()
- rfq.submit()
-
- # Make suppier quotation from RFQ against each supplier.
- if random.random() < 0.6:
- for rfq in frappe.get_all('Request for Quotation',
- filters={'status': 'Open'}, limit=random.randint(1, 6)):
- if not frappe.get_all('Supplier Quotation',
- filters={'request_for_quotation': rfq.name}, limit=1):
- rfq = frappe.get_doc('Request for Quotation', rfq.name)
-
- for supplier in rfq.suppliers:
- supplier_quotation = make_supplier_quotation_from_rfq(rfq.name, for_supplier=supplier.supplier)
- supplier_quotation.save()
- supplier_quotation.submit()
-
- # get supplier details
- supplier = get_random("Supplier")
-
- company_currency = frappe.get_cached_value('Company', erpnext.get_default_company(), "default_currency")
- party_account_currency = get_party_account_currency("Supplier", supplier, erpnext.get_default_company())
- if company_currency == party_account_currency:
- exchange_rate = 1
- else:
- exchange_rate = get_exchange_rate(party_account_currency, company_currency, args="for_buying")
-
- # make supplier quotations
- if random.random() < 0.5:
- from erpnext.stock.doctype.material_request.material_request import make_supplier_quotation
-
- report = "Material Requests for which Supplier Quotations are not created"
- for row in query_report.run(report)["result"][:random.randint(1, 3)]:
- if row[0] != "Total":
- sq = frappe.get_doc(make_supplier_quotation(row[0]))
- sq.transaction_date = frappe.flags.current_date
- sq.supplier = supplier
- sq.currency = party_account_currency or company_currency
- sq.conversion_rate = exchange_rate
- sq.insert()
- sq.submit()
- frappe.db.commit()
-
- # make purchase orders
- if random.random() < 0.5:
- from erpnext.stock.doctype.material_request.material_request import make_purchase_order
- report = "Requested Items To Be Ordered"
- for row in query_report.run(report)["result"][:how_many("Purchase Order")]:
- if row[0] != "Total":
- try:
- po = frappe.get_doc(make_purchase_order(row[0]))
- po.supplier = supplier
- po.currency = party_account_currency or company_currency
- po.conversion_rate = exchange_rate
- po.transaction_date = frappe.flags.current_date
- po.insert()
- po.submit()
- except Exception:
- pass
- else:
- frappe.db.commit()
-
- if random.random() < 0.5:
- make_subcontract()
-
-def make_material_request(item_code, qty):
- mr = frappe.new_doc("Material Request")
-
- variant_of = frappe.db.get_value('Item', item_code, 'variant_of') or item_code
-
- if frappe.db.get_value('BOM', {'item': variant_of, 'is_default': 1, 'is_active': 1}):
- mr.material_request_type = 'Manufacture'
- else:
- mr.material_request_type = "Purchase"
-
- mr.transaction_date = frappe.flags.current_date
- mr.schedule_date = frappe.utils.add_days(mr.transaction_date, 7)
-
- mr.append("items", {
- "doctype": "Material Request Item",
- "schedule_date": frappe.utils.add_days(mr.transaction_date, 7),
- "item_code": item_code,
- "qty": qty
- })
- mr.insert()
- mr.submit()
- return mr
-
-def add_suppliers(rfq):
- for i in range(2):
- supplier = get_random("Supplier")
- if supplier not in [d.supplier for d in rfq.get('suppliers')]:
- rfq.append("suppliers", { "supplier": supplier })
-
-def make_subcontract():
- from erpnext.buying.doctype.purchase_order.purchase_order import make_rm_stock_entry
- item_code = get_random("Item", {"is_sub_contracted_item": 1})
- if item_code:
- # make sub-contract PO
- po = frappe.new_doc("Purchase Order")
- po.is_subcontracted = "Yes"
- po.supplier = get_random("Supplier")
- po.transaction_date = frappe.flags.current_date # added
- po.schedule_date = frappe.utils.add_days(frappe.flags.current_date, 7)
-
- item_code = get_random("Item", {"is_sub_contracted_item": 1})
-
- po.append("items", {
- "item_code": item_code,
- "schedule_date": frappe.utils.add_days(frappe.flags.current_date, 7),
- "qty": random.randint(10, 30)
- })
- po.set_missing_values()
- try:
- po.insert()
- except InvalidCurrency:
- return
-
- po.submit()
-
- # make material request for
- make_material_request(po.items[0].item_code, po.items[0].qty)
-
- # transfer material for sub-contract
- rm_items = get_rm_item(po.items[0], po.supplied_items[0])
- stock_entry = frappe.get_doc(make_rm_stock_entry(po.name, json.dumps([rm_items])))
- stock_entry.from_warehouse = "Stores - WPL"
- stock_entry.to_warehouse = "Supplier - WPL"
- stock_entry.insert()
-
-def get_rm_item(items, supplied_items):
- return {
- "item_code": items.get("item_code"),
- "rm_item_code": supplied_items.get("rm_item_code"),
- "item_name": supplied_items.get("rm_item_code"),
- "qty": supplied_items.get("required_qty") + random.randint(3,10),
- "amount": supplied_items.get("amount"),
- "warehouse": supplied_items.get("reserve_warehouse"),
- "rate": supplied_items.get("rate"),
- "stock_uom": supplied_items.get("stock_uom")
- }
diff --git a/erpnext/demo/user/sales.py b/erpnext/demo/user/sales.py
deleted file mode 100644
index ef6e4c4..0000000
--- a/erpnext/demo/user/sales.py
+++ /dev/null
@@ -1,145 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-
-import random
-
-import frappe
-from frappe.utils import flt
-from frappe.utils.make_random import add_random_children, get_random
-
-import erpnext
-from erpnext.accounts.doctype.payment_request.payment_request import (
- make_payment_entry,
- make_payment_request,
-)
-from erpnext.accounts.party import get_party_account_currency
-from erpnext.setup.utils import get_exchange_rate
-
-
-def work(domain="Manufacturing"):
- frappe.set_user(frappe.db.get_global('demo_sales_user_2'))
-
- for i in range(random.randint(1,7)):
- if random.random() < 0.5:
- make_opportunity(domain)
-
- for i in range(random.randint(1,3)):
- if random.random() < 0.5:
- make_quotation(domain)
-
- try:
- lost_reason = frappe.get_doc({
- "doctype": "Opportunity Lost Reason",
- "lost_reason": "Did not ask"
- })
- lost_reason.save(ignore_permissions=True)
- except frappe.exceptions.DuplicateEntryError:
- pass
-
- # lost quotations / inquiries
- if random.random() < 0.3:
- for i in range(random.randint(1,3)):
- quotation = get_random('Quotation', doc=True)
- if quotation and quotation.status == 'Submitted':
- quotation.declare_order_lost([{'lost_reason': 'Did not ask'}])
-
- for i in range(random.randint(1,3)):
- opportunity = get_random('Opportunity', doc=True)
- if opportunity and opportunity.status in ('Open', 'Replied'):
- opportunity.declare_enquiry_lost([{'lost_reason': 'Did not ask'}])
-
- for i in range(random.randint(1,3)):
- if random.random() < 0.6:
- make_sales_order()
-
- if random.random() < 0.5:
- #make payment request against Sales Order
- sales_order_name = get_random("Sales Order", filters={"docstatus": 1})
- try:
- if sales_order_name:
- so = frappe.get_doc("Sales Order", sales_order_name)
- if flt(so.per_billed) != 100:
- payment_request = make_payment_request(dt="Sales Order", dn=so.name, recipient_id=so.contact_email,
- submit_doc=True, mute_email=True, use_dummy_message=True)
-
- payment_entry = frappe.get_doc(make_payment_entry(payment_request.name))
- payment_entry.posting_date = frappe.flags.current_date
- payment_entry.submit()
- except Exception:
- pass
-
-def make_opportunity(domain):
- b = frappe.get_doc({
- "doctype": "Opportunity",
- "opportunity_from": "Customer",
- "party_name": frappe.get_value("Customer", get_random("Customer"), 'name'),
- "opportunity_type": "Sales",
- "with_items": 1,
- "transaction_date": frappe.flags.current_date,
- })
-
- add_random_children(b, "items", rows=4, randomize = {
- "qty": (1, 5),
- "item_code": ("Item", {"has_variants": 0, "is_fixed_asset": 0, "domain": domain})
- }, unique="item_code")
-
- b.insert()
- frappe.db.commit()
-
-def make_quotation(domain):
- # get open opportunites
- opportunity = get_random("Opportunity", {"status": "Open", "with_items": 1})
-
- if opportunity:
- from erpnext.crm.doctype.opportunity.opportunity import make_quotation
- qtn = frappe.get_doc(make_quotation(opportunity))
- qtn.insert()
- frappe.db.commit()
- qtn.submit()
- frappe.db.commit()
- else:
- # make new directly
-
- # get customer, currency and exchange_rate
- customer = get_random("Customer")
-
- company_currency = frappe.get_cached_value('Company', erpnext.get_default_company(), "default_currency")
- party_account_currency = get_party_account_currency("Customer", customer, erpnext.get_default_company())
- if company_currency == party_account_currency:
- exchange_rate = 1
- else:
- exchange_rate = get_exchange_rate(party_account_currency, company_currency, args="for_selling")
-
- qtn = frappe.get_doc({
- "creation": frappe.flags.current_date,
- "doctype": "Quotation",
- "quotation_to": "Customer",
- "party_name": customer,
- "currency": party_account_currency or company_currency,
- "conversion_rate": exchange_rate,
- "order_type": "Sales",
- "transaction_date": frappe.flags.current_date,
- })
-
- add_random_children(qtn, "items", rows=3, randomize = {
- "qty": (1, 5),
- "item_code": ("Item", {"has_variants": "0", "is_fixed_asset": 0, "domain": domain})
- }, unique="item_code")
-
- qtn.insert()
- frappe.db.commit()
- qtn.submit()
- frappe.db.commit()
-
-def make_sales_order():
- q = get_random("Quotation", {"status": "Submitted"})
- if q:
- from erpnext.selling.doctype.quotation.quotation import make_sales_order as mso
- so = frappe.get_doc(mso(q))
- so.transaction_date = frappe.flags.current_date
- so.delivery_date = frappe.utils.add_days(frappe.flags.current_date, 10)
- so.insert()
- frappe.db.commit()
- so.submit()
- frappe.db.commit()
diff --git a/erpnext/demo/user/stock.py b/erpnext/demo/user/stock.py
deleted file mode 100644
index de37975..0000000
--- a/erpnext/demo/user/stock.py
+++ /dev/null
@@ -1,138 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-
-import random
-
-import frappe
-from frappe.desk import query_report
-
-import erpnext
-from erpnext.stock.doctype.batch.batch import UnableToSelectBatchError
-from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_return
-from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_return
-from erpnext.stock.doctype.serial_no.serial_no import SerialNoQtyError, SerialNoRequiredError
-from erpnext.stock.stock_ledger import NegativeStockError
-
-
-def work():
- frappe.set_user(frappe.db.get_global('demo_manufacturing_user'))
-
- make_purchase_receipt()
- make_delivery_note()
- make_stock_reconciliation()
- submit_draft_stock_entries()
- make_sales_return_records()
- make_purchase_return_records()
-
-def make_purchase_receipt():
- if random.random() < 0.6:
- from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
- report = "Purchase Order Items To Be Received"
- po_list =list(set([r[0] for r in query_report.run(report)["result"] if r[0]!="Total"]))[:random.randint(1, 10)]
- for po in po_list:
- pr = frappe.get_doc(make_purchase_receipt(po))
-
- if pr.is_subcontracted=="Yes":
- pr.supplier_warehouse = "Supplier - WPL"
-
- pr.posting_date = frappe.flags.current_date
- pr.insert()
- try:
- pr.submit()
- except NegativeStockError:
- print('Negative stock for {0}'.format(po))
- pass
- frappe.db.commit()
-
-def make_delivery_note():
- # make purchase requests
-
- # make delivery notes (if possible)
- if random.random() < 0.6:
- from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
- report = "Ordered Items To Be Delivered"
- for so in list(set([r[0] for r in query_report.run(report)["result"]
- if r[0]!="Total"]))[:random.randint(1, 3)]:
- dn = frappe.get_doc(make_delivery_note(so))
- dn.posting_date = frappe.flags.current_date
- for d in dn.get("items"):
- if not d.expense_account:
- d.expense_account = ("Cost of Goods Sold - {0}".format(
- frappe.get_cached_value('Company', dn.company, 'abbr')))
-
- try:
- dn.insert()
- dn.submit()
- frappe.db.commit()
- except (NegativeStockError, SerialNoRequiredError, SerialNoQtyError, UnableToSelectBatchError):
- frappe.db.rollback()
-
-def make_stock_reconciliation():
- # random set some items as damaged
- from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import (
- EmptyStockReconciliationItemsError,
- OpeningEntryAccountError,
- )
-
- if random.random() < 0.4:
- stock_reco = frappe.new_doc("Stock Reconciliation")
- stock_reco.posting_date = frappe.flags.current_date
- stock_reco.company = erpnext.get_default_company()
- stock_reco.get_items_for("Stores - WPL")
- if stock_reco.items:
- for item in stock_reco.items:
- if item.qty:
- item.qty = item.qty - round(random.randint(1, item.qty))
- try:
- stock_reco.insert(ignore_permissions=True, ignore_mandatory=True)
- stock_reco.submit()
- frappe.db.commit()
- except OpeningEntryAccountError:
- frappe.db.rollback()
- except EmptyStockReconciliationItemsError:
- frappe.db.rollback()
-
-def submit_draft_stock_entries():
- from erpnext.stock.doctype.stock_entry.stock_entry import (
- DuplicateEntryForWorkOrderError,
- IncorrectValuationRateError,
- OperationsNotCompleteError,
- )
-
- # try posting older drafts (if exists)
- frappe.db.commit()
- for st in frappe.db.get_values("Stock Entry", {"docstatus":0}, "name"):
- try:
- ste = frappe.get_doc("Stock Entry", st[0])
- ste.posting_date = frappe.flags.current_date
- ste.save()
- ste.submit()
- frappe.db.commit()
- except (NegativeStockError, IncorrectValuationRateError, DuplicateEntryForWorkOrderError,
- OperationsNotCompleteError):
- frappe.db.rollback()
-
-def make_sales_return_records():
- if random.random() < 0.1:
- for data in frappe.get_all('Delivery Note', fields=["name"], filters={"docstatus": 1}):
- if random.random() < 0.1:
- try:
- dn = make_sales_return(data.name)
- dn.insert()
- dn.submit()
- frappe.db.commit()
- except Exception:
- frappe.db.rollback()
-
-def make_purchase_return_records():
- if random.random() < 0.1:
- for data in frappe.get_all('Purchase Receipt', fields=["name"], filters={"docstatus": 1}):
- if random.random() < 0.1:
- try:
- pr = make_purchase_return(data.name)
- pr.insert()
- pr.submit()
- frappe.db.commit()
- except Exception:
- frappe.db.rollback()
diff --git a/erpnext/domains/hospitality.py b/erpnext/domains/hospitality.py
deleted file mode 100644
index 09b98c2..0000000
--- a/erpnext/domains/hospitality.py
+++ /dev/null
@@ -1,35 +0,0 @@
-data = {
- 'desktop_icons': [
- 'Restaurant',
- 'Hotels',
- 'Accounts',
- 'Buying',
- 'Stock',
- 'HR',
- 'Project',
- 'ToDo'
- ],
- 'restricted_roles': [
- 'Restaurant Manager',
- 'Hotel Manager',
- 'Hotel Reservation User'
- ],
- 'custom_fields': {
- 'Sales Invoice': [
- {
- 'fieldname': 'restaurant', 'fieldtype': 'Link', 'options': 'Restaurant',
- 'insert_after': 'customer_name', 'label': 'Restaurant',
- },
- {
- 'fieldname': 'restaurant_table', 'fieldtype': 'Link', 'options': 'Restaurant Table',
- 'insert_after': 'restaurant', 'label': 'Restaurant Table',
- }
- ],
- 'Price List': [
- {
- 'fieldname':'restaurant_menu', 'fieldtype':'Link', 'options':'Restaurant Menu', 'label':'Restaurant Menu',
- 'insert_after':'currency'
- }
- ]
- }
-}
diff --git a/erpnext/education/api.py b/erpnext/education/api.py
index d9013b0..636b948 100644
--- a/erpnext/education/api.py
+++ b/erpnext/education/api.py
@@ -201,8 +201,8 @@
conditions = get_event_conditions("Course Schedule", filters)
data = frappe.db.sql("""select name, course, color,
- timestamp(schedule_date, from_time) as from_datetime,
- timestamp(schedule_date, to_time) as to_datetime,
+ timestamp(schedule_date, from_time) as from_time,
+ timestamp(schedule_date, to_time) as to_time,
room, student_group, 0 as 'allDay'
from `tabCourse Schedule`
where ( schedule_date between %(start)s and %(end)s )
diff --git a/erpnext/education/doctype/course_schedule/course_schedule.py b/erpnext/education/doctype/course_schedule/course_schedule.py
index ffd323d..615d2c4 100644
--- a/erpnext/education/doctype/course_schedule/course_schedule.py
+++ b/erpnext/education/doctype/course_schedule/course_schedule.py
@@ -3,6 +3,8 @@
# For license information, please see license.txt
+from datetime import datetime
+
import frappe
from frappe import _
from frappe.model.document import Document
@@ -30,6 +32,14 @@
if self.from_time > self.to_time:
frappe.throw(_("From Time cannot be greater than To Time."))
+ """Handles specicfic case to update schedule date in calendar """
+ if isinstance(self.from_time, str):
+ try:
+ datetime_obj = datetime.strptime(self.from_time, '%Y-%m-%d %H:%M:%S')
+ self.schedule_date = datetime_obj
+ except ValueError:
+ pass
+
def validate_overlap(self):
"""Validates overlap for Student Group, Instructor, Room"""
@@ -47,4 +57,4 @@
validate_overlap_for(self, "Assessment Plan", "student_group")
validate_overlap_for(self, "Assessment Plan", "room")
- validate_overlap_for(self, "Assessment Plan", "supervisor", self.instructor)
+ validate_overlap_for(self, "Assessment Plan", "supervisor", self.instructor)
\ No newline at end of file
diff --git a/erpnext/education/doctype/course_schedule/course_schedule_calendar.js b/erpnext/education/doctype/course_schedule/course_schedule_calendar.js
index 803527e..cacd539 100644
--- a/erpnext/education/doctype/course_schedule/course_schedule_calendar.js
+++ b/erpnext/education/doctype/course_schedule/course_schedule_calendar.js
@@ -1,11 +1,10 @@
frappe.views.calendar["Course Schedule"] = {
field_map: {
- // from_datetime and to_datetime don't exist as docfields but are used in onload
- "start": "from_datetime",
- "end": "to_datetime",
+ "start": "from_time",
+ "end": "to_time",
"id": "name",
"title": "course",
- "allDay": "allDay"
+ "allDay": "allDay",
},
gantt: false,
order_by: "schedule_date",
diff --git a/erpnext/education/doctype/course_schedule/test_course_schedule.py b/erpnext/education/doctype/course_schedule/test_course_schedule.py
index a732419..56149af 100644
--- a/erpnext/education/doctype/course_schedule/test_course_schedule.py
+++ b/erpnext/education/doctype/course_schedule/test_course_schedule.py
@@ -6,6 +6,7 @@
import frappe
from frappe.utils import to_timedelta, today
+from frappe.utils.data import add_to_date
from erpnext.education.utils import OverlapError
@@ -39,6 +40,11 @@
make_course_schedule_test_record(from_time= cs1.from_time, to_time= cs1.to_time,
student_group="Course-TC102-2014-2015 (_Test Academic Term)", instructor="_Test Instructor 2", room=frappe.get_all("Room")[1].name)
+ def test_update_schedule_date(self):
+ doc = make_course_schedule_test_record(schedule_date= add_to_date(today(), days=1))
+ doc.schedule_date = add_to_date(doc.schedule_date, days=1)
+ doc.save()
+
def make_course_schedule_test_record(**args):
args = frappe._dict(args)
diff --git a/erpnext/education/workspace/education/education.json b/erpnext/education/workspace/education/education.json
index 1465295..0c7f198 100644
--- a/erpnext/education/workspace/education/education.json
+++ b/erpnext/education/workspace/education/education.json
@@ -5,7 +5,7 @@
"label": "Program Enrollments"
}
],
- "content": "[{\"type\": \"onboarding\", \"data\": {\"onboarding_name\":\"Education\", \"col\": 12}}, {\"type\": \"chart\", \"data\": {\"chart_name\": \"Program Enrollments\", \"col\": 12}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Student\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Instructor\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Program\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Course\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Fees\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Student Monthly Attendance Sheet\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Course Scheduling Tool\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Student Attendance Tool\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Dashboard\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Student and Instructor\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Masters\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Content Masters\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Settings\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Admission\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Fees\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Schedule\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Attendance\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"LMS Activity\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Assessment\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Assessment Reports\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Tools\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Other Reports\", \"col\": 4}}]",
+ "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Education\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Program Enrollments\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Student\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Instructor\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Program\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Course\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Fees\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Student Monthly Attendance Sheet\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Course Scheduling Tool\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Student Attendance Tool\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Student and Instructor\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Masters\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Content Masters\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Admission\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Fees\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Schedule\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Attendance\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"LMS Activity\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Assessment\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Assessment Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]",
"creation": "2020-03-02 17:22:57.066401",
"docstatus": 0,
"doctype": "Workspace",
@@ -692,7 +692,7 @@
"type": "Link"
}
],
- "modified": "2021-08-05 12:15:57.929276",
+ "modified": "2022-01-13 17:29:13.676542",
"modified_by": "Administrator",
"module": "Education",
"name": "Education",
@@ -701,7 +701,7 @@
"public": 1,
"restrict_to_domain": "Education",
"roles": [],
- "sequence_id": 9,
+ "sequence_id": 9.0,
"shortcuts": [
{
"color": "Grey",
diff --git a/erpnext/erpnext_integrations/workspace/erpnext_integrations/erpnext_integrations.json b/erpnext/erpnext_integrations/workspace/erpnext_integrations/erpnext_integrations.json
index 8e4f927..45077aa 100644
--- a/erpnext/erpnext_integrations/workspace/erpnext_integrations/erpnext_integrations.json
+++ b/erpnext/erpnext_integrations/workspace/erpnext_integrations/erpnext_integrations.json
@@ -1,6 +1,6 @@
{
"charts": [],
- "content": "[{\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Marketplace\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Payments\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Settings\", \"col\": 4}}]",
+ "content": "[{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Marketplace\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Payments\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
"creation": "2020-08-20 19:30:48.138801",
"docstatus": 0,
"doctype": "Workspace",
@@ -41,17 +41,6 @@
"type": "Link"
},
{
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Shopify Settings",
- "link_count": 0,
- "link_to": "Shopify Settings",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
"hidden": 0,
"is_query_report": 0,
"label": "Payments",
@@ -112,7 +101,7 @@
"type": "Link"
}
],
- "modified": "2021-08-05 12:15:58.740247",
+ "modified": "2022-01-13 17:35:35.508718",
"modified_by": "Administrator",
"module": "ERPNext Integrations",
"name": "ERPNext Integrations",
@@ -121,7 +110,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 10,
+ "sequence_id": 10.0,
"shortcuts": [],
"title": "ERPNext Integrations"
}
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 4502f2b..274f625 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -67,7 +67,6 @@
domains = {
'Distribution': 'erpnext.domains.distribution',
'Education': 'erpnext.domains.education',
- 'Hospitality': 'erpnext.domains.hospitality',
'Manufacturing': 'erpnext.domains.manufacturing',
'Retail': 'erpnext.domains.retail',
'Services': 'erpnext.domains.services',
@@ -563,13 +562,6 @@
{'doctype': 'Assessment Code', 'index': 39},
{'doctype': 'Discussion', 'index': 40},
],
- "Hospitality": [
- {'doctype': 'Hotel Room', 'index': 0},
- {'doctype': 'Hotel Room Reservation', 'index': 1},
- {'doctype': 'Hotel Room Pricing', 'index': 2},
- {'doctype': 'Hotel Room Package', 'index': 3},
- {'doctype': 'Hotel Room Type', 'index': 4}
- ]
}
additional_timeline_content = {
diff --git a/erpnext/hotels/doctype/__init__.py b/erpnext/hotels/doctype/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/hotels/doctype/__init__.py
+++ /dev/null
diff --git a/erpnext/hotels/doctype/hotel_room/__init__.py b/erpnext/hotels/doctype/hotel_room/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/hotels/doctype/hotel_room/__init__.py
+++ /dev/null
diff --git a/erpnext/hotels/doctype/hotel_room/hotel_room.js b/erpnext/hotels/doctype/hotel_room/hotel_room.js
deleted file mode 100644
index 76f22d5..0000000
--- a/erpnext/hotels/doctype/hotel_room/hotel_room.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Hotel Room', {
- refresh: function(frm) {
-
- }
-});
diff --git a/erpnext/hotels/doctype/hotel_room/hotel_room.json b/erpnext/hotels/doctype/hotel_room/hotel_room.json
deleted file mode 100644
index 2567c07..0000000
--- a/erpnext/hotels/doctype/hotel_room/hotel_room.json
+++ /dev/null
@@ -1,175 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "prompt",
- "beta": 1,
- "creation": "2017-12-08 12:33:56.320420",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "hotel_room_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": 0,
- "label": "Hotel Room Type",
- "length": 0,
- "no_copy": 0,
- "options": "Hotel Room 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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "capacity",
- "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": "Capacity",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "extra_bed_capacity",
- "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": "Extra Bed Capacity",
- "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
- }
- ],
- "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": "2017-12-09 12:10:50.670113",
- "modified_by": "Administrator",
- "module": "Hotels",
- "name": "Hotel Room",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- },
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Hotel Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room/hotel_room.py b/erpnext/hotels/doctype/hotel_room/hotel_room.py
deleted file mode 100644
index e4bd1c8..0000000
--- a/erpnext/hotels/doctype/hotel_room/hotel_room.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe.model.document import Document
-
-
-class HotelRoom(Document):
- def validate(self):
- if not self.capacity:
- self.capacity, self.extra_bed_capacity = frappe.db.get_value('Hotel Room Type',
- self.hotel_room_type, ['capacity', 'extra_bed_capacity'])
diff --git a/erpnext/hotels/doctype/hotel_room/test_hotel_room.py b/erpnext/hotels/doctype/hotel_room/test_hotel_room.py
deleted file mode 100644
index 95efe2c..0000000
--- a/erpnext/hotels/doctype/hotel_room/test_hotel_room.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-test_dependencies = ["Hotel Room Package"]
-test_records = [
- dict(doctype="Hotel Room", name="1001",
- hotel_room_type="Basic Room"),
- dict(doctype="Hotel Room", name="1002",
- hotel_room_type="Basic Room"),
- dict(doctype="Hotel Room", name="1003",
- hotel_room_type="Basic Room"),
- dict(doctype="Hotel Room", name="1004",
- hotel_room_type="Basic Room"),
- dict(doctype="Hotel Room", name="1005",
- hotel_room_type="Basic Room"),
- dict(doctype="Hotel Room", name="1006",
- hotel_room_type="Basic Room")
-]
-
-class TestHotelRoom(unittest.TestCase):
- pass
diff --git a/erpnext/hotels/doctype/hotel_room_amenity/__init__.py b/erpnext/hotels/doctype/hotel_room_amenity/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/hotels/doctype/hotel_room_amenity/__init__.py
+++ /dev/null
diff --git a/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.json b/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.json
deleted file mode 100644
index 29a0407..0000000
--- a/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.json
+++ /dev/null
@@ -1,103 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2017-12-08 12:35:36.572185",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 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": 0,
- "label": "Item",
- "length": 0,
- "no_copy": 0,
- "options": "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "billable",
- "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": "Billable",
- "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
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2017-12-09 12:05:07.125687",
- "modified_by": "Administrator",
- "module": "Hotels",
- "name": "Hotel Room Amenity",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.py b/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.py
deleted file mode 100644
index 1664931..0000000
--- a/erpnext/hotels/doctype/hotel_room_amenity/hotel_room_amenity.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class HotelRoomAmenity(Document):
- pass
diff --git a/erpnext/hotels/doctype/hotel_room_package/__init__.py b/erpnext/hotels/doctype/hotel_room_package/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/hotels/doctype/hotel_room_package/__init__.py
+++ /dev/null
diff --git a/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.js b/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.js
deleted file mode 100644
index 5b09ae5..0000000
--- a/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Hotel Room Package', {
- hotel_room_type: function(frm) {
- if (frm.doc.hotel_room_type) {
- frappe.model.with_doc('Hotel Room Type', frm.doc.hotel_room_type, () => {
- let hotel_room_type = frappe.get_doc('Hotel Room Type', frm.doc.hotel_room_type);
-
- // reset the amenities
- frm.doc.amenities = [];
-
- for (let amenity of hotel_room_type.amenities) {
- let d = frm.add_child('amenities');
- d.item = amenity.item;
- d.billable = amenity.billable;
- }
-
- frm.refresh();
- });
- }
- }
-});
diff --git a/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.json b/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.json
deleted file mode 100644
index 57dad44..0000000
--- a/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.json
+++ /dev/null
@@ -1,215 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "prompt",
- "beta": 1,
- "creation": "2017-12-08 12:43:17.211064",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "hotel_room_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": 0,
- "label": "Hotel Room Type",
- "length": 0,
- "no_copy": 0,
- "options": "Hotel Room 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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_2",
- "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
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 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": 0,
- "in_standard_filter": 0,
- "label": "Item",
- "length": 0,
- "no_copy": 0,
- "options": "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_4",
- "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
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amenities",
- "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": "Amenities",
- "length": 0,
- "no_copy": 0,
- "options": "Hotel Room Amenity",
- "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,
- "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": "2017-12-09 12:10:31.111952",
- "modified_by": "Administrator",
- "module": "Hotels",
- "name": "Hotel Room Package",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.py b/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.py
deleted file mode 100644
index aedc83a..0000000
--- a/erpnext/hotels/doctype/hotel_room_package/hotel_room_package.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe.model.document import Document
-
-
-class HotelRoomPackage(Document):
- def validate(self):
- if not self.item:
- item = frappe.get_doc(dict(
- doctype = 'Item',
- item_code = self.name,
- item_group = 'Products',
- is_stock_item = 0,
- stock_uom = 'Unit'
- ))
- item.insert()
- self.item = item.name
diff --git a/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.py b/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.py
deleted file mode 100644
index 749731f..0000000
--- a/erpnext/hotels/doctype/hotel_room_package/test_hotel_room_package.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-test_records = [
- dict(doctype='Item', item_code='Breakfast',
- item_group='Products', is_stock_item=0),
- dict(doctype='Item', item_code='Lunch',
- item_group='Products', is_stock_item=0),
- dict(doctype='Item', item_code='Dinner',
- item_group='Products', is_stock_item=0),
- dict(doctype='Item', item_code='WiFi',
- item_group='Products', is_stock_item=0),
- dict(doctype='Hotel Room Type', name="Delux Room",
- capacity=4,
- extra_bed_capacity=2,
- amenities = [
- dict(item='WiFi', billable=0)
- ]),
- dict(doctype='Hotel Room Type', name="Basic Room",
- capacity=4,
- extra_bed_capacity=2,
- amenities = [
- dict(item='Breakfast', billable=0)
- ]),
- dict(doctype="Hotel Room Package", name="Basic Room with Breakfast",
- hotel_room_type="Basic Room",
- amenities = [
- dict(item="Breakfast", billable=0)
- ]),
- dict(doctype="Hotel Room Package", name="Basic Room with Lunch",
- hotel_room_type="Basic Room",
- amenities = [
- dict(item="Breakfast", billable=0),
- dict(item="Lunch", billable=0)
- ]),
- dict(doctype="Hotel Room Package", name="Basic Room with Dinner",
- hotel_room_type="Basic Room",
- amenities = [
- dict(item="Breakfast", billable=0),
- dict(item="Dinner", billable=0)
- ])
-]
-
-class TestHotelRoomPackage(unittest.TestCase):
- pass
diff --git a/erpnext/hotels/doctype/hotel_room_pricing/__init__.py b/erpnext/hotels/doctype/hotel_room_pricing/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing/__init__.py
+++ /dev/null
diff --git a/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.js b/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.js
deleted file mode 100644
index 87bb192..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Hotel Room Pricing', {
- refresh: function(frm) {
-
- }
-});
diff --git a/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.json b/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.json
deleted file mode 100644
index 0f5a776..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.json
+++ /dev/null
@@ -1,266 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "prompt",
- "beta": 1,
- "creation": "2017-12-08 12:51:47.088174",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 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": 1,
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_5",
- "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
- },
- {
- "allow_bulk_edit": 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,
- "options": "Hotel Room Pricing 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": 1,
- "search_index": 0,
- "set_only_once": 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": "2017-12-09 12:10:41.559559",
- "modified_by": "Administrator",
- "module": "Hotels",
- "name": "Hotel Room Pricing",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- },
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Hotel Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.py b/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.py
deleted file mode 100644
index d28e573..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing/hotel_room_pricing.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class HotelRoomPricing(Document):
- pass
diff --git a/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.py b/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.py
deleted file mode 100644
index 3455009..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing/test_hotel_room_pricing.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-test_dependencies = ["Hotel Room Package"]
-test_records = [
- dict(doctype="Hotel Room Pricing", enabled=1,
- name="Winter 2017",
- from_date="2017-01-01", to_date="2017-01-10",
- items = [
- dict(item="Basic Room with Breakfast", rate=10000),
- dict(item="Basic Room with Lunch", rate=11000),
- dict(item="Basic Room with Dinner", rate=12000)
- ])
-]
-
-class TestHotelRoomPricing(unittest.TestCase):
- pass
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_item/__init__.py b/erpnext/hotels/doctype/hotel_room_pricing_item/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing_item/__init__.py
+++ /dev/null
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.json b/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.json
deleted file mode 100644
index d6cd826..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.json
+++ /dev/null
@@ -1,103 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2017-12-08 12:50:13.486090",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 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": 0,
- "label": "Item",
- "length": 0,
- "no_copy": 0,
- "options": "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "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,
- "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,
- "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": 1,
- "max_attachments": 0,
- "modified": "2017-12-09 12:04:58.641703",
- "modified_by": "Administrator",
- "module": "Hotels",
- "name": "Hotel Room Pricing Item",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.py b/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.py
deleted file mode 100644
index 2e6bb5f..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing_item/hotel_room_pricing_item.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class HotelRoomPricingItem(Document):
- pass
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/__init__.py b/erpnext/hotels/doctype/hotel_room_pricing_package/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing_package/__init__.py
+++ /dev/null
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.js b/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.js
deleted file mode 100644
index f6decd9..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Hotel Room Pricing Package', {
- refresh: function(frm) {
-
- }
-});
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.json b/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.json
deleted file mode 100644
index 1e52932..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.json
+++ /dev/null
@@ -1,173 +0,0 @@
-{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2017-12-08 12:50:13.486090",
- "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,
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "hotel_room_package",
- "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": "Hotel Room Package",
- "length": 0,
- "no_copy": 0,
- "options": "Hotel Room Package",
- "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": "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,
- "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
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-11-04 03:34:02.551811",
- "modified_by": "Administrator",
- "module": "Hotels",
- "name": "Hotel Room Pricing Package",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "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/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.py b/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.py
deleted file mode 100644
index ebbdb6e..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing_package/hotel_room_pricing_package.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class HotelRoomPricingPackage(Document):
- pass
diff --git a/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.py b/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.py
deleted file mode 100644
index 196e650..0000000
--- a/erpnext/hotels/doctype/hotel_room_pricing_package/test_hotel_room_pricing_package.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestHotelRoomPricingPackage(unittest.TestCase):
- pass
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/__init__.py b/erpnext/hotels/doctype/hotel_room_reservation/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/hotels/doctype/hotel_room_reservation/__init__.py
+++ /dev/null
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.js b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.js
deleted file mode 100644
index e58d763..0000000
--- a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.js
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Hotel Room Reservation', {
- refresh: function(frm) {
- if(frm.doc.docstatus == 1){
- frm.add_custom_button(__('Create Invoice'), ()=> {
- frm.trigger("make_invoice");
- });
- }
- },
- from_date: function(frm) {
- frm.trigger("recalculate_rates");
- },
- to_date: function(frm) {
- frm.trigger("recalculate_rates");
- },
- recalculate_rates: function(frm) {
- if (!frm.doc.from_date || !frm.doc.to_date
- || !frm.doc.items.length){
- return;
- }
- frappe.call({
- "method": "erpnext.hotels.doctype.hotel_room_reservation.hotel_room_reservation.get_room_rate",
- "args": {"hotel_room_reservation": frm.doc}
- }).done((r)=> {
- for (var i = 0; i < r.message.items.length; i++) {
- frm.doc.items[i].rate = r.message.items[i].rate;
- frm.doc.items[i].amount = r.message.items[i].amount;
- }
- frappe.run_serially([
- ()=> frm.set_value("net_total", r.message.net_total),
- ()=> frm.refresh_field("items")
- ]);
- });
- },
- make_invoice: function(frm) {
- frappe.model.with_doc("Hotel Settings", "Hotel Settings", ()=>{
- frappe.model.with_doctype("Sales Invoice", ()=>{
- let hotel_settings = frappe.get_doc("Hotel Settings", "Hotel Settings");
- let invoice = frappe.model.get_new_doc("Sales Invoice");
- invoice.customer = frm.doc.customer || hotel_settings.default_customer;
- if (hotel_settings.default_invoice_naming_series){
- invoice.naming_series = hotel_settings.default_invoice_naming_series;
- }
- for (let d of frm.doc.items){
- let invoice_item = frappe.model.add_child(invoice, "items")
- invoice_item.item_code = d.item;
- invoice_item.qty = d.qty;
- invoice_item.rate = d.rate;
- }
- if (hotel_settings.default_taxes_and_charges){
- invoice.taxes_and_charges = hotel_settings.default_taxes_and_charges;
- }
- frappe.set_route("Form", invoice.doctype, invoice.name);
- });
- });
- }
-});
-
-frappe.ui.form.on('Hotel Room Reservation Item', {
- item: function(frm, doctype, name) {
- frm.trigger("recalculate_rates");
- },
- qty: function(frm) {
- frm.trigger("recalculate_rates");
- }
-});
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.json b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.json
deleted file mode 100644
index fd20efd..0000000
--- a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.json
+++ /dev/null
@@ -1,436 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 0,
- "autoname": "HTL-RES-.YYYY.-.#####",
- "beta": 1,
- "creation": "2017-12-08 13:01:34.829175",
- "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,
- "fieldname": "guest_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": "Guest Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 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": "customer",
- "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",
- "length": 0,
- "no_copy": 0,
- "options": "Customer",
- "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": "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
- },
- {
- "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
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "late_checkin",
- "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": "Late Checkin",
- "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": "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
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 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": 0,
- "in_standard_filter": 0,
- "label": "Status",
- "length": 0,
- "no_copy": 0,
- "options": "Booked\nAdvance Paid\nInvoiced\nPaid\nCompleted\nCancelled",
- "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": "section_break_8",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "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,
- "options": "Hotel Room Reservation 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": 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": "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,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amended_from",
- "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": "Hotel Room Reservation",
- "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
- }
- ],
- "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:47.326951",
- "modified_by": "Administrator",
- "module": "Hotels",
- "name": "Hotel Room Reservation",
- "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,
- "write": 1
- },
- {
- "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": "Hotel Reservation User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "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/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py
deleted file mode 100644
index 7725955..0000000
--- a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import json
-
-import frappe
-from frappe import _
-from frappe.model.document import Document
-from frappe.utils import add_days, date_diff, flt
-
-
-class HotelRoomUnavailableError(frappe.ValidationError): pass
-class HotelRoomPricingNotSetError(frappe.ValidationError): pass
-
-class HotelRoomReservation(Document):
- def validate(self):
- self.total_rooms = {}
- self.set_rates()
- self.validate_availability()
-
- def validate_availability(self):
- for i in range(date_diff(self.to_date, self.from_date)):
- day = add_days(self.from_date, i)
- self.rooms_booked = {}
-
- for d in self.items:
- if not d.item in self.rooms_booked:
- self.rooms_booked[d.item] = 0
-
- room_type = frappe.db.get_value("Hotel Room Package",
- d.item, 'hotel_room_type')
- rooms_booked = get_rooms_booked(room_type, day, exclude_reservation=self.name) \
- + d.qty + self.rooms_booked.get(d.item)
- total_rooms = self.get_total_rooms(d.item)
- if total_rooms < rooms_booked:
- frappe.throw(_("Hotel Rooms of type {0} are unavailable on {1}").format(d.item,
- frappe.format(day, dict(fieldtype="Date"))), exc=HotelRoomUnavailableError)
-
- self.rooms_booked[d.item] += rooms_booked
-
- def get_total_rooms(self, item):
- if not item in self.total_rooms:
- self.total_rooms[item] = frappe.db.sql("""
- select count(*)
- from
- `tabHotel Room Package` package
- inner join
- `tabHotel Room` room on package.hotel_room_type = room.hotel_room_type
- where
- package.item = %s""", item)[0][0] or 0
-
- return self.total_rooms[item]
-
- def set_rates(self):
- self.net_total = 0
- for d in self.items:
- net_rate = 0.0
- for i in range(date_diff(self.to_date, self.from_date)):
- day = add_days(self.from_date, i)
- if not d.item:
- continue
- day_rate = frappe.db.sql("""
- select
- item.rate
- from
- `tabHotel Room Pricing Item` item,
- `tabHotel Room Pricing` pricing
- where
- item.parent = pricing.name
- and item.item = %s
- and %s between pricing.from_date
- and pricing.to_date""", (d.item, day))
-
- if day_rate:
- net_rate += day_rate[0][0]
- else:
- frappe.throw(
- _("Please set Hotel Room Rate on {}").format(
- frappe.format(day, dict(fieldtype="Date"))), exc=HotelRoomPricingNotSetError)
- d.rate = net_rate
- d.amount = net_rate * flt(d.qty)
- self.net_total += d.amount
-
-@frappe.whitelist()
-def get_room_rate(hotel_room_reservation):
- """Calculate rate for each day as it may belong to different Hotel Room Pricing Item"""
- doc = frappe.get_doc(json.loads(hotel_room_reservation))
- doc.set_rates()
- return doc.as_dict()
-
-def get_rooms_booked(room_type, day, exclude_reservation=None):
- exclude_condition = ''
- if exclude_reservation:
- exclude_condition = 'and reservation.name != {0}'.format(frappe.db.escape(exclude_reservation))
-
- return frappe.db.sql("""
- select sum(item.qty)
- from
- `tabHotel Room Package` room_package,
- `tabHotel Room Reservation Item` item,
- `tabHotel Room Reservation` reservation
- where
- item.parent = reservation.name
- and room_package.item = item.item
- and room_package.hotel_room_type = %s
- and reservation.docstatus = 1
- {exclude_condition}
- and %s between reservation.from_date
- and reservation.to_date""".format(exclude_condition=exclude_condition),
- (room_type, day))[0][0] or 0
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation_calendar.js b/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation_calendar.js
deleted file mode 100644
index 7bde292..0000000
--- a/erpnext/hotels/doctype/hotel_room_reservation/hotel_room_reservation_calendar.js
+++ /dev/null
@@ -1,9 +0,0 @@
-frappe.views.calendar["Hotel Room Reservation"] = {
- field_map: {
- "start": "from_date",
- "end": "to_date",
- "id": "name",
- "title": "guest_name",
- "status": "status"
- }
-}
diff --git a/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.py b/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.py
deleted file mode 100644
index bb32a27..0000000
--- a/erpnext/hotels/doctype/hotel_room_reservation/test_hotel_room_reservation.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-import frappe
-
-from erpnext.hotels.doctype.hotel_room_reservation.hotel_room_reservation import (
- HotelRoomPricingNotSetError,
- HotelRoomUnavailableError,
-)
-
-test_dependencies = ["Hotel Room Package", "Hotel Room Pricing", "Hotel Room"]
-
-class TestHotelRoomReservation(unittest.TestCase):
- def setUp(self):
- frappe.db.sql("delete from `tabHotel Room Reservation`")
- frappe.db.sql("delete from `tabHotel Room Reservation Item`")
-
- def test_reservation(self):
- reservation = make_reservation(
- from_date="2017-01-01",
- to_date="2017-01-03",
- items=[
- dict(item="Basic Room with Dinner", qty=2)
- ]
- )
- reservation.insert()
- self.assertEqual(reservation.net_total, 48000)
-
- def test_price_not_set(self):
- reservation = make_reservation(
- from_date="2016-01-01",
- to_date="2016-01-03",
- items=[
- dict(item="Basic Room with Dinner", qty=2)
- ]
- )
- self.assertRaises(HotelRoomPricingNotSetError, reservation.insert)
-
- def test_room_unavailable(self):
- reservation = make_reservation(
- from_date="2017-01-01",
- to_date="2017-01-03",
- items=[
- dict(item="Basic Room with Dinner", qty=2),
- ]
- )
- reservation.insert()
-
- reservation = make_reservation(
- from_date="2017-01-01",
- to_date="2017-01-03",
- items=[
- dict(item="Basic Room with Dinner", qty=20),
- ]
- )
- self.assertRaises(HotelRoomUnavailableError, reservation.insert)
-
-def make_reservation(**kwargs):
- kwargs["doctype"] = "Hotel Room Reservation"
- if not "guest_name" in kwargs:
- kwargs["guest_name"] = "Test Guest"
- doc = frappe.get_doc(kwargs)
- return doc
diff --git a/erpnext/hotels/doctype/hotel_room_reservation_item/__init__.py b/erpnext/hotels/doctype/hotel_room_reservation_item/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/hotels/doctype/hotel_room_reservation_item/__init__.py
+++ /dev/null
diff --git a/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.json b/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.json
deleted file mode 100644
index 2b7931e..0000000
--- a/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.json
+++ /dev/null
@@ -1,195 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "",
- "beta": 0,
- "creation": "2017-12-08 12:58:21.733330",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 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": 0,
- "label": "Item",
- "length": 0,
- "no_copy": 0,
- "options": "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "qty",
- "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": "Qty",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 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,
- "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": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "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,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 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": 1,
- "in_standard_filter": 0,
- "label": "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,
- "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": 1,
- "max_attachments": 0,
- "modified": "2017-12-09 12:04:34.562956",
- "modified_by": "Administrator",
- "module": "Hotels",
- "name": "Hotel Room Reservation Item",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.py b/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.py
deleted file mode 100644
index 41d86dd..0000000
--- a/erpnext/hotels/doctype/hotel_room_reservation_item/hotel_room_reservation_item.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class HotelRoomReservationItem(Document):
- pass
diff --git a/erpnext/hotels/doctype/hotel_room_type/__init__.py b/erpnext/hotels/doctype/hotel_room_type/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/hotels/doctype/hotel_room_type/__init__.py
+++ /dev/null
diff --git a/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.js b/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.js
deleted file mode 100644
index d73835d..0000000
--- a/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Hotel Room Type', {
- refresh: function(frm) {
-
- }
-});
diff --git a/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.json b/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.json
deleted file mode 100644
index 3d26413..0000000
--- a/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.json
+++ /dev/null
@@ -1,204 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "prompt",
- "beta": 1,
- "creation": "2017-12-08 12:38:29.485175",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "capacity",
- "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": "Capacity",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "extra_bed_capacity",
- "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": "Extra Bed Capacity",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_3",
- "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
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amenities",
- "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": "Amenities",
- "length": 0,
- "no_copy": 0,
- "options": "Hotel Room Amenity",
- "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,
- "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": "2017-12-09 12:10:23.355486",
- "modified_by": "Administrator",
- "module": "Hotels",
- "name": "Hotel Room Type",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- },
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Hotel Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.py b/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.py
deleted file mode 100644
index 7ab529f..0000000
--- a/erpnext/hotels/doctype/hotel_room_type/hotel_room_type.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class HotelRoomType(Document):
- pass
diff --git a/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.py b/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.py
deleted file mode 100644
index 8d1147d..0000000
--- a/erpnext/hotels/doctype/hotel_room_type/test_hotel_room_type.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestHotelRoomType(unittest.TestCase):
- pass
diff --git a/erpnext/hotels/doctype/hotel_settings/hotel_settings.js b/erpnext/hotels/doctype/hotel_settings/hotel_settings.js
deleted file mode 100644
index 0b4a2c3..0000000
--- a/erpnext/hotels/doctype/hotel_settings/hotel_settings.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Hotel Settings', {
- refresh: function(frm) {
-
- }
-});
diff --git a/erpnext/hotels/doctype/hotel_settings/hotel_settings.json b/erpnext/hotels/doctype/hotel_settings/hotel_settings.json
deleted file mode 100644
index d9f5572..0000000
--- a/erpnext/hotels/doctype/hotel_settings/hotel_settings.json
+++ /dev/null
@@ -1,175 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 1,
- "creation": "2017-12-08 17:50:24.523107",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "default_customer",
- "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": "Default Customer",
- "length": 0,
- "no_copy": 0,
- "options": "Customer",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "default_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": "Default Taxes and Charges",
- "length": 0,
- "no_copy": 0,
- "options": "Sales Taxes and Charges 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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "default_invoice_naming_series",
- "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": "Default Invoice Naming Series",
- "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
- }
- ],
- "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": "2017-12-09 12:11:12.857308",
- "modified_by": "Administrator",
- "module": "Hotels",
- "name": "Hotel Settings",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 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,
- "write": 1
- },
- {
- "amend": 0,
- "apply_user_permissions": 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": "Hotel Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/hotels/doctype/hotel_settings/hotel_settings.py b/erpnext/hotels/doctype/hotel_settings/hotel_settings.py
deleted file mode 100644
index 8376d50..0000000
--- a/erpnext/hotels/doctype/hotel_settings/hotel_settings.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class HotelSettings(Document):
- pass
diff --git a/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.py b/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.py
deleted file mode 100644
index e76c00c..0000000
--- a/erpnext/hotels/doctype/hotel_settings/test_hotel_settings.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestHotelSettings(unittest.TestCase):
- pass
diff --git a/erpnext/hotels/report/hotel_room_occupancy/__init__.py b/erpnext/hotels/report/hotel_room_occupancy/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/hotels/report/hotel_room_occupancy/__init__.py
+++ /dev/null
diff --git a/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.js b/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.js
deleted file mode 100644
index 81efb2d..0000000
--- a/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-/* eslint-disable */
-
-frappe.query_reports["Hotel Room Occupancy"] = {
- "filters": [
- {
- "fieldname":"from_date",
- "label": __("From Date"),
- "fieldtype": "Date",
- "default": frappe.datetime.now_date(),
- "reqd":1
- },
- {
- "fieldname":"to_date",
- "label": __("To Date"),
- "fieldtype": "Date",
- "default": frappe.datetime.now_date(),
- "reqd":1
- }
- ]
-}
diff --git a/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.json b/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.json
deleted file mode 100644
index 782a48b..0000000
--- a/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "add_total_row": 1,
- "apply_user_permissions": 1,
- "creation": "2017-12-09 14:31:26.306705",
- "disabled": 0,
- "docstatus": 0,
- "doctype": "Report",
- "idx": 0,
- "is_standard": "Yes",
- "modified": "2017-12-09 14:31:26.306705",
- "modified_by": "Administrator",
- "module": "Hotels",
- "name": "Hotel Room Occupancy",
- "owner": "Administrator",
- "ref_doctype": "Hotel Room Reservation",
- "report_name": "Hotel Room Occupancy",
- "report_type": "Script Report",
- "roles": [
- {
- "role": "System Manager"
- },
- {
- "role": "Hotel Reservation User"
- }
- ]
-}
\ No newline at end of file
diff --git a/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.py b/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.py
deleted file mode 100644
index c43589d..0000000
--- a/erpnext/hotels/report/hotel_room_occupancy/hotel_room_occupancy.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe import _
-from frappe.utils import add_days, date_diff
-
-from erpnext.hotels.doctype.hotel_room_reservation.hotel_room_reservation import get_rooms_booked
-
-
-def execute(filters=None):
- columns = get_columns(filters)
- data = get_data(filters)
- return columns, data
-
-def get_columns(filters):
- columns = [
- dict(label=_("Room Type"), fieldname="room_type"),
- dict(label=_("Rooms Booked"), fieldtype="Int")
- ]
- return columns
-
-def get_data(filters):
- out = []
- for room_type in frappe.get_all('Hotel Room Type'):
- total_booked = 0
- for i in range(date_diff(filters.to_date, filters.from_date)):
- day = add_days(filters.from_date, i)
- total_booked += get_rooms_booked(room_type.name, day)
-
- out.append([room_type.name, total_booked])
-
- return out
diff --git a/erpnext/hr/doctype/appointment_letter/appointment_letter.json b/erpnext/hr/doctype/appointment_letter/appointment_letter.json
index c81b700..012f6b6 100644
--- a/erpnext/hr/doctype/appointment_letter/appointment_letter.json
+++ b/erpnext/hr/doctype/appointment_letter/appointment_letter.json
@@ -86,11 +86,12 @@
}
],
"links": [],
- "modified": "2020-01-21 17:30:36.334395",
+ "modified": "2022-01-18 19:27:35.649424",
"modified_by": "Administrator",
"module": "HR",
"name": "Appointment Letter",
"name_case": "Title Case",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -118,7 +119,10 @@
"write": 1
}
],
+ "search_fields": "applicant_name, company",
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
+ "title_field": "applicant_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/appointment_letter_template/appointment_letter_template.json b/erpnext/hr/doctype/appointment_letter_template/appointment_letter_template.json
index c136fb2..5e50fe6 100644
--- a/erpnext/hr/doctype/appointment_letter_template/appointment_letter_template.json
+++ b/erpnext/hr/doctype/appointment_letter_template/appointment_letter_template.json
@@ -1,11 +1,12 @@
{
"actions": [],
- "autoname": "HR-APP-LETTER-TEMP-.#####",
+ "autoname": "field:template_name",
"creation": "2019-12-26 12:20:14.219578",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
+ "template_name",
"introduction",
"terms",
"closing_notes"
@@ -29,13 +30,21 @@
"label": "Terms",
"options": "Appointment Letter content",
"reqd": 1
+ },
+ {
+ "fieldname": "template_name",
+ "fieldtype": "Data",
+ "label": "Template Name",
+ "reqd": 1,
+ "unique": 1
}
],
"links": [],
- "modified": "2020-01-21 17:00:46.779420",
+ "modified": "2022-01-18 19:25:14.614616",
"modified_by": "Administrator",
"module": "HR",
"name": "Appointment Letter Template",
+ "naming_rule": "By fieldname",
"owner": "Administrator",
"permissions": [
{
@@ -63,7 +72,10 @@
"write": 1
}
],
+ "search_fields": "template_name",
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
+ "title_field": "template_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py
index 7dcfac2..b1eaaf8 100644
--- a/erpnext/hr/doctype/attendance/attendance.py
+++ b/erpnext/hr/doctype/attendance/attendance.py
@@ -5,9 +5,9 @@
import frappe
from frappe import _
from frappe.model.document import Document
-from frappe.utils import cstr, formatdate, get_datetime, getdate, nowdate
+from frappe.utils import cint, cstr, formatdate, get_datetime, getdate, nowdate
-from erpnext.hr.utils import validate_active_employee
+from erpnext.hr.utils import get_holiday_dates_for_employee, validate_active_employee
class Attendance(Document):
@@ -171,7 +171,7 @@
})
@frappe.whitelist()
-def get_unmarked_days(employee, month):
+def get_unmarked_days(employee, month, exclude_holidays=0):
import calendar
month_map = get_month_map()
@@ -191,6 +191,11 @@
])
marked_days = [get_datetime(record.attendance_date) for record in records]
+ if cint(exclude_holidays):
+ holiday_dates = get_holiday_dates_for_employee(employee, month_start, month_end)
+ holidays = [get_datetime(record) for record in holiday_dates]
+ marked_days.extend(holidays)
+
unmarked_days = []
for date in dates_of_month:
diff --git a/erpnext/hr/doctype/attendance/attendance_list.js b/erpnext/hr/doctype/attendance/attendance_list.js
index 6b3c29a..3a5c591 100644
--- a/erpnext/hr/doctype/attendance/attendance_list.js
+++ b/erpnext/hr/doctype/attendance/attendance_list.js
@@ -28,6 +28,7 @@
onchange: function() {
dialog.set_df_property("unmarked_days", "hidden", 1);
dialog.set_df_property("status", "hidden", 1);
+ dialog.set_df_property("exclude_holidays", "hidden", 1);
dialog.set_df_property("month", "value", '');
dialog.set_df_property("unmarked_days", "options", []);
dialog.no_unmarked_days_left = false;
@@ -42,9 +43,14 @@
onchange: function() {
if (dialog.fields_dict.employee.value && dialog.fields_dict.month.value) {
dialog.set_df_property("status", "hidden", 0);
+ dialog.set_df_property("exclude_holidays", "hidden", 0);
dialog.set_df_property("unmarked_days", "options", []);
dialog.no_unmarked_days_left = false;
- me.get_multi_select_options(dialog.fields_dict.employee.value, dialog.fields_dict.month.value).then(options => {
+ me.get_multi_select_options(
+ dialog.fields_dict.employee.value,
+ dialog.fields_dict.month.value,
+ dialog.fields_dict.exclude_holidays.get_value()
+ ).then(options => {
if (options.length > 0) {
dialog.set_df_property("unmarked_days", "hidden", 0);
dialog.set_df_property("unmarked_days", "options", options);
@@ -65,6 +71,31 @@
},
{
+ label: __("Exclude Holidays"),
+ fieldtype: "Check",
+ fieldname: "exclude_holidays",
+ hidden: 1,
+ onchange: function() {
+ if (dialog.fields_dict.employee.value && dialog.fields_dict.month.value) {
+ dialog.set_df_property("status", "hidden", 0);
+ dialog.set_df_property("unmarked_days", "options", []);
+ dialog.no_unmarked_days_left = false;
+ me.get_multi_select_options(
+ dialog.fields_dict.employee.value,
+ dialog.fields_dict.month.value,
+ dialog.fields_dict.exclude_holidays.get_value()
+ ).then(options => {
+ if (options.length > 0) {
+ dialog.set_df_property("unmarked_days", "hidden", 0);
+ dialog.set_df_property("unmarked_days", "options", options);
+ } else {
+ dialog.no_unmarked_days_left = true;
+ }
+ });
+ }
+ }
+ },
+ {
label: __("Unmarked Attendance for days"),
fieldname: "unmarked_days",
fieldtype: "MultiCheck",
@@ -105,7 +136,7 @@
});
},
- get_multi_select_options: function(employee, month) {
+ get_multi_select_options: function(employee, month, exclude_holidays) {
return new Promise(resolve => {
frappe.call({
method: 'erpnext.hr.doctype.attendance.attendance.get_unmarked_days',
@@ -113,6 +144,7 @@
args: {
employee: employee,
month: month,
+ exclude_holidays: exclude_holidays
}
}).then(r => {
var options = [];
diff --git a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py
index cb1b560..2d129c8 100644
--- a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py
+++ b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py
@@ -19,7 +19,7 @@
if frappe.db.exists('Employee Onboarding', {'employee_name': 'Test Researcher'}):
frappe.delete_doc('Employee Onboarding', {'employee_name': 'Test Researcher'})
- project = "Employee Onboarding : Test Researcher - test@researcher.com"
+ project = "Employee Onboarding : test@researcher.com"
frappe.db.sql("delete from tabProject where name=%s", project)
frappe.db.sql("delete from tabTask where project=%s", project)
@@ -27,7 +27,7 @@
onboarding = create_employee_onboarding()
project_name = frappe.db.get_value('Project', onboarding.project, 'project_name')
- self.assertEqual(project_name, 'Employee Onboarding : Test Researcher - test@researcher.com')
+ self.assertEqual(project_name, 'Employee Onboarding : test@researcher.com')
# don't allow making employee if onboarding is not complete
self.assertRaises(IncompleteTaskError, make_employee, onboarding.name)
@@ -64,8 +64,8 @@
def get_job_applicant():
- if frappe.db.exists('Job Applicant', 'Test Researcher - test@researcher.com'):
- return frappe.get_doc('Job Applicant', 'Test Researcher - test@researcher.com')
+ if frappe.db.exists('Job Applicant', 'test@researcher.com'):
+ return frappe.get_doc('Job Applicant', 'test@researcher.com')
applicant = frappe.new_doc('Job Applicant')
applicant.applicant_name = 'Test Researcher'
applicant.email_id = 'test@researcher.com'
diff --git a/erpnext/hr/doctype/job_applicant/job_applicant.json b/erpnext/hr/doctype/job_applicant/job_applicant.json
index 200f675..66b609c 100644
--- a/erpnext/hr/doctype/job_applicant/job_applicant.json
+++ b/erpnext/hr/doctype/job_applicant/job_applicant.json
@@ -192,10 +192,11 @@
"idx": 1,
"index_web_pages_for_search": 1,
"links": [],
- "modified": "2021-09-29 23:06:10.904260",
+ "modified": "2022-01-12 16:28:53.196881",
"modified_by": "Administrator",
"module": "HR",
"name": "Job Applicant",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -210,10 +211,11 @@
"write": 1
}
],
- "search_fields": "applicant_name",
+ "search_fields": "applicant_name, email_id, job_title, phone_number",
"sender_field": "email_id",
"sort_field": "modified",
"sort_order": "ASC",
+ "states": [],
"subject_field": "notes",
"title_field": "applicant_name"
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/job_applicant/job_applicant.py b/erpnext/hr/doctype/job_applicant/job_applicant.py
index abaa50c..5b3d9bf 100644
--- a/erpnext/hr/doctype/job_applicant/job_applicant.py
+++ b/erpnext/hr/doctype/job_applicant/job_applicant.py
@@ -7,6 +7,7 @@
import frappe
from frappe import _
from frappe.model.document import Document
+from frappe.model.naming import append_number_if_name_exists
from frappe.utils import validate_email_address
from erpnext.hr.doctype.interview.interview import get_interviewers
@@ -21,10 +22,11 @@
self.get("__onload").job_offer = job_offer[0].name
def autoname(self):
- keys = filter(None, (self.applicant_name, self.email_id, self.job_title))
- if not keys:
- frappe.throw(_("Name or Email is mandatory"), frappe.NameError)
- self.name = " - ".join(keys)
+ self.name = self.email_id
+
+ # applicant can apply more than once for a different job title or reapply
+ if frappe.db.exists("Job Applicant", self.name):
+ self.name = append_number_if_name_exists("Job Applicant", self.name)
def validate(self):
if self.email_id:
diff --git a/erpnext/hr/doctype/job_applicant/test_job_applicant.py b/erpnext/hr/doctype/job_applicant/test_job_applicant.py
index 36dcf6b..bf16220 100644
--- a/erpnext/hr/doctype/job_applicant/test_job_applicant.py
+++ b/erpnext/hr/doctype/job_applicant/test_job_applicant.py
@@ -9,7 +9,26 @@
class TestJobApplicant(unittest.TestCase):
- pass
+ def test_job_applicant_naming(self):
+ applicant = frappe.get_doc({
+ "doctype": "Job Applicant",
+ "status": "Open",
+ "applicant_name": "_Test Applicant",
+ "email_id": "job_applicant_naming@example.com"
+ }).insert()
+ self.assertEqual(applicant.name, 'job_applicant_naming@example.com')
+
+ applicant = frappe.get_doc({
+ "doctype": "Job Applicant",
+ "status": "Open",
+ "applicant_name": "_Test Applicant",
+ "email_id": "job_applicant_naming@example.com"
+ }).insert()
+ self.assertEqual(applicant.name, 'job_applicant_naming@example.com-1')
+
+ def tearDown(self):
+ frappe.db.rollback()
+
def create_job_applicant(**args):
args = frappe._dict(args)
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.json b/erpnext/hr/doctype/leave_allocation/leave_allocation.json
index 52ee463..9ecbe01 100644
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.json
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.json
@@ -237,10 +237,11 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-10-01 15:28:26.335104",
+ "modified": "2022-01-18 19:15:53.262536",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Allocation",
+ "naming_rule": "By \"Naming Series\" field",
"owner": "Administrator",
"permissions": [
{
@@ -278,5 +279,7 @@
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
- "timeline_field": "employee"
-}
+ "states": [],
+ "timeline_field": "employee",
+ "title_field": "employee_name"
+}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_application/leave_application_email_template.html b/erpnext/hr/doctype/leave_application/leave_application_email_template.html
index 14ca41b..dae9084 100644
--- a/erpnext/hr/doctype/leave_application/leave_application_email_template.html
+++ b/erpnext/hr/doctype/leave_application/leave_application_email_template.html
@@ -23,3 +23,8 @@
<td>{{status}}</td>
</tr>
</table>
+
+ {% set doc_link = frappe.utils.get_url_to_form('Leave Application', name) %}
+
+ <br><br>
+ <a class="btn btn-primary" href="{{ doc_link }}" target="_blank">{{ _('Open Now') }}</a>
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py
index f73d3e5..9b8d638 100644
--- a/erpnext/hr/doctype/leave_application/test_leave_application.py
+++ b/erpnext/hr/doctype/leave_application/test_leave_application.py
@@ -443,6 +443,7 @@
leave_policy = frappe.get_doc({
"doctype": "Leave Policy",
+ "title": "Test Leave Policy",
"leave_policy_details": [{"leave_type": leave_type, "annual_allocation": 6}]
}).insert()
diff --git a/erpnext/hr/doctype/leave_encashment/leave_encashment.json b/erpnext/hr/doctype/leave_encashment/leave_encashment.json
index 1f6c03f..cc4e53e 100644
--- a/erpnext/hr/doctype/leave_encashment/leave_encashment.json
+++ b/erpnext/hr/doctype/leave_encashment/leave_encashment.json
@@ -154,10 +154,11 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2021-03-31 22:32:55.492327",
+ "modified": "2022-01-18 19:16:52.414356",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Encashment",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -218,7 +219,10 @@
"write": 1
}
],
+ "search_fields": "employee,employee_name",
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
+ "title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_period/leave_period.json b/erpnext/hr/doctype/leave_period/leave_period.json
index 9e895c3..84ce114 100644
--- a/erpnext/hr/doctype/leave_period/leave_period.json
+++ b/erpnext/hr/doctype/leave_period/leave_period.json
@@ -1,294 +1,108 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
+ "actions": [],
"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",
+ "field_order": [
+ "from_date",
+ "to_date",
+ "is_active",
+ "column_break_3",
+ "company",
+ "optional_holiday_list"
+ ],
"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,
- "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": 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
+ "reqd": 1
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
+ "default": "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
+ "label": "Is Active"
},
{
- "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
+ "fieldtype": "Column Break"
},
{
- "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
+ "reqd": 1
},
{
- "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
+ "options": "Holiday List"
}
],
- "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",
+ "links": [],
+ "modified": "2022-01-13 13:28:12.951025",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Period",
- "name_case": "",
+ "naming_rule": "Expression (old style)",
"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,
"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,
"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,
"write": 1
}
],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
+ "search_fields": "from_date, to_date, company",
"sort_field": "modified",
"sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "states": [],
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_policy/leave_policy.json b/erpnext/hr/doctype/leave_policy/leave_policy.json
index 373095d..6ac8f20 100644
--- a/erpnext/hr/doctype/leave_policy/leave_policy.json
+++ b/erpnext/hr/doctype/leave_policy/leave_policy.json
@@ -1,131 +1,55 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
+ "actions": [],
"autoname": "HR-LPOL-.YYYY.-.#####",
- "beta": 0,
"creation": "2018-04-13 16:06:19.507624",
- "custom": 0,
- "docstatus": 0,
"doctype": "DocType",
- "document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
+ "field_order": [
+ "title",
+ "leave_allocations_section",
+ "leave_policy_details",
+ "amended_from"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
"allow_in_quick_entry": 1,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "leave_allocations_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": "Leave Allocations",
- "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": "Leave Allocations"
},
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "leave_policy_details",
"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": "Leave Policy Details",
- "length": 0,
- "no_copy": 0,
"options": "Leave Policy Detail",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "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": "Leave Policy",
- "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_on_submit": 1,
+ "fieldname": "title",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Title",
+ "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-29 08:42:53.363088",
+ "links": [],
+ "modified": "2022-01-19 13:07:40.556500",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Policy",
- "name_case": "",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -135,14 +59,10 @@
"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,
"write": 1
@@ -154,14 +74,10 @@
"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,
"write": 1
@@ -173,26 +89,19 @@
"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,
"write": 1
}
],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
+ "search_fields": "title",
"sort_field": "modified",
"sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ "states": [],
+ "title_field": "title",
+ "track_changes": 1
}
\ 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 3dbbef8..a4b8af7 100644
--- a/erpnext/hr/doctype/leave_policy/test_leave_policy.py
+++ b/erpnext/hr/doctype/leave_policy/test_leave_policy.py
@@ -24,6 +24,7 @@
args = frappe._dict(args)
return frappe.get_doc({
"doctype": "Leave Policy",
+ "title": "Test Leave Policy",
"leave_policy_details": [{
"leave_type": args.leave_type or "_Test Leave Type",
"annual_allocation": args.annual_allocation or 10
diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.json b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.json
index 3373350..27f0540 100644
--- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.json
+++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.json
@@ -113,10 +113,11 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2021-03-01 17:54:01.014509",
+ "modified": "2022-01-13 13:37:11.218882",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Policy Assignment",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -164,5 +165,7 @@
],
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
+ "title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
index 655e3ac..355370f 100644
--- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
+++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
@@ -128,6 +128,8 @@
monthly_earned_leave = get_monthly_earned_leave(new_leaves_allocated,
leave_type_details.get(leave_type).earned_leave_frequency, leave_type_details.get(leave_type).rounding)
new_leaves_allocated = monthly_earned_leave * months_passed
+ else:
+ new_leaves_allocated = 0
return new_leaves_allocated
diff --git a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_list.js b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_list.js
index 8b954c4..6b75817 100644
--- a/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_list.js
+++ b/erpnext/hr/doctype/leave_policy_assignment/leave_policy_assignment_list.js
@@ -48,7 +48,16 @@
if (cur_dialog.fields_dict.leave_period.value) {
me.set_effective_date();
}
- }
+ },
+ get_query() {
+ let filters = {"is_active": 1};
+ if (cur_dialog.fields_dict.company.value)
+ filters["company"] = cur_dialog.fields_dict.company.value;
+
+ return {
+ filters: filters
+ };
+ },
},
{
fieldtype: "Column Break"
diff --git a/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py b/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py
index b1861ad..3b7f8ec 100644
--- a/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py
+++ b/erpnext/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py
@@ -4,6 +4,7 @@
import unittest
import frappe
+from frappe.utils import add_months, get_first_day, getdate
from erpnext.hr.doctype.leave_application.test_leave_application import (
get_employee,
@@ -17,9 +18,8 @@
test_dependencies = ["Employee"]
class TestLeavePolicyAssignment(unittest.TestCase):
-
def setUp(self):
- for doctype in ["Leave Application", "Leave Allocation", "Leave Policy Assignment", "Leave Ledger Entry"]:
+ for doctype in ["Leave Period", "Leave Application", "Leave Allocation", "Leave Policy Assignment", "Leave Ledger Entry"]:
frappe.db.sql("delete from `tab{0}`".format(doctype)) #nosec
def test_grant_leaves(self):
@@ -54,8 +54,8 @@
self.assertEqual(leave_alloc_doc.new_leaves_allocated, 10)
self.assertEqual(leave_alloc_doc.leave_type, "_Test Leave Type")
- self.assertEqual(leave_alloc_doc.from_date, leave_period.from_date)
- self.assertEqual(leave_alloc_doc.to_date, leave_period.to_date)
+ self.assertEqual(getdate(leave_alloc_doc.from_date), getdate(leave_period.from_date))
+ self.assertEqual(getdate(leave_alloc_doc.to_date), getdate(leave_period.to_date))
self.assertEqual(leave_alloc_doc.leave_policy, leave_policy.name)
self.assertEqual(leave_alloc_doc.leave_policy_assignment, leave_policy_assignments[0])
@@ -101,6 +101,56 @@
# User are now allowed to grant leave
self.assertEqual(leave_policy_assignment_doc.leaves_allocated, 0)
+ def test_earned_leave_allocation(self):
+ leave_period = create_leave_period("Test Earned Leave Period")
+ employee = get_employee()
+ leave_type = create_earned_leave_type("Test Earned Leave")
+
+ leave_policy = frappe.get_doc({
+ "doctype": "Leave Policy",
+ "title": "Test Leave Policy",
+ "leave_policy_details": [{"leave_type": leave_type.name, "annual_allocation": 6}]
+ }).insert()
+
+ data = {
+ "assignment_based_on": "Leave Period",
+ "leave_policy": leave_policy.name,
+ "leave_period": leave_period.name
+ }
+ leave_policy_assignments = create_assignment_for_multiple_employees([employee.name], frappe._dict(data))
+
+ # leaves allocated should be 0 since it is an earned leave and allocation happens via scheduler based on set frequency
+ leaves_allocated = frappe.db.get_value("Leave Allocation", {
+ "leave_policy_assignment": leave_policy_assignments[0]
+ }, "total_leaves_allocated")
+ self.assertEqual(leaves_allocated, 0)
+
def tearDown(self):
- for doctype in ["Leave Application", "Leave Allocation", "Leave Policy Assignment", "Leave Ledger Entry"]:
- frappe.db.sql("delete from `tab{0}`".format(doctype)) #nosec
+ frappe.db.rollback()
+
+
+def create_earned_leave_type(leave_type):
+ frappe.delete_doc_if_exists("Leave Type", leave_type, force=1)
+
+ return frappe.get_doc(dict(
+ leave_type_name=leave_type,
+ doctype="Leave Type",
+ is_earned_leave=1,
+ earned_leave_frequency="Monthly",
+ rounding=0.5,
+ max_leaves_allowed=6
+ )).insert()
+
+
+def create_leave_period(name):
+ frappe.delete_doc_if_exists("Leave Period", name, force=1)
+ start_date = get_first_day(getdate())
+
+ return frappe.get_doc(dict(
+ name=name,
+ doctype="Leave Period",
+ from_date=start_date,
+ to_date=add_months(start_date, 12),
+ company="_Test Company",
+ is_active=1
+ )).insert()
\ No newline at end of file
diff --git a/erpnext/hr/doctype/training_feedback/training_feedback.json b/erpnext/hr/doctype/training_feedback/training_feedback.json
index cd967d5..ebf5a50 100644
--- a/erpnext/hr/doctype/training_feedback/training_feedback.json
+++ b/erpnext/hr/doctype/training_feedback/training_feedback.json
@@ -1,443 +1,144 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "HR-TRF-.YYYY.-.#####",
- "beta": 0,
- "creation": "2016-08-08 06:35:34.158568",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
+ "actions": [],
+ "autoname": "HR-TRF-.YYYY.-.#####",
+ "creation": "2016-08-08 06:35:34.158568",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "employee",
+ "employee_name",
+ "department",
+ "course",
+ "column_break_3",
+ "training_event",
+ "event_name",
+ "trainer_name",
+ "section_break_6",
+ "feedback",
+ "amended_from"
+ ],
"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": 1,
- "in_list_view": 0,
- "in_standard_filter": 1,
- "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_global_search": 1,
+ "in_standard_filter": 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,
- "fetch_from": "employee.employee_name",
- "fieldname": "employee_name",
- "fieldtype": "Read Only",
- "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": "Employee Name",
- "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
- },
+ "fetch_from": "employee.employee_name",
+ "fieldname": "employee_name",
+ "fieldtype": "Read Only",
+ "in_global_search": 1,
+ "label": "Employee Name"
+ },
{
- "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": "training_event.course",
- "fieldname": "course",
- "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": "Course",
- "length": 0,
- "no_copy": 0,
- "options": "Course",
- "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": "training_event.course",
+ "fieldname": "course",
+ "fieldtype": "Link",
+ "label": "Course",
+ "options": "Course",
+ "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_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
- },
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "training_event",
- "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": "Training Event",
- "length": 0,
- "no_copy": 0,
- "options": "Training Event",
- "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": "training_event",
+ "fieldtype": "Link",
+ "in_standard_filter": 1,
+ "label": "Training Event",
+ "options": "Training Event",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "training_event.event_name",
- "fieldname": "event_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": "Event 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": "training_event.event_name",
+ "fieldname": "event_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Event 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": "training_event.trainer_name",
- "fieldname": "trainer_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": "Trainer 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": "training_event.trainer_name",
+ "fieldname": "trainer_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Trainer Name",
+ "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_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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "section_break_6",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "feedback",
- "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": "Feedback",
- "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": "feedback",
+ "fieldtype": "Text",
+ "label": "Feedback",
+ "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": "Training Feedback",
- "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": "Training Feedback",
+ "print_hide": 1,
+ "read_only": 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": "2019-01-30 11:28:13.849860",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Training Feedback",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2022-01-18 19:32:20.805277",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Training Feedback",
+ "naming_rule": "Expression (old style)",
+ "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": 1,
- "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": 1,
+ "create": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Employee",
+ "share": 1,
+ "submit": 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": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "search_fields": "employee_name, training_event, event_name",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "states": [],
+ "title_field": "employee_name"
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/training_result/training_result.json b/erpnext/hr/doctype/training_result/training_result.json
index dd7abd7..f28669e 100644
--- a/erpnext/hr/doctype/training_result/training_result.json
+++ b/erpnext/hr/doctype/training_result/training_result.json
@@ -1,226 +1,83 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 1,
- "autoname": "HR-TRR-.YYYY.-.#####",
- "beta": 0,
- "creation": "2016-11-04 02:13:48.407576",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_rename": 1,
+ "autoname": "HR-TRR-.YYYY.-.#####",
+ "creation": "2016-11-04 02:13:48.407576",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "training_event",
+ "section_break_3",
+ "employees",
+ "amended_from",
+ "employee_emails"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "training_event",
- "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": "Training Event",
- "length": 0,
- "no_copy": 0,
- "options": "Training Event",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "fieldname": "training_event",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Training Event",
+ "options": "Training Event",
+ "reqd": 1,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_3",
- "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_3",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "employees",
- "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": "Employees",
- "length": 0,
- "no_copy": 0,
- "options": "Training Result 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": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "employees",
+ "fieldtype": "Table",
+ "label": "Employees",
+ "options": "Training Result Employee"
+ },
{
- "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": "Training Result",
- "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": "Training Result",
+ "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": "employee_emails",
- "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": "Employee Emails",
- "length": 0,
- "no_copy": 0,
- "options": "Email",
- "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": "employee_emails",
+ "fieldtype": "Small Text",
+ "hidden": 1,
+ "label": "Employee Emails",
+ "options": "Email"
}
- ],
- "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:47.614563",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Training Result",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2022-01-18 19:31:44.900034",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Training Result",
+ "naming_rule": "Expression (old style)",
+ "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
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "training_event",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "search_fields": "training_event",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "states": [],
+ "title_field": "training_event"
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/travel_request/travel_request.json b/erpnext/hr/doctype/travel_request/travel_request.json
index 441907c..7908e1a 100644
--- a/erpnext/hr/doctype/travel_request/travel_request.json
+++ b/erpnext/hr/doctype/travel_request/travel_request.json
@@ -216,10 +216,11 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2019-12-12 18:42:26.451359",
+ "modified": "2022-01-18 19:19:33.678664",
"modified_by": "Administrator",
"module": "HR",
"name": "Travel Request",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -235,7 +236,10 @@
"write": 1
}
],
+ "search_fields": "employee_name",
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
+ "title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/hr/workspace/hr/hr.json b/erpnext/hr/workspace/hr/hr.json
index 85e641c..30cec1b 100644
--- a/erpnext/hr/workspace/hr/hr.json
+++ b/erpnext/hr/workspace/hr/hr.json
@@ -5,7 +5,7 @@
"label": "Outgoing Salary"
}
],
- "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Human Resource\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Outgoing Salary\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Employee\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Leave Application\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Attendance\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Job Applicant\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Monthly Attendance Sheet\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":4}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Employee\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Employee Lifecycle\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Employee Exit\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Shift Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Leaves\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Attendance\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Expense Claims\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Loans\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Recruitment\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Performance\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Fleet Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Training\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]",
+ "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Human Resource\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Outgoing Salary\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Employee\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Leave Application\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Attendance\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Job Applicant\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Monthly Attendance Sheet\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Employee\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Employee Lifecycle\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Employee Exit\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Shift Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Leaves\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Attendance\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Expense Claims\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Loans\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Recruitment\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Performance\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Fleet Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Training\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]",
"creation": "2020-03-02 15:48:58.322521",
"docstatus": 0,
"doctype": "Workspace",
@@ -1642,7 +1642,7 @@
"type": "Link"
}
],
- "modified": "2021-12-05 22:05:13.004462",
+ "modified": "2022-01-13 17:38:45.489128",
"modified_by": "Administrator",
"module": "HR",
"name": "HR",
@@ -1651,7 +1651,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 14,
+ "sequence_id": 14.0,
"shortcuts": [
{
"color": "Green",
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
index 6479853..93ef217 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
@@ -13,8 +13,10 @@
"column_break_3",
"company",
"posting_date",
- "is_term_loan",
"rate_of_interest",
+ "payroll_payable_account",
+ "is_term_loan",
+ "repay_from_salary",
"payment_details_section",
"due_date",
"pending_principal_amount",
@@ -243,15 +245,31 @@
"label": "Total Penalty Paid",
"options": "Company:company:default_currency",
"read_only": 1
+ },
+ {
+ "depends_on": "eval:doc.repay_from_salary",
+ "fieldname": "payroll_payable_account",
+ "fieldtype": "Link",
+ "label": "Payroll Payable Account",
+ "mandatory_depends_on": "eval:doc.repay_from_salary",
+ "options": "Account"
+ },
+ {
+ "default": "0",
+ "fetch_from": "against_loan.repay_from_salary",
+ "fieldname": "repay_from_salary",
+ "fieldtype": "Check",
+ "label": "Repay From Salary"
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-04-19 18:10:00.935364",
+ "modified": "2022-01-06 01:51:06.707782",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan Repayment",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -287,5 +305,6 @@
],
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index 2abb395..7e997e8 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -320,74 +320,79 @@
else:
remarks = _("Repayment against Loan: ") + self.against_loan
- if not loan_details.repay_from_salary:
- if self.total_penalty_paid:
- gle_map.append(
- self.get_gl_dict({
- "account": loan_details.loan_account,
- "against": loan_details.payment_account,
- "debit": self.total_penalty_paid,
- "debit_in_account_currency": self.total_penalty_paid,
- "against_voucher_type": "Loan",
- "against_voucher": self.against_loan,
- "remarks": _("Penalty against loan:") + self.against_loan,
- "cost_center": self.cost_center,
- "party_type": self.applicant_type,
- "party": self.applicant,
- "posting_date": getdate(self.posting_date)
- })
- )
+ if self.repay_from_salary:
+ payment_account = self.payroll_payable_account
+ else:
+ payment_account = loan_details.payment_account
- gle_map.append(
- self.get_gl_dict({
- "account": loan_details.penalty_income_account,
- "against": loan_details.payment_account,
- "credit": self.total_penalty_paid,
- "credit_in_account_currency": self.total_penalty_paid,
- "against_voucher_type": "Loan",
- "against_voucher": self.against_loan,
- "remarks": _("Penalty against loan:") + self.against_loan,
- "cost_center": self.cost_center,
- "posting_date": getdate(self.posting_date)
- })
- )
-
- gle_map.append(
- self.get_gl_dict({
- "account": loan_details.payment_account,
- "against": loan_details.loan_account + ", " + loan_details.interest_income_account
- + ", " + loan_details.penalty_income_account,
- "debit": self.amount_paid,
- "debit_in_account_currency": self.amount_paid,
- "against_voucher_type": "Loan",
- "against_voucher": self.against_loan,
- "remarks": remarks,
- "cost_center": self.cost_center,
- "posting_date": getdate(self.posting_date)
- })
- )
-
+ if self.total_penalty_paid:
gle_map.append(
self.get_gl_dict({
"account": loan_details.loan_account,
- "party_type": loan_details.applicant_type,
- "party": loan_details.applicant,
"against": loan_details.payment_account,
- "credit": self.amount_paid,
- "credit_in_account_currency": self.amount_paid,
+ "debit": self.total_penalty_paid,
+ "debit_in_account_currency": self.total_penalty_paid,
"against_voucher_type": "Loan",
"against_voucher": self.against_loan,
- "remarks": remarks,
+ "remarks": _("Penalty against loan:") + self.against_loan,
+ "cost_center": self.cost_center,
+ "party_type": self.applicant_type,
+ "party": self.applicant,
+ "posting_date": getdate(self.posting_date)
+ })
+ )
+
+ gle_map.append(
+ self.get_gl_dict({
+ "account": loan_details.penalty_income_account,
+ "against": payment_account,
+ "credit": self.total_penalty_paid,
+ "credit_in_account_currency": self.total_penalty_paid,
+ "against_voucher_type": "Loan",
+ "against_voucher": self.against_loan,
+ "remarks": _("Penalty against loan:") + self.against_loan,
"cost_center": self.cost_center,
"posting_date": getdate(self.posting_date)
})
)
- if gle_map:
- make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj, merge_entries=False)
+ gle_map.append(
+ self.get_gl_dict({
+ "account": payment_account,
+ "against": loan_details.loan_account + ", " + loan_details.interest_income_account
+ + ", " + loan_details.penalty_income_account,
+ "debit": self.amount_paid,
+ "debit_in_account_currency": self.amount_paid,
+ "against_voucher_type": "Loan",
+ "against_voucher": self.against_loan,
+ "remarks": remarks,
+ "cost_center": self.cost_center,
+ "posting_date": getdate(self.posting_date)
+ })
+ )
+
+ gle_map.append(
+ self.get_gl_dict({
+ "account": loan_details.loan_account,
+ "party_type": loan_details.applicant_type,
+ "party": loan_details.applicant,
+ "against": payment_account,
+ "credit": self.amount_paid,
+ "credit_in_account_currency": self.amount_paid,
+ "against_voucher_type": "Loan",
+ "against_voucher": self.against_loan,
+ "remarks": remarks,
+ "cost_center": self.cost_center,
+ "posting_date": getdate(self.posting_date)
+ })
+ )
+
+ if gle_map:
+ make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj, merge_entries=False)
def create_repayment_entry(loan, applicant, company, posting_date, loan_type,
- payment_type, interest_payable, payable_principal_amount, amount_paid, penalty_amount=None):
+ payment_type, interest_payable, payable_principal_amount, amount_paid, penalty_amount=None,
+ payroll_payable_account=None):
lr = frappe.get_doc({
"doctype": "Loan Repayment",
@@ -400,7 +405,8 @@
"interest_payable": interest_payable,
"payable_principal_amount": payable_principal_amount,
"amount_paid": amount_paid,
- "loan_type": loan_type
+ "loan_type": loan_type,
+ "payroll_payable_account": payroll_payable_account
}).insert()
return lr
diff --git a/erpnext/loan_management/workspace/loan_management/loan_management.json b/erpnext/loan_management/workspace/loan_management/loan_management.json
index 7deee0d..b08a85e 100644
--- a/erpnext/loan_management/workspace/loan_management/loan_management.json
+++ b/erpnext/loan_management/workspace/loan_management/loan_management.json
@@ -1,6 +1,6 @@
{
"charts": [],
- "content": "[{\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Loan Application\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Loan\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Dashboard\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Loan\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Loan Processes\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Disbursement and Repayment\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Loan Security\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Reports\", \"col\": 4}}]",
+ "content": "[{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Loan Application\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Loan\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Loan\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Loan Processes\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Disbursement and Repayment\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Loan Security\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]",
"creation": "2020-03-12 16:35:55.299820",
"docstatus": 0,
"doctype": "Workspace",
@@ -238,7 +238,7 @@
"type": "Link"
}
],
- "modified": "2021-08-05 12:18:13.350905",
+ "modified": "2022-01-13 17:39:16.790152",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loans",
@@ -247,7 +247,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 16,
+ "sequence_id": 16.0,
"shortcuts": [
{
"color": "Green",
diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
index 2ffae1a..07d928c 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
+++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
@@ -1,7 +1,6 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
-
import frappe
from frappe import _, throw
from frappe.utils import add_days, cint, cstr, date_diff, formatdate, getdate
@@ -306,13 +305,18 @@
return schedule.name
@frappe.whitelist()
-def update_serial_nos(s_id):
- serial_nos = frappe.db.get_value('Maintenance Schedule Detail', s_id, 'serial_no')
+def get_serial_nos_from_schedule(item_code, schedule=None):
+ serial_nos = []
+ if schedule:
+ serial_nos = frappe.db.get_value('Maintenance Schedule Item', {
+ 'parent': schedule,
+ 'item_code': item_code
+ }, 'serial_no')
+
if serial_nos:
serial_nos = get_serial_nos(serial_nos)
- return serial_nos
- else:
- return False
+
+ return serial_nos
@frappe.whitelist()
def make_maintenance_visit(source_name, target_doc=None, item_name=None, s_id=None):
@@ -320,12 +324,9 @@
def update_status_and_detail(source, target, parent):
target.maintenance_type = "Scheduled"
- target.maintenance_schedule = source.name
target.maintenance_schedule_detail = s_id
- def update_sales_and_serial(source, target, parent):
- sales_person = frappe.db.get_value('Maintenance Schedule Detail', s_id, 'sales_person')
- target.service_person = sales_person
+ def update_serial(source, target, parent):
serial_nos = get_serial_nos(target.serial_no)
if len(serial_nos) == 1:
target.serial_no = serial_nos[0]
@@ -346,7 +347,10 @@
"Maintenance Schedule Item": {
"doctype": "Maintenance Visit Purpose",
"condition": lambda doc: doc.item_name == item_name,
- "postprocess": update_sales_and_serial
+ "field_map": {
+ "sales_person": "service_person"
+ },
+ "postprocess": update_serial
}
}, target_doc)
diff --git a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py
index 5017126..6e727e5 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py
+++ b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py
@@ -4,11 +4,15 @@
import unittest
import frappe
+from frappe.utils import format_date
from frappe.utils.data import add_days, formatdate, today
from erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule import (
+ get_serial_nos_from_schedule,
make_maintenance_visit,
)
+from erpnext.stock.doctype.item.test_item import create_item
+from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
# test_records = frappe.get_test_records('Maintenance Schedule')
@@ -79,6 +83,49 @@
#checks if visit status is back updated in schedule
self.assertTrue(ms.schedules[1].completion_status, "Partially Completed")
+ self.assertEqual(format_date(visit.mntc_date), format_date(ms.schedules[1].actual_date))
+
+ #checks if visit status is updated on cancel
+ visit.cancel()
+ ms.reload()
+ self.assertTrue(ms.schedules[1].completion_status, "Pending")
+ self.assertEqual(ms.schedules[1].actual_date, None)
+
+ def test_serial_no_filters(self):
+ # Without serial no. set in schedule -> returns None
+ item_code = "_Test Serial Item"
+ make_serial_item_with_serial(item_code)
+ ms = make_maintenance_schedule(item_code=item_code)
+ ms.submit()
+
+ s_item = ms.schedules[0]
+ mv = make_maintenance_visit(source_name=ms.name, item_name=item_code, s_id=s_item.name)
+ mvi = mv.purposes[0]
+ serial_nos = get_serial_nos_from_schedule(mvi.item_name, ms.name)
+ self.assertEqual(serial_nos, None)
+
+ # With serial no. set in schedule -> returns serial nos.
+ make_serial_item_with_serial(item_code)
+ ms = make_maintenance_schedule(item_code=item_code, serial_no="TEST001, TEST002")
+ ms.submit()
+
+ s_item = ms.schedules[0]
+ mv = make_maintenance_visit(source_name=ms.name, item_name=item_code, s_id=s_item.name)
+ mvi = mv.purposes[0]
+ serial_nos = get_serial_nos_from_schedule(mvi.item_name, ms.name)
+ self.assertEqual(serial_nos, ["TEST001", "TEST002"])
+
+ frappe.db.rollback()
+
+def make_serial_item_with_serial(item_code):
+ serial_item_doc = create_item(item_code, is_stock_item=1)
+ if not serial_item_doc.has_serial_no or not serial_item_doc.serial_no_series:
+ serial_item_doc.has_serial_no = 1
+ serial_item_doc.serial_no_series = "TEST.###"
+ serial_item_doc.save(ignore_permissions=True)
+ active_serials = frappe.db.get_all('Serial No', {"status": "Active", "item_code": item_code})
+ if len(active_serials) < 2:
+ make_serialized_item(item_code=item_code)
def get_events(ms):
return frappe.get_all("Event Participants", filters={
@@ -87,17 +134,18 @@
"parenttype": "Event"
})
-def make_maintenance_schedule():
+def make_maintenance_schedule(**args):
ms = frappe.new_doc("Maintenance Schedule")
ms.company = "_Test Company"
ms.customer = "_Test Customer"
ms.transaction_date = today()
ms.append("items", {
- "item_code": "_Test Item",
+ "item_code": args.get("item_code") or "_Test Item",
"start_date": today(),
"periodicity": "Weekly",
"no_of_visits": 4,
+ "serial_no": args.get("serial_no"),
"sales_person": "Sales Team",
})
ms.insert(ignore_permissions=True)
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
index d2197a6..72686e7 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
@@ -2,52 +2,54 @@
// License: GNU General Public License v3. See license.txt
frappe.provide("erpnext.maintenance");
-var serial_nos = [];
frappe.ui.form.on('Maintenance Visit', {
- refresh: function (frm) {
- //filters for serial_no based on item_code
- frm.set_query('serial_no', 'purposes', function (frm, cdt, cdn) {
- let item = locals[cdt][cdn];
- if (serial_nos) {
- return {
- filters: {
- 'item_code': item.item_code,
- 'name': ["in", serial_nos]
- }
- };
- } else {
- return {
- filters: {
- 'item_code': item.item_code
- }
- };
- }
- });
- },
setup: function (frm) {
frm.set_query('contact_person', erpnext.queries.contact_query);
frm.set_query('customer_address', erpnext.queries.address_query);
frm.set_query('customer', erpnext.queries.customer);
},
- onload: function (frm, cdt, cdn) {
- let item = locals[cdt][cdn];
+ onload: function (frm) {
+ // filters for serial no based on item code
if (frm.doc.maintenance_type === "Scheduled") {
- const schedule_id = item.purposes[0].prevdoc_detail_docname || frm.doc.maintenance_schedule_detail;
+ let item_code = frm.doc.purposes[0].item_code;
frappe.call({
- method: "erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule.update_serial_nos",
+ method: "erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule.get_serial_nos_from_schedule",
args: {
- s_id: schedule_id
- },
- callback: function (r) {
- serial_nos = r.message;
+ schedule: frm.doc.maintenance_schedule,
+ item_code: item_code
}
+ }).then((r) => {
+ let serial_nos = r.message;
+ frm.set_query('serial_no', 'purposes', () => {
+ if (serial_nos.length > 0) {
+ return {
+ filters: {
+ 'item_code': item_code,
+ 'name': ["in", serial_nos]
+ }
+ };
+ }
+ return {
+ filters: {
+ 'item_code': item_code
+ }
+ };
+ });
+ });
+ } else {
+ frm.set_query('serial_no', 'purposes', (frm, cdt, cdn) => {
+ let row = locals[cdt][cdn];
+ return {
+ filters: {
+ 'item_code': row.item_code
+ }
+ };
});
}
if (!frm.doc.status) {
frm.set_value({ status: 'Draft' });
}
if (frm.doc.__islocal) {
- frm.doc.maintenance_type == 'Unscheduled' && frm.clear_table("purposes");
frm.set_value({ mntc_date: frappe.datetime.get_today() });
}
},
@@ -60,7 +62,6 @@
contact_person: function (frm) {
erpnext.utils.get_contact_details(frm);
}
-
})
// TODO commonify this code
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.json b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.json
index ec32239..4a6aa0a 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.json
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.json
@@ -179,8 +179,7 @@
"label": "Purposes",
"oldfieldname": "maintenance_visit_details",
"oldfieldtype": "Table",
- "options": "Maintenance Visit Purpose",
- "reqd": 1
+ "options": "Maintenance Visit Purpose"
},
{
"fieldname": "more_info",
@@ -294,10 +293,11 @@
"idx": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-05-27 16:06:17.352572",
+ "modified": "2021-12-17 03:10:27.608112",
"modified_by": "Administrator",
"module": "Maintenance",
"name": "Maintenance Visit",
+ "naming_rule": "By \"Naming Series\" field",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
index 5a87b16..6fe2466 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
@@ -4,7 +4,7 @@
import frappe
from frappe import _
-from frappe.utils import get_datetime
+from frappe.utils import format_date, get_datetime
from erpnext.utilities.transaction_base import TransactionBase
@@ -18,25 +18,34 @@
if d.serial_no and not frappe.db.exists("Serial No", d.serial_no):
frappe.throw(_("Serial No {0} does not exist").format(d.serial_no))
+ def validate_purpose_table(self):
+ if not self.purposes:
+ frappe.throw(_("Add Items in the Purpose Table"), title="Purposes Required")
+
def validate_maintenance_date(self):
if self.maintenance_type == "Scheduled" and self.maintenance_schedule_detail:
item_ref = frappe.db.get_value('Maintenance Schedule Detail', self.maintenance_schedule_detail, 'item_reference')
if item_ref:
start_date, end_date = frappe.db.get_value('Maintenance Schedule Item', item_ref, ['start_date', 'end_date'])
if get_datetime(self.mntc_date) < get_datetime(start_date) or get_datetime(self.mntc_date) > get_datetime(end_date):
- frappe.throw(_("Date must be between {0} and {1}").format(start_date, end_date))
+ frappe.throw(_("Date must be between {0} and {1}")
+ .format(format_date(start_date), format_date(end_date)))
+
def validate(self):
self.validate_serial_no()
self.validate_maintenance_date()
+ self.validate_purpose_table()
- def update_completion_status(self):
+ def update_status_and_actual_date(self, cancel=False):
+ status = "Pending"
+ actual_date = None
+ if not cancel:
+ status = self.completion_status
+ actual_date = self.mntc_date
if self.maintenance_schedule_detail:
- frappe.db.set_value('Maintenance Schedule Detail', self.maintenance_schedule_detail, 'completion_status', self.completion_status)
-
- def update_actual_date(self):
- if self.maintenance_schedule_detail:
- frappe.db.set_value('Maintenance Schedule Detail', self.maintenance_schedule_detail, 'actual_date', self.mntc_date)
+ frappe.db.set_value('Maintenance Schedule Detail', self.maintenance_schedule_detail, 'completion_status', status)
+ frappe.db.set_value('Maintenance Schedule Detail', self.maintenance_schedule_detail, 'actual_date', actual_date)
def update_customer_issue(self, flag):
if not self.maintenance_schedule:
@@ -97,12 +106,12 @@
def on_submit(self):
self.update_customer_issue(1)
frappe.db.set(self, 'status', 'Submitted')
- self.update_completion_status()
- self.update_actual_date()
+ self.update_status_and_actual_date()
def on_cancel(self):
self.check_if_last_visit()
frappe.db.set(self, 'status', 'Cancelled')
+ self.update_status_and_actual_date(cancel=True)
def on_update(self):
pass
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index f82d9a0..5a60fb7 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -530,16 +530,6 @@
row.hour_rate = (hour_rate / flt(self.conversion_rate)
if self.conversion_rate and hour_rate else hour_rate)
- if self.routing:
- time_in_mins = flt(frappe.db.get_value("BOM Operation", {
- "workstation": row.workstation,
- "operation": row.operation,
- "parent": self.routing
- }, ["time_in_mins"]))
-
- if time_in_mins:
- row.time_in_mins = time_in_mins
-
if row.hour_rate and row.time_in_mins:
row.base_hour_rate = flt(row.hour_rate) * flt(self.conversion_rate)
row.operating_cost = flt(row.hour_rate) * flt(row.time_in_mins) / 60.0
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 7cec7f5..8b1dbd0 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -947,11 +947,8 @@
locations = get_available_item_locations(item.get("item_code"),
warehouses, item.get("quantity"), company, ignore_validation=True)
- if not locations:
- new_mr_items.append(item)
- return
-
required_qty = item.get("quantity")
+ # get available material by transferring to production warehouse
for d in locations:
if required_qty <=0: return
@@ -962,14 +959,34 @@
new_dict.update({
"quantity": quantity,
"material_request_type": "Material Transfer",
+ "uom": new_dict.get("stock_uom"), # internal transfer should be in stock UOM
"from_warehouse": d.get("warehouse")
})
required_qty -= quantity
new_mr_items.append(new_dict)
+ # raise purchase request for remaining qty
if required_qty:
+ stock_uom, purchase_uom = frappe.db.get_value(
+ 'Item',
+ item['item_code'],
+ ['stock_uom', 'purchase_uom']
+ )
+
+ if purchase_uom != stock_uom and purchase_uom == item['uom']:
+ conversion_factor = get_uom_conversion_factor(item['item_code'], item['uom'])
+ if not (conversion_factor or frappe.flags.show_qty_in_stock_uom):
+ frappe.throw(_("UOM Conversion factor ({0} -> {1}) not found for item: {2}")
+ .format(purchase_uom, stock_uom, item['item_code']))
+
+ required_qty = required_qty / conversion_factor
+
+ if frappe.db.get_value("UOM", purchase_uom, "must_be_whole_number"):
+ required_qty = ceil(required_qty)
+
item["quantity"] = required_qty
+
new_mr_items.append(item)
@frappe.whitelist()
diff --git a/erpnext/manufacturing/doctype/routing/test_routing.py b/erpnext/manufacturing/doctype/routing/test_routing.py
index e90b0a7..8bd60ea 100644
--- a/erpnext/manufacturing/doctype/routing/test_routing.py
+++ b/erpnext/manufacturing/doctype/routing/test_routing.py
@@ -46,6 +46,7 @@
wo_doc.delete()
def test_update_bom_operation_time(self):
+ """Update cost shouldn't update routing times."""
operations = [
{
"operation": "Test Operation A",
@@ -85,8 +86,8 @@
routing_doc.save()
bom_doc.update_cost()
bom_doc.reload()
- self.assertEqual(bom_doc.operations[0].time_in_mins, 90)
- self.assertEqual(bom_doc.operations[1].time_in_mins, 42.2)
+ self.assertEqual(bom_doc.operations[0].time_in_mins, 30)
+ self.assertEqual(bom_doc.operations[1].time_in_mins, 20)
def setup_operations(rows):
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index 9926b15..e7eb9c6 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -2,7 +2,7 @@
# License: GNU General Public License v3. See license.txt
import frappe
-from frappe.utils import add_months, cint, flt, now, today
+from frappe.utils import add_days, add_months, cint, flt, now, today
from erpnext.manufacturing.doctype.job_card.job_card import JobCardCancelError
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
@@ -12,6 +12,7 @@
OverProductionError,
StockOverProductionError,
close_work_order,
+ make_job_card,
make_stock_entry,
stop_unstop,
)
@@ -804,6 +805,34 @@
if row.is_scrap_item:
self.assertEqual(row.qty, 1)
+ # Partial Job Card 1 with qty 10
+ wo_order = make_wo_order_test_record(item=item, company=company, planned_start_date=add_days(now(), 60), qty=20, skip_transfer=1)
+ job_card = frappe.db.get_value('Job Card', {'work_order': wo_order.name}, 'name')
+ update_job_card(job_card, 10)
+
+ stock_entry = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 10))
+ for row in stock_entry.items:
+ if row.is_scrap_item:
+ self.assertEqual(row.qty, 2)
+
+ # Partial Job Card 2 with qty 10
+ operations = []
+ wo_order.load_from_db()
+ for row in wo_order.operations:
+ n_dict = row.as_dict()
+ n_dict['qty'] = 10
+ n_dict['pending_qty'] = 10
+ operations.append(n_dict)
+
+ make_job_card(wo_order.name, operations)
+ job_card = frappe.db.get_value('Job Card', {'work_order': wo_order.name, 'docstatus': 0}, 'name')
+ update_job_card(job_card, 10)
+
+ stock_entry = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 10))
+ for row in stock_entry.items:
+ if row.is_scrap_item:
+ self.assertEqual(row.qty, 2)
+
def test_close_work_order(self):
items = ['Test FG Item for Closed WO', 'Test RM Item 1 for Closed WO',
'Test RM Item 2 for Closed WO']
@@ -883,7 +912,8 @@
self.assertEqual(wo1.operations[0].time_in_mins, wo2.operations[0].time_in_mins)
-def update_job_card(job_card):
+def update_job_card(job_card, jc_qty=None):
+ employee = frappe.db.get_value('Employee', {'status': 'Active'}, 'name')
job_card_doc = frappe.get_doc('Job Card', job_card)
job_card_doc.set('scrap_items', [
{
@@ -896,8 +926,12 @@
},
])
+ if jc_qty:
+ job_card_doc.for_quantity = jc_qty
+
job_card_doc.append('time_logs', {
'from_time': now(),
+ 'employee': employee,
'time_in_mins': 60,
'completed_qty': job_card_doc.for_quantity
})
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index 5ffbb03..6433a99 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -131,16 +131,14 @@
erpnext.work_order.set_custom_buttons(frm);
frm.set_intro("");
- if (frm.doc.docstatus === 0 && !frm.doc.__islocal) {
+ if (frm.doc.docstatus === 0 && !frm.is_new()) {
frm.set_intro(__("Submit this Work Order for further processing."));
+ } else {
+ frm.trigger("show_progress_for_items");
+ frm.trigger("show_progress_for_operations");
}
if (frm.doc.status != "Closed") {
- if (frm.doc.docstatus===1) {
- frm.trigger('show_progress_for_items');
- frm.trigger('show_progress_for_operations');
- }
-
if (frm.doc.docstatus === 1
&& frm.doc.operations && frm.doc.operations.length) {
diff --git a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js
index 7468e34..0eb22a2 100644
--- a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js
+++ b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js
@@ -4,6 +4,39 @@
frappe.query_reports["BOM Operations Time"] = {
"filters": [
-
+ {
+ "fieldname": "item_code",
+ "label": __("Item Code"),
+ "fieldtype": "Link",
+ "width": "100",
+ "options": "Item",
+ "get_query": () =>{
+ return {
+ filters: { "disabled": 0, "is_stock_item": 1 }
+ }
+ }
+ },
+ {
+ "fieldname": "bom_id",
+ "label": __("BOM ID"),
+ "fieldtype": "MultiSelectList",
+ "width": "100",
+ "options": "BOM",
+ "get_data": function(txt) {
+ return frappe.db.get_link_options("BOM", txt);
+ },
+ "get_query": () =>{
+ return {
+ filters: { "docstatus": 1, "is_active": 1, "with_operations": 1 }
+ }
+ }
+ },
+ {
+ "fieldname": "workstation",
+ "label": __("Workstation"),
+ "fieldtype": "Link",
+ "width": "100",
+ "options": "Workstation"
+ },
]
};
diff --git a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.json b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.json
index 665c5b9..8162017 100644
--- a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.json
+++ b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.json
@@ -1,14 +1,16 @@
{
- "add_total_row": 0,
+ "add_total_row": 1,
+ "columns": [],
"creation": "2020-03-03 01:41:20.862521",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
+ "filters": [],
"idx": 0,
"is_standard": "Yes",
"letter_head": "",
- "modified": "2020-03-03 01:41:20.862521",
+ "modified": "2022-01-20 14:21:47.771591",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Operations Time",
diff --git a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py
index e7a818a..eda9eb9 100644
--- a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py
+++ b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.py
@@ -12,19 +12,15 @@
return columns, data
def get_data(filters):
- data = []
+ bom_wise_data = {}
+ bom_data, report_data = [], []
- bom_data = []
- for d in frappe.db.sql("""
- SELECT
- bom.name, bom.item, bom.item_name, bom.uom,
- bomps.operation, bomps.workstation, bomps.time_in_mins
- FROM `tabBOM` bom, `tabBOM Operation` bomps
- WHERE
- bom.docstatus = 1 and bom.is_active = 1 and bom.name = bomps.parent
- """, as_dict=1):
+ bom_operation_data = get_filtered_data(filters)
+
+ for d in bom_operation_data:
row = get_args()
if d.name not in bom_data:
+ bom_wise_data[d.name] = []
bom_data.append(d.name)
row.update(d)
else:
@@ -34,14 +30,49 @@
"time_in_mins": d.time_in_mins
})
- data.append(row)
+ # maintain BOM wise data for grouping such as:
+ # {"BOM A": [{Row1}, {Row2}], "BOM B": ...}
+ bom_wise_data[d.name].append(row)
used_as_subassembly_items = get_bom_count(bom_data)
- for d in data:
- d.used_as_subassembly_items = used_as_subassembly_items.get(d.name, 0)
+ for d in bom_wise_data:
+ for row in bom_wise_data[d]:
+ row.used_as_subassembly_items = used_as_subassembly_items.get(row.name, 0)
+ report_data.append(row)
- return data
+ return report_data
+
+def get_filtered_data(filters):
+ bom = frappe.qb.DocType("BOM")
+ bom_ops = frappe.qb.DocType("BOM Operation")
+
+ bom_ops_query = (
+ frappe.qb.from_(bom)
+ .join(bom_ops).on(bom.name == bom_ops.parent)
+ .select(
+ bom.name, bom.item, bom.item_name, bom.uom,
+ bom_ops.operation, bom_ops.workstation, bom_ops.time_in_mins
+ ).where(
+ (bom.docstatus == 1)
+ & (bom.is_active == 1)
+ )
+ )
+
+ if filters.get("item_code"):
+ bom_ops_query = bom_ops_query.where(bom.item == filters.get("item_code"))
+
+ if filters.get("bom_id"):
+ bom_ops_query = bom_ops_query.where(bom.name.isin(filters.get("bom_id")))
+
+ if filters.get("workstation"):
+ bom_ops_query = bom_ops_query.where(
+ bom_ops.workstation == filters.get("workstation")
+ )
+
+ bom_operation_data = bom_ops_query.run(as_dict=True)
+
+ return bom_operation_data
def get_bom_count(bom_data):
data = frappe.get_all("BOM Item",
@@ -68,13 +99,13 @@
"options": "BOM",
"fieldname": "name",
"fieldtype": "Link",
- "width": 140
+ "width": 220
}, {
- "label": _("BOM Item Code"),
+ "label": _("Item Code"),
"options": "Item",
"fieldname": "item",
"fieldtype": "Link",
- "width": 140
+ "width": 150
}, {
"label": _("Item Name"),
"fieldname": "item_name",
@@ -85,13 +116,13 @@
"options": "UOM",
"fieldname": "uom",
"fieldtype": "Link",
- "width": 140
+ "width": 100
}, {
"label": _("Operation"),
"options": "Operation",
"fieldname": "operation",
"fieldtype": "Link",
- "width": 120
+ "width": 140
}, {
"label": _("Workstation"),
"options": "Workstation",
@@ -101,11 +132,11 @@
}, {
"label": _("Time (In Mins)"),
"fieldname": "time_in_mins",
- "fieldtype": "Int",
- "width": 140
+ "fieldtype": "Float",
+ "width": 120
}, {
"label": _("Sub-assembly BOM Count"),
"fieldname": "used_as_subassembly_items",
"fieldtype": "Int",
- "width": 180
+ "width": 200
}]
diff --git a/erpnext/manufacturing/workspace/manufacturing/manufacturing.json b/erpnext/manufacturing/workspace/manufacturing/manufacturing.json
index 65b4d02..05ca2a8 100644
--- a/erpnext/manufacturing/workspace/manufacturing/manufacturing.json
+++ b/erpnext/manufacturing/workspace/manufacturing/manufacturing.json
@@ -1,6 +1,6 @@
{
"charts": [],
- "content": "[{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Work Order\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Plan\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Forecasting\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Work Order Summary\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM Stock Report\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Planning Report\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":4}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Production\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Bill of Materials\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
+ "content": "[{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Work Order\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Plan\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Forecasting\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Work Order Summary\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM Stock Report\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Planning Report\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Production\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Bill of Materials\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
"creation": "2020-03-02 17:11:37.032604",
"docstatus": 0,
"doctype": "Workspace",
@@ -402,7 +402,7 @@
"type": "Link"
}
],
- "modified": "2021-11-22 17:55:03.524496",
+ "modified": "2022-01-13 17:40:09.474747",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Manufacturing",
@@ -411,7 +411,7 @@
"public": 1,
"restrict_to_domain": "Manufacturing",
"roles": [],
- "sequence_id": 17,
+ "sequence_id": 17.0,
"shortcuts": [
{
"color": "Green",
diff --git a/erpnext/modules.txt b/erpnext/modules.txt
index cd1586c..308480b 100644
--- a/erpnext/modules.txt
+++ b/erpnext/modules.txt
@@ -15,11 +15,9 @@
Maintenance
Education
Regional
-Restaurant
ERPNext Integrations
-Hotels
Quality Management
Communication
Loan Management
Payroll
-Telephony
\ No newline at end of file
+Telephony
diff --git a/erpnext/non_profit/workspace/non_profit/non_profit.json b/erpnext/non_profit/workspace/non_profit/non_profit.json
new file mode 100644
index 0000000..fc90475
--- /dev/null
+++ b/erpnext/non_profit/workspace/non_profit/non_profit.json
@@ -0,0 +1,272 @@
+{
+ "charts": [],
+ "content": "[{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Member\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Non Profit Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Membership\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chapter\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chapter Member\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Loan Management\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Grant Application\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Membership\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Volunteer\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Chapter\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Donation\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tax Exemption Certification (India)\",\"col\":4}}]",
+ "creation": "2020-03-02 17:23:47.811421",
+ "docstatus": 0,
+ "doctype": "Workspace",
+ "for_user": "",
+ "hide_custom": 0,
+ "icon": "non-profit",
+ "idx": 0,
+ "label": "Non Profit",
+ "links": [
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Loan Management",
+ "link_count": 0,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Loan Type",
+ "link_count": 0,
+ "link_to": "Loan Type",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Loan Application",
+ "link_count": 0,
+ "link_to": "Loan Application",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Loan",
+ "link_count": 0,
+ "link_to": "Loan",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Grant Application",
+ "link_count": 0,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Grant Application",
+ "link_count": 0,
+ "link_to": "Grant Application",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Membership",
+ "link_count": 0,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Member",
+ "link_count": 0,
+ "link_to": "Member",
+ "link_type": "DocType",
+ "onboard": 1,
+ "type": "Link"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Membership",
+ "link_count": 0,
+ "link_to": "Membership",
+ "link_type": "DocType",
+ "onboard": 1,
+ "type": "Link"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Membership Type",
+ "link_count": 0,
+ "link_to": "Membership Type",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Membership Settings",
+ "link_count": 0,
+ "link_to": "Non Profit Settings",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Volunteer",
+ "link_count": 0,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Volunteer",
+ "link_count": 0,
+ "link_to": "Volunteer",
+ "link_type": "DocType",
+ "onboard": 1,
+ "type": "Link"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Volunteer Type",
+ "link_count": 0,
+ "link_to": "Volunteer Type",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Chapter",
+ "link_count": 0,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Chapter",
+ "link_count": 0,
+ "link_to": "Chapter",
+ "link_type": "DocType",
+ "onboard": 1,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Donation",
+ "link_count": 0,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Donor",
+ "link_count": 0,
+ "link_to": "Donor",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Donor Type",
+ "link_count": 0,
+ "link_to": "Donor Type",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Donation",
+ "link_count": 0,
+ "link_to": "Donation",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Tax Exemption Certification (India)",
+ "link_count": 0,
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Tax Exemption 80G Certificate",
+ "link_count": 0,
+ "link_to": "Tax Exemption 80G Certificate",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ }
+ ],
+ "modified": "2022-01-13 17:40:50.220877",
+ "modified_by": "Administrator",
+ "module": "Non Profit",
+ "name": "Non Profit",
+ "owner": "Administrator",
+ "parent_page": "",
+ "public": 1,
+ "restrict_to_domain": "Non Profit",
+ "roles": [],
+ "sequence_id": 18.0,
+ "shortcuts": [
+ {
+ "label": "Member",
+ "link_to": "Member",
+ "type": "DocType"
+ },
+ {
+ "label": "Non Profit Settings",
+ "link_to": "Non Profit Settings",
+ "type": "DocType"
+ },
+ {
+ "label": "Membership",
+ "link_to": "Membership",
+ "type": "DocType"
+ },
+ {
+ "label": "Chapter",
+ "link_to": "Chapter",
+ "type": "DocType"
+ },
+ {
+ "label": "Chapter Member",
+ "link_to": "Chapter Member",
+ "type": "DocType"
+ }
+ ],
+ "title": "Non Profit"
+}
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 970a8f9..6a26935 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -165,7 +165,6 @@
erpnext.patches.v12_0.set_default_payroll_based_on
erpnext.patches.v12_0.repost_stock_ledger_entries_for_target_warehouse
erpnext.patches.v12_0.update_end_date_and_status_in_email_campaign
-erpnext.patches.v13_0.validate_options_for_data_field
erpnext.patches.v13_0.move_tax_slabs_from_payroll_period_to_income_tax_slab #123
erpnext.patches.v12_0.fix_quotation_expired_status
erpnext.patches.v12_0.rename_pos_closing_doctype
@@ -280,6 +279,7 @@
erpnext.patches.v13_0.update_recipient_email_digest
erpnext.patches.v13_0.shopify_deprecation_warning
erpnext.patches.v13_0.remove_bad_selling_defaults
+erpnext.patches.v13_0.trim_whitespace_from_serial_nos # 16-01-2022
erpnext.patches.v13_0.migrate_stripe_api
erpnext.patches.v13_0.reset_clearance_date_for_intracompany_payment_entries
erpnext.patches.v13_0.einvoicing_deprecation_warning
@@ -305,6 +305,7 @@
erpnext.patches.v13_0.enable_scheduler_job_for_item_reposting
erpnext.patches.v13_0.requeue_failed_reposts
erpnext.patches.v13_0.update_job_card_status
+erpnext.patches.v13_0.enable_uoms
erpnext.patches.v12_0.update_production_plan_status
erpnext.patches.v13_0.healthcare_deprecation_warning
erpnext.patches.v13_0.item_naming_series_not_mandatory
@@ -312,10 +313,12 @@
erpnext.patches.v13_0.update_category_in_ltds_certificate
erpnext.patches.v13_0.create_pan_field_for_india #2
erpnext.patches.v14_0.delete_hub_doctypes
-erpnext.patches.v13_0.create_ksa_vat_custom_fields
+erpnext.patches.v13_0.update_maintenance_schedule_field_in_visit
+erpnext.patches.v13_0.create_ksa_vat_custom_fields # 07-01-2022
erpnext.patches.v14_0.rename_ongoing_status_in_sla_documents
erpnext.patches.v14_0.migrate_crm_settings
erpnext.patches.v13_0.rename_ksa_qr_field
+erpnext.patches.v13_0.wipe_serial_no_field_for_0_qty
erpnext.patches.v13_0.disable_ksa_print_format_for_others # 16-12-2021
erpnext.patches.v14_0.add_default_exit_questionnaire_notification_template
erpnext.patches.v13_0.update_tax_category_for_rcm
@@ -323,5 +326,12 @@
erpnext.patches.v14_0.set_payroll_cost_centers
erpnext.patches.v13_0.agriculture_deprecation_warning
erpnext.patches.v14_0.delete_agriculture_doctypes
+erpnext.patches.v13_0.hospitality_deprecation_warning
+erpnext.patches.v14_0.delete_hospitality_doctypes # 20-01-2022
+erpnext.patches.v13_0.update_exchange_rate_settings
+erpnext.patches.v14_0.rearrange_company_fields
+erpnext.patches.v14_0.update_leave_notification_template
+erpnext.patches.v13_0.update_asset_quantity_field
+erpnext.patches.v13_0.delete_bank_reconciliation_detail
erpnext.patches.v13_0.non_profit_deprecation_warning
erpnext.patches.v14_0.delete_non_profit_doctypes
diff --git a/erpnext/patches/v13_0/delete_bank_reconciliation_detail.py b/erpnext/patches/v13_0/delete_bank_reconciliation_detail.py
new file mode 100644
index 0000000..75953b0
--- /dev/null
+++ b/erpnext/patches/v13_0/delete_bank_reconciliation_detail.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2019, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+
+import frappe
+
+
+def execute():
+
+ if frappe.db.exists('DocType', 'Bank Reconciliation Detail') and \
+ frappe.db.exists('DocType', 'Bank Clearance Detail'):
+
+ frappe.delete_doc("DocType", 'Bank Reconciliation Detail', force=1)
diff --git a/erpnext/patches/v13_0/enable_uoms.py b/erpnext/patches/v13_0/enable_uoms.py
new file mode 100644
index 0000000..4d3f637
--- /dev/null
+++ b/erpnext/patches/v13_0/enable_uoms.py
@@ -0,0 +1,13 @@
+import frappe
+
+
+def execute():
+ frappe.reload_doc('setup', 'doctype', 'uom')
+
+ uom = frappe.qb.DocType("UOM")
+
+ (frappe.qb
+ .update(uom)
+ .set(uom.enabled, 1)
+ .where(uom.creation >= "2021-10-18") # date when this field was released
+ ).run()
diff --git a/erpnext/patches/v13_0/hospitality_deprecation_warning.py b/erpnext/patches/v13_0/hospitality_deprecation_warning.py
new file mode 100644
index 0000000..2708b2c
--- /dev/null
+++ b/erpnext/patches/v13_0/hospitality_deprecation_warning.py
@@ -0,0 +1,10 @@
+import click
+
+
+def execute():
+
+ click.secho(
+ "Hospitality domain is moved to a separate app and will be removed from ERPNext in version-14.\n"
+ "When upgrading to ERPNext version-14, please install the app to continue using the Hospitality domain: https://github.com/frappe/hospitality",
+ fg="yellow",
+ )
diff --git a/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py b/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py
new file mode 100644
index 0000000..4ec22e9
--- /dev/null
+++ b/erpnext/patches/v13_0/trim_whitespace_from_serial_nos.py
@@ -0,0 +1,67 @@
+import frappe
+
+from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
+
+
+def execute():
+ broken_sles = frappe.db.sql("""
+ select name, serial_no
+ from `tabStock Ledger Entry`
+ where
+ is_cancelled = 0
+ and ( serial_no like %s or serial_no like %s or serial_no like %s or serial_no like %s
+ or serial_no = %s )
+ """,
+ (
+ " %", # leading whitespace
+ "% ", # trailing whitespace
+ "%\n %", # leading whitespace on newline
+ "% \n%", # trailing whitespace on newline
+ "\n", # just new line
+ ),
+ as_dict=True,
+ )
+
+ frappe.db.MAX_WRITES_PER_TRANSACTION += len(broken_sles)
+
+ if not broken_sles:
+ return
+
+ broken_serial_nos = set()
+
+ # patch SLEs
+ for sle in broken_sles:
+ serial_no_list = get_serial_nos(sle.serial_no)
+ correct_sr_no = "\n".join(serial_no_list)
+
+ if correct_sr_no == sle.serial_no:
+ continue
+
+ frappe.db.set_value("Stock Ledger Entry", sle.name, "serial_no", correct_sr_no, update_modified=False)
+ broken_serial_nos.update(serial_no_list)
+
+ if not broken_serial_nos:
+ return
+
+ # Patch serial No documents if they don't have purchase info
+ # Purchase info is used for fetching incoming rate
+ broken_sr_no_records = frappe.get_list("Serial No",
+ filters={
+ "status":"Active",
+ "name": ("in", broken_serial_nos),
+ "purchase_document_type": ("is", "not set")
+ },
+ pluck="name",
+ )
+
+ frappe.db.MAX_WRITES_PER_TRANSACTION += len(broken_sr_no_records)
+
+ patch_savepoint = "serial_no_patch"
+ for serial_no in broken_sr_no_records:
+ try:
+ frappe.db.savepoint(patch_savepoint)
+ sn = frappe.get_doc("Serial No", serial_no)
+ sn.update_serial_no_reference()
+ sn.db_update()
+ except Exception:
+ frappe.db.rollback(save_point=patch_savepoint)
diff --git a/erpnext/patches/v13_0/update_asset_quantity_field.py b/erpnext/patches/v13_0/update_asset_quantity_field.py
new file mode 100644
index 0000000..47884d1
--- /dev/null
+++ b/erpnext/patches/v13_0/update_asset_quantity_field.py
@@ -0,0 +1,8 @@
+import frappe
+
+
+def execute():
+ if frappe.db.count('Asset'):
+ frappe.reload_doc("assets", "doctype", "Asset")
+ asset = frappe.qb.DocType('Asset')
+ frappe.qb.update(asset).set(asset.asset_quantity, 1).run()
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/update_exchange_rate_settings.py b/erpnext/patches/v13_0/update_exchange_rate_settings.py
new file mode 100644
index 0000000..b7ec232
--- /dev/null
+++ b/erpnext/patches/v13_0/update_exchange_rate_settings.py
@@ -0,0 +1,10 @@
+import frappe
+
+from erpnext.setup.install import setup_currency_exchange
+
+
+def execute():
+ frappe.reload_doc("accounts", "doctype", "currency_exchange_settings")
+ frappe.reload_doc("accounts", "doctype", "currency_exchange_settings_result")
+ frappe.reload_doc("accounts", "doctype", "currency_exchange_settings_details")
+ setup_currency_exchange()
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/update_maintenance_schedule_field_in_visit.py b/erpnext/patches/v13_0/update_maintenance_schedule_field_in_visit.py
new file mode 100644
index 0000000..450c00e
--- /dev/null
+++ b/erpnext/patches/v13_0/update_maintenance_schedule_field_in_visit.py
@@ -0,0 +1,22 @@
+
+import frappe
+
+
+def execute():
+ # Updates the Maintenance Schedule link to fetch serial nos
+ from frappe.query_builder.functions import Coalesce
+ mvp = frappe.qb.DocType('Maintenance Visit Purpose')
+ mv = frappe.qb.DocType('Maintenance Visit')
+
+ frappe.qb.update(
+ mv
+ ).join(
+ mvp
+ ).on(mvp.parent == mv.name).set(
+ mv.maintenance_schedule,
+ Coalesce(mvp.prevdoc_docname, '')
+ ).where(
+ (mv.maintenance_type == "Scheduled")
+ & (mvp.prevdoc_docname.notnull())
+ & (mv.docstatus < 2)
+ ).run(as_dict=1)
diff --git a/erpnext/patches/v13_0/validate_options_for_data_field.py b/erpnext/patches/v13_0/validate_options_for_data_field.py
deleted file mode 100644
index ad777b8..0000000
--- a/erpnext/patches/v13_0/validate_options_for_data_field.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2021, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-
-import frappe
-from frappe.model import data_field_options
-
-
-def execute():
-
- for field in frappe.get_all('Custom Field',
- fields = ['name'],
- filters = {
- 'fieldtype': 'Data',
- 'options': ['!=', None]
- }):
-
- if field not in data_field_options:
- frappe.db.sql("""
- UPDATE
- `tabCustom Field`
- SET
- options=NULL
- WHERE
- name=%s
- """, (field))
diff --git a/erpnext/patches/v13_0/wipe_serial_no_field_for_0_qty.py b/erpnext/patches/v13_0/wipe_serial_no_field_for_0_qty.py
new file mode 100644
index 0000000..e43a8ba
--- /dev/null
+++ b/erpnext/patches/v13_0/wipe_serial_no_field_for_0_qty.py
@@ -0,0 +1,18 @@
+import frappe
+
+
+def execute():
+
+ doctype = "Stock Reconciliation Item"
+
+ if not frappe.db.has_column(doctype, "current_serial_no"):
+ # nothing to fix if column doesn't exist
+ return
+
+ sr_item = frappe.qb.DocType(doctype)
+
+ (frappe.qb
+ .update(sr_item)
+ .set(sr_item.current_serial_no, None)
+ .where(sr_item.current_qty == 0)
+ ).run()
diff --git a/erpnext/patches/v14_0/delete_healthcare_doctypes.py b/erpnext/patches/v14_0/delete_healthcare_doctypes.py
index 28fc01b..3a4f8f5 100644
--- a/erpnext/patches/v14_0/delete_healthcare_doctypes.py
+++ b/erpnext/patches/v14_0/delete_healthcare_doctypes.py
@@ -47,3 +47,18 @@
frappe.delete_doc("DocType", doctype, ignore_missing=True)
frappe.delete_doc("Module Def", "Healthcare", ignore_missing=True, force=True)
+
+ custom_fields = {
+ 'Sales Invoice': ['patient', 'patient_name', 'ref_practitioner'],
+ 'Sales Invoice Item': ['reference_dt', 'reference_dn'],
+ 'Stock Entry': ['inpatient_medication_entry'],
+ 'Stock Entry Detail': ['patient', 'inpatient_medication_entry_child'],
+ }
+ for doc, fields in custom_fields.items():
+ filters = {
+ 'dt': doc,
+ 'fieldname': ['in', fields]
+ }
+ records = frappe.get_all('Custom Field', filters=filters, pluck='name')
+ for record in records:
+ frappe.delete_doc('Custom Field', record, ignore_missing=True, force=True)
diff --git a/erpnext/patches/v14_0/delete_hospitality_doctypes.py b/erpnext/patches/v14_0/delete_hospitality_doctypes.py
new file mode 100644
index 0000000..d0216f8
--- /dev/null
+++ b/erpnext/patches/v14_0/delete_hospitality_doctypes.py
@@ -0,0 +1,32 @@
+import frappe
+
+
+def execute():
+ modules = ['Hotels', 'Restaurant']
+
+ for module in modules:
+ frappe.delete_doc("Module Def", module, ignore_missing=True, force=True)
+
+ frappe.delete_doc("Workspace", module, ignore_missing=True, force=True)
+
+ reports = frappe.get_all("Report", {"module": module, "is_standard": "Yes"}, pluck='name')
+ for report in reports:
+ frappe.delete_doc("Report", report, ignore_missing=True, force=True)
+
+ dashboards = frappe.get_all("Dashboard", {"module": module, "is_standard": 1}, pluck='name')
+ for dashboard in dashboards:
+ frappe.delete_doc("Dashboard", dashboard, ignore_missing=True, force=True)
+
+ doctypes = frappe.get_all("DocType", {"module": module, "custom": 0}, pluck='name')
+ for doctype in doctypes:
+ frappe.delete_doc("DocType", doctype, ignore_missing=True)
+
+ custom_fields = [
+ {"dt": "Sales Invoice", "fieldname": "restaurant"},
+ {"dt": "Sales Invoice", "fieldname": "restaurant_table"},
+ {"dt": "Price List", "fieldname": "restaurant_menu"},
+ ]
+
+ for field in custom_fields:
+ custom_field = frappe.db.get_value("Custom Field", field)
+ frappe.delete_doc("Custom Field", custom_field, ignore_missing=True)
diff --git a/erpnext/patches/v14_0/rearrange_company_fields.py b/erpnext/patches/v14_0/rearrange_company_fields.py
new file mode 100644
index 0000000..dd953ff
--- /dev/null
+++ b/erpnext/patches/v14_0/rearrange_company_fields.py
@@ -0,0 +1,31 @@
+import frappe
+from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
+
+
+def execute():
+ frappe.reload_doc('setup', 'doctype', 'company')
+
+ custom_fields = {
+ 'Company': [
+ dict(fieldname='hra_section', label='HRA Settings',
+ fieldtype='Section Break', insert_after='asset_received_but_not_billed', collapsible=1),
+ dict(fieldname='basic_component', label='Basic Component',
+ fieldtype='Link', options='Salary Component', insert_after='hra_section'),
+ dict(fieldname='hra_component', label='HRA Component',
+ fieldtype='Link', options='Salary Component', insert_after='basic_component'),
+ dict(fieldname='hra_column_break', fieldtype='Column Break', insert_after='hra_component'),
+ dict(fieldname='arrear_component', label='Arrear Component',
+ fieldtype='Link', options='Salary Component', insert_after='hra_column_break'),
+ dict(fieldname='non_profit_section', label='Non Profit Settings',
+ fieldtype='Section Break', insert_after='arrear_component', collapsible=1),
+ dict(fieldname='company_80g_number', label='80G Number',
+ fieldtype='Data', insert_after='non_profit_section'),
+ dict(fieldname='with_effect_from', label='80G With Effect From',
+ fieldtype='Date', insert_after='company_80g_number'),
+ dict(fieldname='non_profit_column_break', fieldtype='Column Break', insert_after='with_effect_from'),
+ dict(fieldname='pan_details', label='PAN Number',
+ fieldtype='Data', insert_after='non_profit_column_break')
+ ]
+ }
+
+ create_custom_fields(custom_fields, update=True)
\ No newline at end of file
diff --git a/erpnext/patches/v14_0/update_leave_notification_template.py b/erpnext/patches/v14_0/update_leave_notification_template.py
new file mode 100644
index 0000000..e744054
--- /dev/null
+++ b/erpnext/patches/v14_0/update_leave_notification_template.py
@@ -0,0 +1,17 @@
+import os
+
+import frappe
+from frappe import _
+
+
+def execute():
+ base_path = frappe.get_app_path("erpnext", "hr", "doctype")
+ response = frappe.read_file(os.path.join(base_path, "leave_application/leave_application_email_template.html"))
+
+ template = frappe.db.exists("Email Template", _("Leave Approval Notification"))
+ if template:
+ frappe.db.set_value("Email Template", template, "response", response)
+
+ template = frappe.db.exists("Email Template", _("Leave Status Notification"))
+ if template:
+ frappe.db.set_value("Email Template", template, "response", response)
diff --git a/erpnext/payroll/doctype/additional_salary/additional_salary.json b/erpnext/payroll/doctype/additional_salary/additional_salary.json
index d9efe45..9c897a7 100644
--- a/erpnext/payroll/doctype/additional_salary/additional_salary.json
+++ b/erpnext/payroll/doctype/additional_salary/additional_salary.json
@@ -204,10 +204,11 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2021-05-26 11:10:00.812698",
+ "modified": "2022-01-19 12:56:51.765353",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Additional Salary",
+ "naming_rule": "By \"Naming Series\" field",
"owner": "Administrator",
"permissions": [
{
@@ -239,8 +240,10 @@
"write": 1
}
],
+ "search_fields": "employee_name",
"sort_field": "modified",
"sort_order": "DESC",
- "title_field": "employee",
+ "states": [],
+ "title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.json b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.json
index 8332697..2e4b64e 100644
--- a/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.json
+++ b/erpnext/payroll/doctype/employee_benefit_application/employee_benefit_application.json
@@ -147,10 +147,11 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2021-03-31 22:35:08.940087",
+ "modified": "2022-01-19 12:58:31.664468",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Employee Benefit Application",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -212,8 +213,10 @@
}
],
"quick_entry": 1,
+ "search_fields": "employee_name",
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
"title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.json b/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.json
index b3bac01..5deb0a5 100644
--- a/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.json
+++ b/erpnext/payroll/doctype/employee_benefit_claim/employee_benefit_claim.json
@@ -144,10 +144,11 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2021-03-31 22:37:21.024625",
+ "modified": "2022-01-19 12:59:15.699118",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Employee Benefit Claim",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -208,8 +209,10 @@
"write": 1
}
],
+ "search_fields": "employee_name",
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
"title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/employee_incentive/employee_incentive.json b/erpnext/payroll/doctype/employee_incentive/employee_incentive.json
index 0d10b2c..64fb8c5 100644
--- a/erpnext/payroll/doctype/employee_incentive/employee_incentive.json
+++ b/erpnext/payroll/doctype/employee_incentive/employee_incentive.json
@@ -94,10 +94,11 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2021-03-31 22:38:20.332316",
+ "modified": "2022-01-19 12:52:19.850710",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Employee Incentive",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -136,8 +137,10 @@
"write": 1
}
],
+ "search_fields": "employee_name",
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
"title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/employee_other_income/employee_other_income.json b/erpnext/payroll/doctype/employee_other_income/employee_other_income.json
index 14f63e4..04ce9f7 100644
--- a/erpnext/payroll/doctype/employee_other_income/employee_other_income.json
+++ b/erpnext/payroll/doctype/employee_other_income/employee_other_income.json
@@ -76,10 +76,11 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2020-06-22 22:55:17.604688",
+ "modified": "2022-01-19 12:58:43.255900",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Employee Other Income",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -129,7 +130,10 @@
}
],
"quick_entry": 1,
+ "search_fields": "employee_name",
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
+ "title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json b/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
index b247d26..5ef373e 100644
--- a/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
+++ b/erpnext/payroll/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json
@@ -119,10 +119,11 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2021-03-31 22:39:59.237361",
+ "modified": "2022-01-19 12:58:54.707871",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Employee Tax Exemption Declaration",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -186,7 +187,10 @@
"write": 1
}
],
+ "search_fields": "employee_name",
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
+ "title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
index 77b107e..bb90051 100644
--- a/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
+++ b/erpnext/payroll/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
@@ -142,10 +142,11 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2021-03-31 22:41:13.723339",
+ "modified": "2022-01-19 12:58:24.244546",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Employee Tax Exemption Proof Submission",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -209,7 +210,10 @@
"write": 1
}
],
+ "search_fields": "employee_name",
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
+ "title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/gratuity/gratuity.json b/erpnext/payroll/doctype/gratuity/gratuity.json
index 48a9ce4..1970895 100644
--- a/erpnext/payroll/doctype/gratuity/gratuity.json
+++ b/erpnext/payroll/doctype/gratuity/gratuity.json
@@ -167,10 +167,11 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-07-02 15:05:57.396398",
+ "modified": "2022-01-19 12:54:37.306145",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Gratuity",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -198,6 +199,9 @@
"write": 1
}
],
+ "search_fields": "employee_name",
"sort_field": "modified",
- "sort_order": "DESC"
+ "sort_order": "DESC",
+ "states": [],
+ "title_field": "employee_name"
}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index ed3fa5b..db88c06 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -61,6 +61,8 @@
def on_cancel(self):
frappe.delete_doc("Salary Slip", frappe.db.sql_list("""select name from `tabSalary Slip`
where payroll_entry=%s """, (self.name)))
+ self.db_set("salary_slips_created", 0)
+ self.db_set("salary_slips_submitted", 0)
def get_emp_list(self):
"""
diff --git a/erpnext/payroll/doctype/retention_bonus/retention_bonus.json b/erpnext/payroll/doctype/retention_bonus/retention_bonus.json
index 7ea6210..f8d8bb4 100644
--- a/erpnext/payroll/doctype/retention_bonus/retention_bonus.json
+++ b/erpnext/payroll/doctype/retention_bonus/retention_bonus.json
@@ -105,10 +105,11 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2021-03-31 22:43:28.363644",
+ "modified": "2022-01-19 12:57:37.898953",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Retention Bonus",
+ "naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
@@ -163,7 +164,10 @@
"share": 1
}
],
+ "search_fields": "employee_name",
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
+ "title_field": "employee_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.json b/erpnext/payroll/doctype/salary_slip/salary_slip.json
index 4e40e13..fe8e22c 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.json
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.json
@@ -637,7 +637,7 @@
"idx": 9,
"is_submittable": 1,
"links": [],
- "modified": "2021-12-23 11:47:47.098248",
+ "modified": "2022-01-19 12:45:54.999345",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Salary Slip",
@@ -673,9 +673,11 @@
"role": "Employee"
}
],
+ "search_fields": "employee_name",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
"timeline_field": "employee",
"title_field": "employee_name"
-}
+}
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index a4e75ac..f33443d 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -1142,15 +1142,17 @@
})
def make_loan_repayment_entry(self):
+ payroll_payable_account = get_payroll_payable_account(self.company, self.payroll_entry)
for loan in self.loans:
- repayment_entry = create_repayment_entry(loan.loan, self.employee,
- self.company, self.posting_date, loan.loan_type, "Regular Payment", loan.interest_amount,
- loan.principal_amount, loan.total_payment)
+ if loan.total_payment:
+ repayment_entry = create_repayment_entry(loan.loan, self.employee,
+ self.company, self.posting_date, loan.loan_type, "Regular Payment", loan.interest_amount,
+ loan.principal_amount, loan.total_payment, payroll_payable_account=payroll_payable_account)
- repayment_entry.save()
- repayment_entry.submit()
+ repayment_entry.save()
+ repayment_entry.submit()
- frappe.db.set_value("Salary Slip Loan", loan.name, "loan_repayment_entry", repayment_entry.name)
+ frappe.db.set_value("Salary Slip Loan", loan.name, "loan_repayment_entry", repayment_entry.name)
def cancel_loan_repayment_entry(self):
for loan in self.loans:
@@ -1384,3 +1386,11 @@
],
as_dict=1,
)
+
+def get_payroll_payable_account(company, payroll_entry):
+ if payroll_entry:
+ payroll_payable_account = frappe.db.get_value('Payroll Entry', payroll_entry, 'payroll_payable_account')
+ else:
+ payroll_payable_account = frappe.db.get_value('Company', company, 'default_payroll_payable_account')
+
+ return payroll_payable_account
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index 6e8fae0..c0e005a 100644
--- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
@@ -380,7 +380,7 @@
make_salary_structure("Test Loan Repayment Salary Structure", "Monthly", employee=applicant, currency='INR',
payroll_period=payroll_period)
- frappe.db.sql("delete from tabLoan")
+ frappe.db.sql("delete from tabLoan where applicant = 'test_loan_repayment_salary_slip@salary.com'")
loan = create_loan(applicant, "Car Loan", 11000, "Repay Over Number of Periods", 20, posting_date=add_months(nowdate(), -1))
loan.repay_from_salary = 1
loan.submit()
diff --git a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json
index 197ab5f..613246e 100644
--- a/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json
+++ b/erpnext/payroll/doctype/salary_structure_assignment/salary_structure_assignment.json
@@ -162,7 +162,7 @@
],
"is_submittable": 1,
"links": [],
- "modified": "2021-12-23 17:28:09.794444",
+ "modified": "2022-01-19 12:43:54.439073",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Salary Structure Assignment",
@@ -209,6 +209,7 @@
"write": 1
}
],
+ "search_fields": "employee_name, salary_structure",
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
diff --git a/erpnext/payroll/workspace/payroll/payroll.json b/erpnext/payroll/workspace/payroll/payroll.json
index 7246dae..762bea0 100644
--- a/erpnext/payroll/workspace/payroll/payroll.json
+++ b/erpnext/payroll/workspace/payroll/payroll.json
@@ -5,7 +5,7 @@
"label": "Outgoing Salary"
}
],
- "content": "[{\"type\": \"onboarding\", \"data\": {\"onboarding_name\":\"Payroll\", \"col\": 12}}, {\"type\": \"chart\", \"data\": {\"chart_name\": \"Outgoing Salary\", \"col\": 12}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Salary Structure\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Payroll Entry\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Salary Slip\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Income Tax Slab\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Salary Register\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Dashboard\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Payroll\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Taxation\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Compensations\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Reports\", \"col\": 4}}]",
+ "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Payroll\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Outgoing Salary\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Salary Structure\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payroll Entry\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Salary Slip\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Income Tax Slab\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Salary Register\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Payroll\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Taxation\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Compensations\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]",
"creation": "2020-05-27 19:54:23.405607",
"docstatus": 0,
"doctype": "Workspace",
@@ -312,7 +312,7 @@
"type": "Link"
}
],
- "modified": "2021-08-05 12:16:01.335325",
+ "modified": "2022-01-13 17:41:19.098813",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Payroll",
@@ -321,7 +321,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 19,
+ "sequence_id": 19.0,
"shortcuts": [
{
"label": "Salary Structure",
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 9b1ea04..8fa0538 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -102,7 +102,7 @@
frappe.throw(_("Completed On cannot be greater than Today"))
def update_depends_on(self):
- depends_on_tasks = self.depends_on_tasks or ""
+ depends_on_tasks = ""
for d in self.depends_on:
if d.task and d.task not in depends_on_tasks:
depends_on_tasks += d.task + ","
diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py
index 148d8ba..989bcd1 100644
--- a/erpnext/projects/doctype/timesheet/test_timesheet.py
+++ b/erpnext/projects/doctype/timesheet/test_timesheet.py
@@ -5,7 +5,7 @@
import unittest
import frappe
-from frappe.utils import add_months, now_datetime, nowdate
+from frappe.utils import add_months, add_to_date, now_datetime, nowdate
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.hr.doctype.employee.test_employee import make_employee
@@ -151,6 +151,27 @@
settings.ignore_employee_time_overlap = initial_setting
settings.save()
+ def test_to_time(self):
+ emp = make_employee("test_employee_6@salary.com")
+ from_time = now_datetime()
+
+ timesheet = frappe.new_doc("Timesheet")
+ timesheet.employee = emp
+ timesheet.append(
+ 'time_logs',
+ {
+ "billable": 1,
+ "activity_type": "_Test Activity Type",
+ "from_time": from_time,
+ "hours": 2,
+ "company": "_Test Company"
+ }
+ )
+ timesheet.save()
+
+ to_time = timesheet.time_logs[0].to_time
+ self.assertEqual(to_time, add_to_date(from_time, hours=2, as_datetime=True))
+
def make_salary_structure_for_timesheet(employee, company=None):
salary_structure_name = "Timesheet Salary Structure Test"
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index e92785e..dd0b5f9 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -7,7 +7,7 @@
import frappe
from frappe import _
from frappe.model.document import Document
-from frappe.utils import flt, getdate, time_diff_in_hours
+from frappe.utils import add_to_date, flt, getdate, time_diff_in_hours
from erpnext.controllers.queries import get_match_cond
from erpnext.hr.utils import validate_active_employee
@@ -136,10 +136,19 @@
def validate_time_logs(self):
for data in self.get('time_logs'):
+ self.set_to_time(data)
self.validate_overlap(data)
self.set_project(data)
self.validate_project(data)
+ def set_to_time(self, data):
+ if not (data.from_time and data.hours):
+ return
+
+ _to_time = add_to_date(data.from_time, hours=data.hours, as_datetime=True)
+ if data.to_time != _to_time:
+ data.to_time = _to_time
+
def validate_overlap(self, data):
settings = frappe.get_single('Projects Settings')
self.validate_overlap_for("user", data, self.user, settings.ignore_user_time_overlap)
diff --git a/erpnext/projects/workspace/projects/projects.json b/erpnext/projects/workspace/projects/projects.json
index 1df2b08..c5a047d 100644
--- a/erpnext/projects/workspace/projects/projects.json
+++ b/erpnext/projects/workspace/projects/projects.json
@@ -5,7 +5,7 @@
"label": "Open Projects"
}
],
- "content": "[{\"type\": \"chart\", \"data\": {\"chart_name\": \"Open Projects\", \"col\": 12}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Task\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Project\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Timesheet\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Project Billing Summary\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Dashboard\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Projects\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Time Tracking\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Reports\", \"col\": 4}}]",
+ "content": "[{\"type\":\"chart\",\"data\":{\"chart_name\":\"Open Projects\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Task\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Project\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Timesheet\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Project Billing Summary\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Projects\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Time Tracking\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]",
"creation": "2020-03-02 15:46:04.874669",
"docstatus": 0,
"doctype": "Workspace",
@@ -194,7 +194,7 @@
"type": "Link"
}
],
- "modified": "2021-08-05 12:16:01.540147",
+ "modified": "2022-01-13 17:41:55.163878",
"modified_by": "Administrator",
"module": "Projects",
"name": "Projects",
@@ -203,7 +203,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 20,
+ "sequence_id": 20.0,
"shortcuts": [
{
"color": "Blue",
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 7c1c8c7..ae0e2a3 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -114,6 +114,8 @@
if ((!item.qty) && me.frm.doc.is_return) {
item.amount = flt(item.rate * -1, precision("amount", item));
+ } else if ((!item.qty) && me.frm.doc.is_debit_note) {
+ item.amount = flt(item.rate, precision("amount", item));
} else {
item.amount = flt(item.rate * item.qty, precision("amount", item));
}
@@ -710,14 +712,15 @@
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "total_advance", "write_off_amount"]);
if(in_list(["Sales Invoice", "POS Invoice", "Purchase Invoice"], this.frm.doc.doctype)) {
- var grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
+ let grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
+ let base_grand_total = this.frm.doc.base_rounded_total || this.frm.doc.base_grand_total;
if(this.frm.doc.party_account_currency == this.frm.doc.currency) {
var total_amount_to_pay = flt((grand_total - this.frm.doc.total_advance
- this.frm.doc.write_off_amount), precision("grand_total"));
} else {
var total_amount_to_pay = flt(
- (flt(grand_total*this.frm.doc.conversion_rate, precision("grand_total"))
+ (flt(base_grand_total, precision("base_grand_total"))
- this.frm.doc.total_advance - this.frm.doc.base_write_off_amount),
precision("base_grand_total")
);
@@ -748,14 +751,15 @@
}
set_total_amount_to_default_mop() {
- var grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
+ let grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
+ let base_grand_total = this.frm.doc.base_rounded_total || this.frm.doc.base_grand_total;
if(this.frm.doc.party_account_currency == this.frm.doc.currency) {
var total_amount_to_pay = flt((grand_total - this.frm.doc.total_advance
- this.frm.doc.write_off_amount), precision("grand_total"));
} else {
var total_amount_to_pay = flt(
- (flt(grand_total*this.frm.doc.conversion_rate, precision("grand_total"))
+ (flt(base_grand_total, precision("base_grand_total"))
- this.frm.doc.total_advance - this.frm.doc.base_write_off_amount),
precision("base_grand_total")
);
diff --git a/erpnext/quality_management/workspace/quality/quality.json b/erpnext/quality_management/workspace/quality/quality.json
index ae28470..3effd59 100644
--- a/erpnext/quality_management/workspace/quality/quality.json
+++ b/erpnext/quality_management/workspace/quality/quality.json
@@ -1,6 +1,6 @@
{
"charts": [],
- "content": "[{\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Quality Goal\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Quality Procedure\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Quality Inspection\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Quality Review\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Quality Action\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Non Conformance\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Goal and Procedure\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Feedback\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Meeting\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Review and Action\", \"col\": 4}}]",
+ "content": "[{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Quality Goal\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Quality Procedure\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Quality Inspection\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Quality Review\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Quality Action\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Non Conformance\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Goal and Procedure\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Feedback\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Meeting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Review and Action\",\"col\":4}}]",
"creation": "2020-03-02 15:49:28.632014",
"docstatus": 0,
"doctype": "Workspace",
@@ -142,7 +142,7 @@
"type": "Link"
}
],
- "modified": "2021-08-05 12:16:01.699913",
+ "modified": "2022-01-13 17:42:20.105187",
"modified_by": "Administrator",
"module": "Quality Management",
"name": "Quality",
@@ -151,7 +151,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 21,
+ "sequence_id": 21.0,
"shortcuts": [
{
"color": "Grey",
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index ecd9294..68bcce7 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -567,16 +567,16 @@
fieldtype='Link', options='Salary Component', insert_after='basic_component'),
dict(fieldname='hra_column_break', fieldtype='Column Break', insert_after='hra_component'),
dict(fieldname='arrear_component', label='Arrear Component',
- fieldtype='Link', options='Salary Component', insert_after='hra_component'),
+ fieldtype='Link', options='Salary Component', insert_after='hra_column_break'),
dict(fieldname='non_profit_section', label='Non Profit Settings',
- fieldtype='Section Break', insert_after='asset_received_but_not_billed', collapsible=1),
+ fieldtype='Section Break', insert_after='arrear_component', collapsible=1),
dict(fieldname='company_80g_number', label='80G Number',
fieldtype='Data', insert_after='non_profit_section'),
dict(fieldname='with_effect_from', label='80G With Effect From',
fieldtype='Date', insert_after='company_80g_number'),
dict(fieldname='non_profit_column_break', fieldtype='Column Break', insert_after='with_effect_from'),
dict(fieldname='pan_details', label='PAN Number',
- fieldtype='Data', insert_after='with_effect_from')
+ fieldtype='Data', insert_after='non_profit_column_break')
],
'Employee Tax Exemption Declaration':[
dict(fieldname='hra_section', label='HRA Exemption',
diff --git a/erpnext/regional/report/gstr_1/gstr_1.js b/erpnext/regional/report/gstr_1/gstr_1.js
index ef2bdb6..4b98978 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.js
+++ b/erpnext/regional/report/gstr_1/gstr_1.js
@@ -53,7 +53,8 @@
{ "value": "CDNR-REG", "label": __("Credit/Debit Notes (Registered) - 9B") },
{ "value": "CDNR-UNREG", "label": __("Credit/Debit Notes (Unregistered) - 9B") },
{ "value": "EXPORT", "label": __("Export Invoice - 6A") },
- { "value": "Advances", "label": __("Tax Liability (Advances Received) - 11A(1), 11A(2)") }
+ { "value": "Advances", "label": __("Tax Liability (Advances Received) - 11A(1), 11A(2)") },
+ { "value": "NIL Rated", "label": __("NIL RATED/EXEMPTED Invoices") }
],
"default": "B2B"
}
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index 11b684d..e50ff18 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -40,7 +40,8 @@
port_code,
shipping_bill_number,
shipping_bill_date,
- reason_for_issuing_document
+ reason_for_issuing_document,
+ company_gstin
"""
def run(self):
@@ -62,6 +63,8 @@
self.get_b2c_data()
elif self.filters.get("type_of_business") == "Advances":
self.get_advance_data()
+ elif self.filters.get("type_of_business") == "NIL Rated":
+ self.get_nil_rated_invoices()
elif self.invoices:
for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
invoice_details = self.invoices.get(inv)
@@ -91,6 +94,57 @@
row= [key[0], key[1], value[0], value[1]]
self.data.append(row)
+ def get_nil_rated_invoices(self):
+ nil_exempt_output = [
+ {
+ "description": "Inter-State supplies to registered persons",
+ "nil_rated": 0.0,
+ "exempted": 0.0,
+ "non_gst": 0.0
+ },
+ {
+ "description": "Intra-State supplies to registered persons",
+ "nil_rated": 0.0,
+ "exempted": 0.0,
+ "non_gst": 0.0
+ },
+ {
+ "description": "Inter-State supplies to unregistered persons",
+ "nil_rated": 0.0,
+ "exempted": 0.0,
+ "non_gst": 0.0
+ },
+ {
+ "description": "Intra-State supplies to unregistered persons",
+ "nil_rated": 0.0,
+ "exempted": 0.0,
+ "non_gst": 0.0
+ }
+ ]
+
+ for invoice, details in self.nil_exempt_non_gst.items():
+ invoice_detail = self.invoices.get(invoice)
+ if invoice_detail.get('gst_category') in ("Registered Regular", "Deemed Export", "SEZ"):
+ if is_inter_state(invoice_detail):
+ nil_exempt_output[0]["nil_rated"] += details[0]
+ nil_exempt_output[0]["exempted"] += details[1]
+ nil_exempt_output[0]["non_gst"] += details[2]
+ else:
+ nil_exempt_output[1]["nil_rated"] += details[0]
+ nil_exempt_output[1]["exempted"] += details[1]
+ nil_exempt_output[1]["non_gst"] += details[2]
+ else:
+ if is_inter_state(invoice_detail):
+ nil_exempt_output[2]["nil_rated"] += details[0]
+ nil_exempt_output[2]["exempted"] += details[1]
+ nil_exempt_output[2]["non_gst"] += details[2]
+ else:
+ nil_exempt_output[3]["nil_rated"] += details[0]
+ nil_exempt_output[3]["exempted"] += details[1]
+ nil_exempt_output[3]["non_gst"] += details[2]
+
+ self.data = nil_exempt_output
+
def get_b2c_data(self):
b2cs_output = {}
@@ -240,10 +294,11 @@
def get_invoice_items(self):
self.invoice_items = frappe._dict()
self.item_tax_rate = frappe._dict()
+ self.nil_exempt_non_gst = {}
items = frappe.db.sql("""
- select item_code, parent, taxable_value, base_net_amount, item_tax_rate
- from `tab%s Item`
+ select item_code, parent, taxable_value, base_net_amount, item_tax_rate, is_nil_exempt,
+ is_non_gst from `tab%s Item`
where parent in (%s)
""" % (self.doctype, ', '.join(['%s']*len(self.invoices))), tuple(self.invoices), as_dict=1)
@@ -260,6 +315,16 @@
tax_rate_dict = self.item_tax_rate.setdefault(d.parent, {}).setdefault(d.item_code, [])
tax_rate_dict.append(rate)
+ if d.is_nil_exempt:
+ self.nil_exempt_non_gst.setdefault(d.parent, [0.0, 0.0, 0.0])
+ if item_tax_rate:
+ self.nil_exempt_non_gst[d.parent][0] += d.get('taxable_value', 0)
+ else:
+ self.nil_exempt_non_gst[d.parent][1] += d.get('taxable_value', 0)
+ elif d.is_non_gst:
+ self.nil_exempt_non_gst.setdefault(d.parent, [0.0, 0.0, 0.0])
+ self.nil_exempt_non_gst[d.parent][2] += d.get('taxable_value', 0)
+
def get_items_based_on_tax_rate(self):
self.tax_details = frappe.db.sql("""
select
@@ -322,21 +387,24 @@
self.items_based_on_tax_rate.setdefault(invoice, {}).setdefault(0, items.keys())
def get_columns(self):
- self.tax_columns = [
- {
- "fieldname": "rate",
- "label": "Rate",
- "fieldtype": "Int",
- "width": 60
- },
- {
- "fieldname": "taxable_value",
- "label": "Taxable Value",
- "fieldtype": "Currency",
- "width": 100
- }
- ]
self.other_columns = []
+ self.tax_columns = []
+
+ if self.filters.get("type_of_business") != "NIL Rated":
+ self.tax_columns = [
+ {
+ "fieldname": "rate",
+ "label": "Rate",
+ "fieldtype": "Int",
+ "width": 60
+ },
+ {
+ "fieldname": "taxable_value",
+ "label": "Taxable Value",
+ "fieldtype": "Currency",
+ "width": 100
+ }
+ ]
if self.filters.get("type_of_business") == "B2B":
self.invoice_columns = [
@@ -705,6 +773,33 @@
"width": 100
}
]
+ elif self.filters.get("type_of_business") == "NIL Rated":
+ self.invoice_columns = [
+ {
+ "fieldname": "description",
+ "label": "Description",
+ "fieldtype": "Data",
+ "width": 420
+ },
+ {
+ "fieldname": "nil_rated",
+ "label": "Nil Rated",
+ "fieldtype": "Currency",
+ "width": 200
+ },
+ {
+ "fieldname": "exempted",
+ "label": "Exempted",
+ "fieldtype": "Currency",
+ "width": 200
+ },
+ {
+ "fieldname": "non_gst",
+ "label": "Non GST",
+ "fieldtype": "Currency",
+ "width": 200
+ }
+ ]
self.columns = self.invoice_columns + self.tax_columns + self.other_columns
@@ -768,6 +863,11 @@
out = get_advances_json(res, gstin)
gst_json["at"] = out
+ elif filters["type_of_business"] == "NIL Rated":
+ res = report_data[:-1]
+ out = get_exempted_json(res)
+ gst_json["nil"] = out
+
return {
'report_name': report_name,
'report_type': filters['type_of_business'],
@@ -980,6 +1080,36 @@
return out
+def get_exempted_json(data):
+ out = {
+ "inv": [
+ {
+ "sply_ty": "INTRB2B"
+ },
+ {
+ "sply_ty": "INTRAB2B"
+ },
+ {
+ "sply_ty": "INTRB2C"
+ },
+ {
+ "sply_ty": "INTRAB2C"
+ }
+ ]
+ }
+
+ for i, v in enumerate(data):
+ if data[i].get('nil_rated'):
+ out['inv'][i]['nil_amt'] = data[i]['nil_rated']
+
+ if data[i].get('exempted'):
+ out['inv'][i]['expt_amt'] = data[i]['exempted']
+
+ if data[i].get('non_gst'):
+ out['inv'][i]['ngsup_amt'] = data[i]['non_gst']
+
+ return out
+
def get_invoice_type_for_cdnr(row):
if row.get('gst_category') == 'SEZ':
if row.get('export_type') == 'WPAY':
@@ -1064,3 +1194,9 @@
frappe.response['filecontent'] = data['data']
frappe.response['content_type'] = 'application/json'
frappe.response['type'] = 'download'
+
+def is_inter_state(invoice_detail):
+ if invoice_detail.place_of_supply.split("-")[0] != invoice_detail.company_gstin[:2]:
+ return True
+ else:
+ return False
\ No newline at end of file
diff --git a/erpnext/regional/report/ksa_vat/ksa_vat.py b/erpnext/regional/report/ksa_vat/ksa_vat.py
index b41b2b0..cc26bd7 100644
--- a/erpnext/regional/report/ksa_vat/ksa_vat.py
+++ b/erpnext/regional/report/ksa_vat/ksa_vat.py
@@ -20,25 +20,35 @@
"fieldname": "title",
"label": _("Title"),
"fieldtype": "Data",
- "width": 300
+ "width": 300,
},
{
"fieldname": "amount",
"label": _("Amount (SAR)"),
"fieldtype": "Currency",
+ "options": "currency",
"width": 150,
},
{
"fieldname": "adjustment_amount",
"label": _("Adjustment (SAR)"),
"fieldtype": "Currency",
+ "options": "currency",
"width": 150,
},
{
"fieldname": "vat_amount",
"label": _("VAT Amount (SAR)"),
"fieldtype": "Currency",
+ "options": "currency",
"width": 150,
+ },
+ {
+ "fieldname": "currency",
+ "label": _("Currency"),
+ "fieldtype": "Currency",
+ "width": 150,
+ "hidden": 1
}
]
@@ -47,6 +57,8 @@
# Validate if vat settings exist
company = filters.get('company')
+ company_currency = frappe.get_cached_value('Company', company, "default_currency")
+
if frappe.db.exists('KSA VAT Setting', company) is None:
url = get_url_to_list('KSA VAT Setting')
frappe.msgprint(_('Create <a href="{}">KSA VAT Setting</a> for this company').format(url))
@@ -55,7 +67,7 @@
ksa_vat_setting = frappe.get_doc('KSA VAT Setting', company)
# Sales Heading
- append_data(data, 'VAT on Sales', '', '', '')
+ append_data(data, 'VAT on Sales', '', '', '', company_currency)
grand_total_taxable_amount = 0
grand_total_taxable_adjustment_amount = 0
@@ -67,7 +79,7 @@
# Adding results to data
append_data(data, vat_setting.title, total_taxable_amount,
- total_taxable_adjustment_amount, total_tax)
+ total_taxable_adjustment_amount, total_tax, company_currency)
grand_total_taxable_amount += total_taxable_amount
grand_total_taxable_adjustment_amount += total_taxable_adjustment_amount
@@ -75,13 +87,13 @@
# Sales Grand Total
append_data(data, 'Grand Total', grand_total_taxable_amount,
- grand_total_taxable_adjustment_amount, grand_total_tax)
+ grand_total_taxable_adjustment_amount, grand_total_tax, company_currency)
# Blank Line
- append_data(data, '', '', '', '')
+ append_data(data, '', '', '', '', company_currency)
# Purchase Heading
- append_data(data, 'VAT on Purchases', '', '', '')
+ append_data(data, 'VAT on Purchases', '', '', '', company_currency)
grand_total_taxable_amount = 0
grand_total_taxable_adjustment_amount = 0
@@ -93,7 +105,7 @@
# Adding results to data
append_data(data, vat_setting.title, total_taxable_amount,
- total_taxable_adjustment_amount, total_tax)
+ total_taxable_adjustment_amount, total_tax, company_currency)
grand_total_taxable_amount += total_taxable_amount
grand_total_taxable_adjustment_amount += total_taxable_adjustment_amount
@@ -101,7 +113,7 @@
# Purchase Grand Total
append_data(data, 'Grand Total', grand_total_taxable_amount,
- grand_total_taxable_adjustment_amount, grand_total_tax)
+ grand_total_taxable_adjustment_amount, grand_total_tax, company_currency)
return data
@@ -147,9 +159,10 @@
-def append_data(data, title, amount, adjustment_amount, vat_amount):
+def append_data(data, title, amount, adjustment_amount, vat_amount, company_currency):
"""Returns data with appended value."""
- data.append({"title": _(title), "amount": amount, "adjustment_amount": adjustment_amount, "vat_amount": vat_amount})
+ data.append({"title": _(title), "amount": amount, "adjustment_amount": adjustment_amount, "vat_amount": vat_amount,
+ "currency": company_currency})
def get_tax_amount(item_code, account_head, doctype, parent):
if doctype == 'Sales Invoice':
diff --git a/erpnext/regional/saudi_arabia/setup.py b/erpnext/regional/saudi_arabia/setup.py
index 2e31c03..15d524d 100644
--- a/erpnext/regional/saudi_arabia/setup.py
+++ b/erpnext/regional/saudi_arabia/setup.py
@@ -3,12 +3,10 @@
import frappe
from frappe.permissions import add_permission, update_permission_property
-from erpnext.regional.united_arab_emirates.setup import make_custom_fields as uae_custom_fields
from erpnext.regional.saudi_arabia.wizard.operations.setup_ksa_vat_setting import create_ksa_vat_setting
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
def setup(company=None, patch=True):
- uae_custom_fields()
add_print_formats()
add_permissions()
make_custom_fields()
@@ -40,38 +38,67 @@
- Company Name in Arabic
- Address in Arabic
"""
+ is_zero_rated = dict(fieldname='is_zero_rated', label='Is Zero Rated',
+ fieldtype='Check', fetch_from='item_code.is_zero_rated', insert_after='description',
+ print_hide=1)
+
+ is_exempt = dict(fieldname='is_exempt', label='Is Exempt',
+ fieldtype='Check', fetch_from='item_code.is_exempt', insert_after='is_zero_rated',
+ print_hide=1)
+
+ purchase_invoice_fields = [
+ dict(fieldname='company_trn', label='Company TRN',
+ fieldtype='Read Only', insert_after='shipping_address',
+ fetch_from='company.tax_id', print_hide=1),
+ dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic',
+ fieldtype='Read Only', insert_after='supplier_name',
+ fetch_from='supplier.supplier_name_in_arabic', print_hide=1)
+ ]
+
+ sales_invoice_fields = [
+ dict(fieldname='company_trn', label='Company TRN',
+ fieldtype='Read Only', insert_after='company_address',
+ fetch_from='company.tax_id', print_hide=1),
+ dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic',
+ fieldtype='Read Only', insert_after='customer_name',
+ fetch_from='customer.customer_name_in_arabic', print_hide=1),
+ dict(fieldname='ksa_einv_qr', label='KSA E-Invoicing QR',
+ fieldtype='Attach Image', read_only=1, no_copy=1, hidden=1)
+ ]
+
custom_fields = {
- 'Sales Invoice': [
- dict(
- fieldname='ksa_einv_qr',
- label='KSA E-Invoicing QR',
- fieldtype='Attach Image',
- read_only=1, no_copy=1, hidden=1
- )
+ 'Item': [is_zero_rated, is_exempt],
+ 'Customer': [
+ dict(fieldname='customer_name_in_arabic', label='Customer Name in Arabic',
+ fieldtype='Data', insert_after='customer_name'),
],
- 'POS Invoice': [
- dict(
- fieldname='ksa_einv_qr',
- label='KSA E-Invoicing QR',
- fieldtype='Attach Image',
- read_only=1, no_copy=1, hidden=1
- )
+ 'Supplier': [
+ dict(fieldname='supplier_name_in_arabic', label='Supplier Name in Arabic',
+ fieldtype='Data', insert_after='supplier_name'),
],
+ 'Purchase Invoice': purchase_invoice_fields,
+ 'Purchase Order': purchase_invoice_fields,
+ 'Purchase Receipt': purchase_invoice_fields,
+ 'Sales Invoice': sales_invoice_fields,
+ 'POS Invoice': sales_invoice_fields,
+ 'Sales Order': sales_invoice_fields,
+ 'Delivery Note': sales_invoice_fields,
+ 'Sales Invoice Item': [is_zero_rated, is_exempt],
+ 'POS Invoice Item': [is_zero_rated, is_exempt],
+ 'Purchase Invoice Item': [is_zero_rated, is_exempt],
+ 'Sales Order Item': [is_zero_rated, is_exempt],
+ 'Delivery Note Item': [is_zero_rated, is_exempt],
+ 'Quotation Item': [is_zero_rated, is_exempt],
+ 'Purchase Order Item': [is_zero_rated, is_exempt],
+ 'Purchase Receipt Item': [is_zero_rated, is_exempt],
+ 'Supplier Quotation Item': [is_zero_rated, is_exempt],
'Address': [
- dict(
- fieldname='address_in_arabic',
- label='Address in Arabic',
- fieldtype='Data',
- insert_after='address_line2'
- )
+ dict(fieldname='address_in_arabic', label='Address in Arabic',
+ fieldtype='Data',insert_after='address_line2')
],
'Company': [
- dict(
- fieldname='company_name_in_arabic',
- label='Company Name In Arabic',
- fieldtype='Data',
- insert_after='company_name'
- )
+ dict(fieldname='company_name_in_arabic', label='Company Name In Arabic',
+ fieldtype='Data', insert_after='company_name')
]
}
diff --git a/erpnext/restaurant/__init__.py b/erpnext/restaurant/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/restaurant/__init__.py
+++ /dev/null
diff --git a/erpnext/restaurant/doctype/__init__.py b/erpnext/restaurant/doctype/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/restaurant/doctype/__init__.py
+++ /dev/null
diff --git a/erpnext/restaurant/doctype/restaurant/__init__.py b/erpnext/restaurant/doctype/restaurant/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/restaurant/doctype/restaurant/__init__.py
+++ /dev/null
diff --git a/erpnext/restaurant/doctype/restaurant/restaurant.js b/erpnext/restaurant/doctype/restaurant/restaurant.js
deleted file mode 100644
index 13fda73..0000000
--- a/erpnext/restaurant/doctype/restaurant/restaurant.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Restaurant', {
- refresh: function(frm) {
- frm.add_custom_button(__('Order Entry'), () => {
- frappe.set_route('Form', 'Restaurant Order Entry');
- });
- }
-});
diff --git a/erpnext/restaurant/doctype/restaurant/restaurant.json b/erpnext/restaurant/doctype/restaurant/restaurant.json
deleted file mode 100644
index 8572687..0000000
--- a/erpnext/restaurant/doctype/restaurant/restaurant.json
+++ /dev/null
@@ -1,309 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "prompt",
- "beta": 1,
- "creation": "2017-09-15 12:40:41.546933",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "image",
- "fieldtype": "Attach Image",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_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,
- "unique": 0
- },
- {
- "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": 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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "default_customer",
- "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 Customer",
- "length": 0,
- "no_copy": 0,
- "options": "Customer",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "invoice_series_prefix",
- "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": "Invoice Series Prefix",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_4",
- "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
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "active_menu",
- "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": "Active Menu",
- "length": 0,
- "no_copy": 0,
- "options": "Restaurant Menu",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "default_tax_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": "Default Tax Template",
- "length": 0,
- "no_copy": 0,
- "options": "Sales Taxes and Charges 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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "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": "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,
- "unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_field": "image",
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2017-12-09 12:13:10.185496",
- "modified_by": "Administrator",
- "module": "Restaurant",
- "name": "Restaurant",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/restaurant/doctype/restaurant/restaurant.py b/erpnext/restaurant/doctype/restaurant/restaurant.py
deleted file mode 100644
index 67838d2..0000000
--- a/erpnext/restaurant/doctype/restaurant/restaurant.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class Restaurant(Document):
- pass
diff --git a/erpnext/restaurant/doctype/restaurant/restaurant_dashboard.py b/erpnext/restaurant/doctype/restaurant/restaurant_dashboard.py
deleted file mode 100644
index bfdd052..0000000
--- a/erpnext/restaurant/doctype/restaurant/restaurant_dashboard.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from frappe import _
-
-
-def get_data():
- return {
- 'fieldname': 'restaurant',
- 'transactions': [
- {
- 'label': _('Setup'),
- 'items': ['Restaurant Menu', 'Restaurant Table']
- },
- {
- 'label': _('Operations'),
- 'items': ['Restaurant Reservation', 'Sales Invoice']
- }
- ]
- }
diff --git a/erpnext/restaurant/doctype/restaurant/test_restaurant.py b/erpnext/restaurant/doctype/restaurant/test_restaurant.py
deleted file mode 100644
index f88f980..0000000
--- a/erpnext/restaurant/doctype/restaurant/test_restaurant.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-test_records = [
- dict(doctype='Restaurant', name='Test Restaurant 1', company='_Test Company 1',
- invoice_series_prefix='Test-Rest-1-Inv-', default_customer='_Test Customer 1'),
- dict(doctype='Restaurant', name='Test Restaurant 2', company='_Test Company 1',
- invoice_series_prefix='Test-Rest-2-Inv-', default_customer='_Test Customer 1'),
-]
-
-class TestRestaurant(unittest.TestCase):
- pass
diff --git a/erpnext/restaurant/doctype/restaurant_menu/__init__.py b/erpnext/restaurant/doctype/restaurant_menu/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/restaurant/doctype/restaurant_menu/__init__.py
+++ /dev/null
diff --git a/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.js b/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.js
deleted file mode 100644
index da7d43f..0000000
--- a/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Restaurant Menu', {
- setup: function(frm) {
- frm.add_fetch('item', 'standard_rate', 'rate');
- },
-});
diff --git a/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.json b/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.json
deleted file mode 100644
index 1b1610d..0000000
--- a/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.json
+++ /dev/null
@@ -1,247 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "prompt",
- "beta": 1,
- "creation": "2017-09-15 12:48:29.818715",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "restaurant",
- "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": "Restaurant",
- "length": 0,
- "no_copy": 0,
- "options": "Restaurant",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fieldname": "enabled",
- "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": "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,
- "unique": 0
- },
- {
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "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 (Auto created)",
- "length": 0,
- "no_copy": 0,
- "options": "Price List",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 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": "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 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,
- "options": "Restaurant Menu 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": 1,
- "search_index": 0,
- "set_only_once": 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": "2017-12-09 12:13:13.684500",
- "modified_by": "Administrator",
- "module": "Restaurant",
- "name": "Restaurant Menu",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Restaurant Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.py b/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.py
deleted file mode 100644
index 64eb40f..0000000
--- a/erpnext/restaurant/doctype/restaurant_menu/restaurant_menu.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import frappe
-from frappe.model.document import Document
-
-
-class RestaurantMenu(Document):
- def validate(self):
- for d in self.items:
- if not d.rate:
- d.rate = frappe.db.get_value('Item', d.item, 'standard_rate')
-
- def on_update(self):
- '''Sync Price List'''
- self.make_price_list()
-
- def on_trash(self):
- '''clear prices'''
- self.clear_item_price()
-
- def clear_item_price(self, price_list=None):
- '''clear all item prices for this menu'''
- if not price_list:
- price_list = self.get_price_list().name
- frappe.db.sql('delete from `tabItem Price` where price_list = %s', price_list)
-
- def make_price_list(self):
- # create price list for menu
- price_list = self.get_price_list()
- self.db_set('price_list', price_list.name)
-
- # delete old items
- self.clear_item_price(price_list.name)
-
- for d in self.items:
- frappe.get_doc(dict(
- doctype = 'Item Price',
- price_list = price_list.name,
- item_code = d.item,
- price_list_rate = d.rate
- )).insert()
-
- def get_price_list(self):
- '''Create price list for menu if missing'''
- price_list_name = frappe.db.get_value('Price List', dict(restaurant_menu=self.name))
- if price_list_name:
- price_list = frappe.get_doc('Price List', price_list_name)
- else:
- price_list = frappe.new_doc('Price List')
- price_list.restaurant_menu = self.name
- price_list.price_list_name = self.name
-
- price_list.enabled = 1
- price_list.selling = 1
- price_list.save()
-
- return price_list
diff --git a/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.py b/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.py
deleted file mode 100644
index 27020eb..0000000
--- a/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-import frappe
-
-test_records = [
- dict(doctype='Item', item_code='Food Item 1',
- item_group='Products', is_stock_item=0),
- dict(doctype='Item', item_code='Food Item 2',
- item_group='Products', is_stock_item=0),
- dict(doctype='Item', item_code='Food Item 3',
- item_group='Products', is_stock_item=0),
- dict(doctype='Item', item_code='Food Item 4',
- item_group='Products', is_stock_item=0),
- dict(doctype='Restaurant Menu', restaurant='Test Restaurant 1', name='Test Restaurant 1 Menu 1',
- items = [
- dict(item='Food Item 1', rate=400),
- dict(item='Food Item 2', rate=300),
- dict(item='Food Item 3', rate=200),
- dict(item='Food Item 4', rate=100),
- ]),
- dict(doctype='Restaurant Menu', restaurant='Test Restaurant 1', name='Test Restaurant 1 Menu 2',
- items = [
- dict(item='Food Item 1', rate=450),
- dict(item='Food Item 2', rate=350),
- ])
-]
-
-class TestRestaurantMenu(unittest.TestCase):
- def test_price_list_creation_and_editing(self):
- menu1 = frappe.get_doc('Restaurant Menu', 'Test Restaurant 1 Menu 1')
- menu1.save()
-
- menu2 = frappe.get_doc('Restaurant Menu', 'Test Restaurant 1 Menu 2')
- menu2.save()
-
- self.assertTrue(frappe.db.get_value('Price List', 'Test Restaurant 1 Menu 1'))
- self.assertEqual(frappe.db.get_value('Item Price',
- dict(price_list = 'Test Restaurant 1 Menu 1', item_code='Food Item 1'), 'price_list_rate'), 400)
- self.assertEqual(frappe.db.get_value('Item Price',
- dict(price_list = 'Test Restaurant 1 Menu 2', item_code='Food Item 1'), 'price_list_rate'), 450)
-
- menu1.items[0].rate = 401
- menu1.save()
-
- self.assertEqual(frappe.db.get_value('Item Price',
- dict(price_list = 'Test Restaurant 1 Menu 1', item_code='Food Item 1'), 'price_list_rate'), 401)
-
- menu1.items[0].rate = 400
- menu1.save()
diff --git a/erpnext/restaurant/doctype/restaurant_menu_item/__init__.py b/erpnext/restaurant/doctype/restaurant_menu_item/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/restaurant/doctype/restaurant_menu_item/__init__.py
+++ /dev/null
diff --git a/erpnext/restaurant/doctype/restaurant_menu_item/restaurant_menu_item.json b/erpnext/restaurant/doctype/restaurant_menu_item/restaurant_menu_item.json
deleted file mode 100644
index 87568bf..0000000
--- a/erpnext/restaurant/doctype/restaurant_menu_item/restaurant_menu_item.json
+++ /dev/null
@@ -1,105 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "",
- "beta": 0,
- "creation": "2017-09-15 12:49:36.072636",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 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": 0,
- "label": "Item",
- "length": 0,
- "no_copy": 0,
- "options": "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "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,
- "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,
- "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": 1,
- "max_attachments": 0,
- "modified": "2017-09-15 14:18:55.145088",
- "modified_by": "Administrator",
- "module": "Restaurant",
- "name": "Restaurant Menu Item",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/restaurant/doctype/restaurant_menu_item/restaurant_menu_item.py b/erpnext/restaurant/doctype/restaurant_menu_item/restaurant_menu_item.py
deleted file mode 100644
index 98b245e..0000000
--- a/erpnext/restaurant/doctype/restaurant_menu_item/restaurant_menu_item.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class RestaurantMenuItem(Document):
- pass
diff --git a/erpnext/restaurant/doctype/restaurant_order_entry/__init__.py b/erpnext/restaurant/doctype/restaurant_order_entry/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/restaurant/doctype/restaurant_order_entry/__init__.py
+++ /dev/null
diff --git a/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.js b/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.js
deleted file mode 100644
index 8df851c..0000000
--- a/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.js
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Restaurant Order Entry', {
- setup: function(frm) {
- let get_item_query = () => {
- return {
- query: 'erpnext.restaurant.doctype.restaurant_order_entry.restaurant_order_entry.item_query_restaurant',
- filters: {
- 'table': frm.doc.restaurant_table
- }
- };
- };
- frm.set_query('item', 'items', get_item_query);
- frm.set_query('add_item', get_item_query);
- },
- onload_post_render: function(frm) {
- if(!frm.item_selector) {
- frm.item_selector = new erpnext.ItemSelector({
- frm: frm,
- item_field: 'item',
- item_query: 'erpnext.restaurant.doctype.restaurant_order_entry.restaurant_order_entry.item_query_restaurant',
- get_filters: () => {
- return {table: frm.doc.restaurant_table};
- }
- });
- }
-
- let $input = frm.get_field('add_item').$input;
-
- $input.on('keyup', function(e) {
- if (e.which===13) {
- if (frm.clear_item_timeout) {
- clearTimeout (frm.clear_item_timeout);
- }
-
- // clear the item input so user can enter a new item
- frm.clear_item_timeout = setTimeout (() => {
- frm.set_value('add_item', '');
- }, 1000);
-
- let item = $input.val();
-
- if (!item) return;
-
- var added = false;
- (frm.doc.items || []).forEach((d) => {
- if (d.item===item) {
- d.qty += 1;
- added = true;
- }
- });
-
- return frappe.run_serially([
- () => {
- if (!added) {
- return frm.add_child('items', {item: item, qty: 1});
- }
- },
- () => frm.get_field("items").refresh()
- ]);
- }
- });
- },
- refresh: function(frm) {
- frm.disable_save();
- frm.add_custom_button(__('Update'), () => {
- return frm.trigger('sync');
- });
- frm.add_custom_button(__('Clear'), () => {
- return frm.trigger('clear');
- });
- frm.add_custom_button(__('Bill'), () => {
- return frm.trigger('make_invoice');
- });
- },
- clear: function(frm) {
- frm.doc.add_item = '';
- frm.doc.grand_total = 0;
- frm.doc.items = [];
- frm.refresh();
- frm.get_field('add_item').$input.focus();
- },
- restaurant_table: function(frm) {
- // select the open sales order items for this table
- if (!frm.doc.restaurant_table) {
- return;
- }
- return frappe.call({
- method: 'erpnext.restaurant.doctype.restaurant_order_entry.restaurant_order_entry.get_invoice',
- args: {
- table: frm.doc.restaurant_table
- },
- callback: (r) => {
- frm.events.set_invoice_items(frm, r);
- }
- });
- },
- sync: function(frm) {
- return frappe.call({
- method: 'erpnext.restaurant.doctype.restaurant_order_entry.restaurant_order_entry.sync',
- args: {
- table: frm.doc.restaurant_table,
- items: frm.doc.items
- },
- callback: (r) => {
- frm.events.set_invoice_items(frm, r);
- frappe.show_alert({message: __('Saved'), indicator: 'green'});
- }
- });
-
- },
- make_invoice: function(frm) {
- frm.trigger('sync').then(() => {
- frappe.prompt([
- {
- fieldname: 'customer',
- label: __('Customer'),
- fieldtype: 'Link',
- reqd: 1,
- options: 'Customer',
- 'default': frm.invoice.customer
- },
- {
- fieldname: 'mode_of_payment',
- label: __('Mode of Payment'),
- fieldtype: 'Link',
- reqd: 1,
- options: 'Mode of Payment',
- 'default': frm.mode_of_payment || ''
- }
- ], (data) => {
- // cache this for next entry
- frm.mode_of_payment = data.mode_of_payment;
- return frappe.call({
- method: 'erpnext.restaurant.doctype.restaurant_order_entry.restaurant_order_entry.make_invoice',
- args: {
- table: frm.doc.restaurant_table,
- customer: data.customer,
- mode_of_payment: data.mode_of_payment
- },
- callback: (r) => {
- frm.set_value('last_sales_invoice', r.message);
- frm.trigger('clear');
- }
- });
- },
- __("Select Customer"));
- });
- },
- set_invoice_items: function(frm, r) {
- let invoice = r.message;
- frm.doc.items = [];
- (invoice.items || []).forEach((d) => {
- frm.add_child('items', {item: d.item_code, qty: d.qty, rate: d.rate});
- });
- frm.set_value('grand_total', invoice.grand_total);
- frm.set_value('last_sales_invoice', invoice.name);
- frm.invoice = invoice;
- frm.refresh();
- }
-});
diff --git a/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.json b/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.json
deleted file mode 100644
index 3e4d593..0000000
--- a/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.json
+++ /dev/null
@@ -1,280 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 1,
- "creation": "2017-09-15 15:10:24.530365",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "restaurant_table",
- "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": "Restaurant Table",
- "length": 0,
- "no_copy": 0,
- "options": "Restaurant Table",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "restaurant_table",
- "description": "Click Enter To Add",
- "fieldname": "add_item",
- "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": "Add Item",
- "length": 0,
- "no_copy": 0,
- "options": "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,
- "unique": 0
- },
- {
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 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": 0,
- "in_standard_filter": 0,
- "label": "Grand Total",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "last_sales_invoice",
- "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": "Last Sales Invoice",
- "length": 0,
- "no_copy": 0,
- "options": "Sales Invoice",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "restaurant_table",
- "fieldname": "current_order",
- "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": "Current 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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "restaurant_table",
- "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,
- "options": "Restaurant Order Entry 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,
- "unique": 0
- }
- ],
- "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": "2017-10-04 17:06:20.926999",
- "modified_by": "Administrator",
- "module": "Restaurant",
- "name": "Restaurant Order Entry",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 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": "Restaurant Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py b/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py
deleted file mode 100644
index f9e75b4..0000000
--- a/erpnext/restaurant/doctype/restaurant_order_entry/restaurant_order_entry.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import json
-
-import frappe
-from frappe import _
-from frappe.model.document import Document
-
-from erpnext.controllers.queries import item_query
-
-
-class RestaurantOrderEntry(Document):
- pass
-
-@frappe.whitelist()
-def get_invoice(table):
- '''returns the active invoice linked to the given table'''
- invoice_name = frappe.get_value('Sales Invoice', dict(restaurant_table = table, docstatus=0))
- restaurant, menu_name = get_restaurant_and_menu_name(table)
- if invoice_name:
- invoice = frappe.get_doc('Sales Invoice', invoice_name)
- else:
- invoice = frappe.new_doc('Sales Invoice')
- invoice.naming_series = frappe.db.get_value('Restaurant', restaurant, 'invoice_series_prefix')
- invoice.is_pos = 1
- default_customer = frappe.db.get_value('Restaurant', restaurant, 'default_customer')
- if not default_customer:
- frappe.throw(_('Please set default customer in Restaurant Settings'))
- invoice.customer = default_customer
-
- invoice.taxes_and_charges = frappe.db.get_value('Restaurant', restaurant, 'default_tax_template')
- invoice.selling_price_list = frappe.db.get_value('Price List', dict(restaurant_menu=menu_name, enabled=1))
-
- return invoice
-
-@frappe.whitelist()
-def sync(table, items):
- '''Sync the sales order related to the table'''
- invoice = get_invoice(table)
- items = json.loads(items)
-
- invoice.items = []
- invoice.restaurant_table = table
- for d in items:
- invoice.append('items', dict(
- item_code = d.get('item'),
- qty = d.get('qty')
- ))
-
- invoice.save()
- return invoice.as_dict()
-
-@frappe.whitelist()
-def make_invoice(table, customer, mode_of_payment):
- '''Make table based on Sales Order'''
- restaurant, menu = get_restaurant_and_menu_name(table)
- invoice = get_invoice(table)
- invoice.customer = customer
- invoice.restaurant = restaurant
- invoice.calculate_taxes_and_totals()
- invoice.append('payments', dict(mode_of_payment=mode_of_payment, amount=invoice.grand_total))
- invoice.save()
- invoice.submit()
-
- frappe.msgprint(_('Invoice Created'), indicator='green', alert=True)
-
- return invoice.name
-
-@frappe.whitelist()
-def item_query_restaurant(doctype='Item', txt='', searchfield='name', start=0, page_len=20, filters=None, as_dict=False):
- '''Return items that are selected in active menu of the restaurant'''
- restaurant, menu = get_restaurant_and_menu_name(filters['table'])
- items = frappe.db.get_all('Restaurant Menu Item', ['item'], dict(parent = menu))
- del filters['table']
- filters['name'] = ('in', [d.item for d in items])
-
- return item_query('Item', txt, searchfield, start, page_len, filters, as_dict)
-
-def get_restaurant_and_menu_name(table):
- if not table:
- frappe.throw(_('Please select a table'))
-
- restaurant = frappe.db.get_value('Restaurant Table', table, 'restaurant')
- menu = frappe.db.get_value('Restaurant', restaurant, 'active_menu')
-
- if not menu:
- frappe.throw(_('Please set an active menu for Restaurant {0}').format(restaurant))
-
- return restaurant, menu
diff --git a/erpnext/restaurant/doctype/restaurant_order_entry_item/__init__.py b/erpnext/restaurant/doctype/restaurant_order_entry_item/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/restaurant/doctype/restaurant_order_entry_item/__init__.py
+++ /dev/null
diff --git a/erpnext/restaurant/doctype/restaurant_order_entry_item/restaurant_order_entry_item.json b/erpnext/restaurant/doctype/restaurant_order_entry_item/restaurant_order_entry_item.json
deleted file mode 100644
index 0240013..0000000
--- a/erpnext/restaurant/doctype/restaurant_order_entry_item/restaurant_order_entry_item.json
+++ /dev/null
@@ -1,163 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2017-09-15 15:11:50.313241",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 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": 0,
- "label": "Item",
- "length": 0,
- "no_copy": 0,
- "options": "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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "qty",
- "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": "Qty",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "served",
- "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": "Served",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "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,
- "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
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2017-09-21 08:39:27.232175",
- "modified_by": "Administrator",
- "module": "Restaurant",
- "name": "Restaurant Order Entry Item",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/restaurant/doctype/restaurant_order_entry_item/restaurant_order_entry_item.py b/erpnext/restaurant/doctype/restaurant_order_entry_item/restaurant_order_entry_item.py
deleted file mode 100644
index 0d9c236..0000000
--- a/erpnext/restaurant/doctype/restaurant_order_entry_item/restaurant_order_entry_item.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from frappe.model.document import Document
-
-
-class RestaurantOrderEntryItem(Document):
- pass
diff --git a/erpnext/restaurant/doctype/restaurant_reservation/__init__.py b/erpnext/restaurant/doctype/restaurant_reservation/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/restaurant/doctype/restaurant_reservation/__init__.py
+++ /dev/null
diff --git a/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.js b/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.js
deleted file mode 100644
index cebd105..0000000
--- a/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Restaurant Reservation', {
- setup: function(frm) {
- frm.add_fetch('customer', 'customer_name', 'customer_name');
- },
- refresh: function(frm) {
-
- }
-});
diff --git a/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.json b/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.json
deleted file mode 100644
index 17df2b9..0000000
--- a/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.json
+++ /dev/null
@@ -1,355 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "RES-RES-.YYYY.-.#####",
- "beta": 1,
- "creation": "2017-09-15 13:05:51.063661",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "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": "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": 0,
- "options": "Open\nWaitlisted\nCancelled\nNo Show\nSuccess",
- "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": "restaurant",
- "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": "Restaurant",
- "length": 0,
- "no_copy": 0,
- "options": "Restaurant",
- "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": "no_of_people",
- "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": "No of People",
- "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": "reservation_time",
- "fieldtype": "Datetime",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Reservation Time",
- "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": 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": "reservation_end_time",
- "fieldtype": "Datetime",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Reservation End Time",
- "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": "column_break_4",
- "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": "customer",
- "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",
- "length": 0,
- "no_copy": 0,
- "options": "Customer",
- "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": "customer_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": 1,
- "label": "Customer Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 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": "contact_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": 0,
- "label": "Contact Number",
- "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_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:38.435656",
- "modified_by": "Administrator",
- "module": "Restaurant",
- "name": "Restaurant Reservation",
- "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": "Restaurant Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "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/restaurant/doctype/restaurant_reservation/restaurant_reservation.py b/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.py
deleted file mode 100644
index 02ffaf6..0000000
--- a/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from datetime import timedelta
-
-from frappe.model.document import Document
-from frappe.utils import get_datetime
-
-
-class RestaurantReservation(Document):
- def validate(self):
- if not self.reservation_end_time:
- self.reservation_end_time = get_datetime(self.reservation_time) + timedelta(hours=1)
diff --git a/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation_calendar.js b/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation_calendar.js
deleted file mode 100644
index fe3dc57..0000000
--- a/erpnext/restaurant/doctype/restaurant_reservation/restaurant_reservation_calendar.js
+++ /dev/null
@@ -1,18 +0,0 @@
-frappe.views.calendar["Restaurant Reservation"] = {
- field_map: {
- "start": "reservation_time",
- "end": "reservation_end_time",
- "id": "name",
- "title": "customer_name",
- "allDay": "allDay",
- },
- gantt: true,
- filters: [
- {
- "fieldtype": "Data",
- "fieldname": "customer_name",
- "label": __("Customer Name")
- }
- ],
- get_events_method: "frappe.desk.calendar.get_events"
-};
diff --git a/erpnext/restaurant/doctype/restaurant_reservation/test_restaurant_reservation.py b/erpnext/restaurant/doctype/restaurant_reservation/test_restaurant_reservation.py
deleted file mode 100644
index 11a3541..0000000
--- a/erpnext/restaurant/doctype/restaurant_reservation/test_restaurant_reservation.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-
-class TestRestaurantReservation(unittest.TestCase):
- pass
diff --git a/erpnext/restaurant/doctype/restaurant_table/__init__.py b/erpnext/restaurant/doctype/restaurant_table/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/restaurant/doctype/restaurant_table/__init__.py
+++ /dev/null
diff --git a/erpnext/restaurant/doctype/restaurant_table/restaurant_table.js b/erpnext/restaurant/doctype/restaurant_table/restaurant_table.js
deleted file mode 100644
index a55605c..0000000
--- a/erpnext/restaurant/doctype/restaurant_table/restaurant_table.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('Restaurant Table', {
- refresh: function(frm) {
-
- }
-});
diff --git a/erpnext/restaurant/doctype/restaurant_table/restaurant_table.json b/erpnext/restaurant/doctype/restaurant_table/restaurant_table.json
deleted file mode 100644
index 5fc6e62..0000000
--- a/erpnext/restaurant/doctype/restaurant_table/restaurant_table.json
+++ /dev/null
@@ -1,156 +0,0 @@
-{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "",
- "beta": 1,
- "creation": "2017-09-15 12:45:24.717355",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Setup",
- "editable_grid": 1,
- "engine": "InnoDB",
- "fields": [
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "restaurant",
- "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": "Restaurant",
- "length": 0,
- "no_copy": 0,
- "options": "Restaurant",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "no_of_seats",
- "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": "No of Seats",
- "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,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "fieldname": "minimum_seating",
- "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": "Minimum Seating",
- "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,
- "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": "2017-12-09 12:13:24.382345",
- "modified_by": "Administrator",
- "module": "Restaurant",
- "name": "Restaurant Table",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [
- {
- "amend": 0,
- "apply_user_permissions": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Restaurant Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "restrict_to_domain": "Hospitality",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
-}
\ No newline at end of file
diff --git a/erpnext/restaurant/doctype/restaurant_table/restaurant_table.py b/erpnext/restaurant/doctype/restaurant_table/restaurant_table.py
deleted file mode 100644
index 29f8a1a..0000000
--- a/erpnext/restaurant/doctype/restaurant_table/restaurant_table.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import re
-
-from frappe.model.document import Document
-from frappe.model.naming import make_autoname
-
-
-class RestaurantTable(Document):
- def autoname(self):
- prefix = re.sub('-+', '-', self.restaurant.replace(' ', '-'))
- self.name = make_autoname(prefix + '-.##')
diff --git a/erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.py b/erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.py
deleted file mode 100644
index 00d14d2..0000000
--- a/erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import unittest
-
-test_records = [
- dict(restaurant='Test Restaurant 1', no_of_seats=5, minimum_seating=1),
- dict(restaurant='Test Restaurant 1', no_of_seats=5, minimum_seating=1),
- dict(restaurant='Test Restaurant 1', no_of_seats=5, minimum_seating=1),
- dict(restaurant='Test Restaurant 1', no_of_seats=5, minimum_seating=1),
-]
-
-class TestRestaurantTable(unittest.TestCase):
- pass
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index b7f74df..d74d5a6 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -142,7 +142,7 @@
self.update_lead_status()
if self.flags.is_new_doc:
- self.create_lead_address_contact()
+ self.link_lead_address_and_contact()
self.update_customer_groups()
@@ -176,62 +176,24 @@
if self.lead_name:
frappe.db.set_value("Lead", self.lead_name, "status", "Converted")
- def create_lead_address_contact(self):
+ def link_lead_address_and_contact(self):
if self.lead_name:
- # assign lead address to customer (if already not set)
- address_names = frappe.get_all('Dynamic Link', filters={
- "parenttype":"Address",
- "link_doctype":"Lead",
- "link_name":self.lead_name
- }, fields=["parent as name"])
+ # assign lead address and contact to customer (if already not set)
+ linked_contacts_and_addresses = frappe.get_all(
+ "Dynamic Link",
+ filters=[
+ ["parenttype", "in", ["Contact", "Address"]],
+ ["link_doctype", "=", "Lead"],
+ ["link_name", "=", self.lead_name],
+ ],
+ fields=["parent as name", "parenttype as doctype"],
+ )
- for address_name in address_names:
- address = frappe.get_doc('Address', address_name.get('name'))
- if not address.has_link('Customer', self.name):
- address.append('links', dict(link_doctype='Customer', link_name=self.name))
- address.save(ignore_permissions=self.flags.ignore_permissions)
-
- lead = frappe.db.get_value("Lead", self.lead_name, ["company_name", "lead_name", "email_id", "phone", "mobile_no", "gender", "salutation"], as_dict=True)
-
- if not lead.lead_name:
- frappe.throw(_("Please mention the Lead Name in Lead {0}").format(self.lead_name))
-
- contact_names = frappe.get_all('Dynamic Link', filters={
- "parenttype":"Contact",
- "link_doctype":"Lead",
- "link_name":self.lead_name
- }, fields=["parent as name"])
-
- for contact_name in contact_names:
- contact = frappe.get_doc('Contact', contact_name.get('name'))
- if not contact.has_link('Customer', self.name):
- contact.append('links', dict(link_doctype='Customer', link_name=self.name))
- contact.save(ignore_permissions=self.flags.ignore_permissions)
-
- if not contact_names:
- lead.lead_name = lead.lead_name.lstrip().split(" ")
- lead.first_name = lead.lead_name[0]
- lead.last_name = " ".join(lead.lead_name[1:])
-
- # create contact from lead
- contact = frappe.new_doc('Contact')
- contact.first_name = lead.first_name
- contact.last_name = lead.last_name
- contact.gender = lead.gender
- contact.salutation = lead.salutation
- contact.email_id = lead.email_id
- contact.phone = lead.phone
- contact.mobile_no = lead.mobile_no
- contact.is_primary_contact = 1
- contact.append('links', dict(link_doctype='Customer', link_name=self.name))
- if lead.email_id:
- contact.append('email_ids', dict(email_id=lead.email_id, is_primary=1))
- if lead.mobile_no:
- contact.append('phone_nos', dict(phone=lead.mobile_no, is_primary_mobile_no=1))
- contact.flags.ignore_permissions = self.flags.ignore_permissions
- contact.autoname()
- if not frappe.db.exists("Contact", contact.name):
- contact.insert()
+ for row in linked_contacts_and_addresses:
+ linked_doc = frappe.get_doc(row.doctype, row.name)
+ if not linked_doc.has_link('Customer', self.name):
+ linked_doc.append('links', dict(link_doctype='Customer', link_name=self.name))
+ linked_doc.save(ignore_permissions=self.flags.ignore_permissions)
def validate_name_with_customer_group(self):
if frappe.db.exists("Customer Group", self.name):
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 777b02c..dd49f13 100644
--- a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
+++ b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
@@ -23,19 +23,24 @@
row = []
outstanding_amt = get_customer_outstanding(d.name, filters.get("company"),
- ignore_outstanding_sales_order=d.bypass_credit_limit_check_at_sales_order)
+ ignore_outstanding_sales_order=d.bypass_credit_limit_check)
credit_limit = get_credit_limit(d.name, filters.get("company"))
bal = flt(credit_limit) - flt(outstanding_amt)
if customer_naming_type == "Naming Series":
- row = [d.name, d.customer_name, credit_limit, outstanding_amt, bal,
- d.bypass_credit_limit_check, d.is_frozen,
- d.disabled]
+ row = [
+ d.name, d.customer_name, credit_limit,
+ outstanding_amt, bal, d.bypass_credit_limit_check,
+ d.is_frozen, d.disabled
+ ]
else:
- row = [d.name, credit_limit, outstanding_amt, bal,
- d.bypass_credit_limit_check_at_sales_order, d.is_frozen, d.disabled]
+ row = [
+ d.name, credit_limit, outstanding_amt, bal,
+ d.bypass_credit_limit_check, d.is_frozen,
+ d.disabled
+ ]
if credit_limit:
data.append(row)
diff --git a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
index 0c0acc7..b2bf546 100644
--- a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
+++ b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
@@ -68,7 +68,8 @@
(soi.billed_amt * IFNULL(so.conversion_rate, 1)) as billed_amount,
(soi.base_amount - (soi.billed_amt * IFNULL(so.conversion_rate, 1))) as pending_amount,
soi.warehouse as warehouse,
- so.company, soi.name
+ so.company, soi.name,
+ soi.description as description
FROM
`tabSales Order` so,
(`tabSales Order Item` soi
@@ -184,6 +185,12 @@
"options": "Item",
"width": 100
})
+ columns.append({
+ "label":_("Description"),
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "width": 100
+ })
columns.extend([
{
diff --git a/erpnext/selling/workspace/retail/retail.json b/erpnext/selling/workspace/retail/retail.json
index a851ace..5bce3ca 100644
--- a/erpnext/selling/workspace/retail/retail.json
+++ b/erpnext/selling/workspace/retail/retail.json
@@ -1,6 +1,6 @@
{
"charts": [],
- "content": "[{\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Point Of Sale\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Settings & Configurations\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Loyalty Program\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Opening & Closing\", \"col\": 4}}]",
+ "content": "[{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Point Of Sale\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings & Configurations\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Loyalty Program\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Opening & Closing\",\"col\":4}}]",
"creation": "2020-03-02 17:18:32.505616",
"docstatus": 0,
"doctype": "Workspace",
@@ -14,7 +14,7 @@
"hidden": 0,
"is_query_report": 0,
"label": "Settings & Configurations",
- "link_count": 0,
+ "link_count": 2,
"onboard": 0,
"type": "Card Break"
},
@@ -44,7 +44,7 @@
"hidden": 0,
"is_query_report": 0,
"label": "Loyalty Program",
- "link_count": 0,
+ "link_count": 2,
"onboard": 0,
"type": "Card Break"
},
@@ -74,7 +74,7 @@
"hidden": 0,
"is_query_report": 0,
"label": "Opening & Closing",
- "link_count": 0,
+ "link_count": 2,
"onboard": 0,
"type": "Card Break"
},
@@ -101,7 +101,7 @@
"type": "Link"
}
],
- "modified": "2021-08-05 12:16:01.840989",
+ "modified": "2022-01-13 18:07:56.711095",
"modified_by": "Administrator",
"module": "Selling",
"name": "Retail",
@@ -110,7 +110,7 @@
"public": 1,
"restrict_to_domain": "Retail",
"roles": [],
- "sequence_id": 22,
+ "sequence_id": 22.0,
"shortcuts": [
{
"doc_view": "",
diff --git a/erpnext/selling/workspace/selling/selling.json b/erpnext/selling/workspace/selling/selling.json
index db2e6ba..a700ad8 100644
--- a/erpnext/selling/workspace/selling/selling.json
+++ b/erpnext/selling/workspace/selling/selling.json
@@ -5,7 +5,7 @@
"label": "Sales Order Trends"
}
],
- "content": "[{\"type\": \"onboarding\", \"data\": {\"onboarding_name\":\"Selling\", \"col\": 12}}, {\"type\": \"chart\", \"data\": {\"chart_name\": \"Sales Order Trends\", \"col\": 12}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Quick Access\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Item\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Sales Order\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Sales Analytics\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Sales Order Analysis\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Dashboard\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Selling\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Items and Pricing\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Settings\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Key Reports\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Other Reports\", \"col\": 4}}]",
+ "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Selling\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Sales Order Trends\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Quick Access</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Order\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Analytics\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Order Analysis\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Selling\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Items and Pricing\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]",
"creation": "2020-01-28 11:49:12.092882",
"docstatus": 0,
"doctype": "Workspace",
@@ -562,7 +562,7 @@
"type": "Link"
}
],
- "modified": "2021-08-05 12:16:01.990703",
+ "modified": "2022-01-13 17:43:02.778627",
"modified_by": "Administrator",
"module": "Selling",
"name": "Selling",
@@ -571,7 +571,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 23,
+ "sequence_id": 23.0,
"shortcuts": [
{
"color": "Grey",
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 45e8dcc..dd185fc 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -213,6 +213,9 @@
["default_payroll_payable_account", {"root_type": "Liability"}],
["round_off_account", {"root_type": "Expense"}],
["write_off_account", {"root_type": "Expense"}],
+ ["default_deferred_expense_account", {}],
+ ["default_deferred_revenue_account", {}],
+ ["default_expense_claim_payable_account", {}],
["default_discount_account", {}],
["discount_allowed_account", {"root_type": "Expense"}],
["discount_received_account", {"root_type": "Income"}],
diff --git a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py
index 2b007e9..06a79b4 100644
--- a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py
+++ b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py
@@ -62,8 +62,13 @@
if kwargs['params'].get('date') and kwargs['params'].get('from') and kwargs['params'].get('to'):
if test_exchange_values.get(kwargs['params']['date']):
return PatchResponse({'result': test_exchange_values[kwargs['params']['date']]}, 200)
+ elif args[0].startswith("https://frankfurter.app") and kwargs.get('params'):
+ if kwargs['params'].get('base') and kwargs['params'].get('symbols'):
+ date = args[0].replace("https://frankfurter.app/", "")
+ if test_exchange_values.get(date):
+ return PatchResponse({'rates': {kwargs['params'].get('symbols'): test_exchange_values.get(date)}}, 200)
- return PatchResponse({'result': None}, 404)
+ return PatchResponse({'rates': None}, 404)
@mock.patch('requests.get', side_effect=patched_requests_get)
class TestCurrencyExchange(unittest.TestCase):
@@ -102,6 +107,41 @@
self.assertFalse(exchange_rate == 60)
self.assertEqual(flt(exchange_rate, 3), 65.1)
+ def test_exchange_rate_via_exchangerate_host(self, mock_get):
+ save_new_records(test_records)
+
+ # Update Currency Exchange Rate
+ settings = frappe.get_single("Currency Exchange Settings")
+ settings.service_provider = 'exchangerate.host'
+ settings.save()
+
+ # Update exchange
+ frappe.db.set_value("Accounts Settings", None, "allow_stale", 1)
+
+ # Start with allow_stale is True
+ exchange_rate = get_exchange_rate("USD", "INR", "2016-01-01", "for_buying")
+ self.assertEqual(flt(exchange_rate, 3), 60.0)
+
+ exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15", "for_buying")
+ self.assertEqual(exchange_rate, 65.1)
+
+ exchange_rate = get_exchange_rate("USD", "INR", "2016-01-30", "for_selling")
+ self.assertEqual(exchange_rate, 62.9)
+
+ # Exchange rate as on 15th Dec, 2015
+ self.clear_cache()
+ exchange_rate = get_exchange_rate("USD", "INR", "2015-12-15", "for_selling")
+ self.assertFalse(exchange_rate == 60)
+ self.assertEqual(flt(exchange_rate, 3), 66.999)
+
+ exchange_rate = get_exchange_rate("USD", "INR", "2016-01-20", "for_buying")
+ self.assertFalse(exchange_rate == 60)
+ self.assertEqual(flt(exchange_rate, 3), 65.1)
+
+ settings = frappe.get_single("Currency Exchange Settings")
+ settings.service_provider = 'frankfurter.app'
+ settings.save()
+
def test_exchange_rate_strict(self, mock_get):
# strict currency settings
frappe.db.set_value("Accounts Settings", None, "allow_stale", 0)
diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py
index 86c9b3f..bafaab8 100644
--- a/erpnext/setup/install.py
+++ b/erpnext/setup/install.py
@@ -60,6 +60,22 @@
frappe.db.set_default("date_format", "dd-mm-yyyy")
+ setup_currency_exchange()
+
+def setup_currency_exchange():
+ ces = frappe.get_single('Currency Exchange Settings')
+ try:
+ ces.set('result_key', [])
+ ces.set('req_params', [])
+
+ ces.api_endpoint = "https://frankfurter.app/{transaction_date}"
+ ces.append('result_key', {'key': 'rates'})
+ ces.append('result_key', {'key': '{to_currency}'})
+ ces.append('req_params', {'key': 'base', 'value': '{from_currency}'})
+ ces.append('req_params', {'key': 'symbols', 'value': '{to_currency}'})
+ ces.save()
+ except frappe.ValidationError:
+ pass
def create_compact_item_print_custom_field():
create_custom_field('Print Settings', {
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index bf35259..9f0b360 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -351,7 +351,8 @@
"doctype": "UOM",
"uom_name": _(d.get("uom_name")),
"name": _(d.get("uom_name")),
- "must_be_whole_number": d.get("must_be_whole_number")
+ "must_be_whole_number": d.get("must_be_whole_number"),
+ "enabled": 1,
}).db_insert()
# bootstrap uom conversion factors
diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py
index cad4c54..4441bb9 100644
--- a/erpnext/setup/utils.py
+++ b/erpnext/setup/utils.py
@@ -100,15 +100,21 @@
if not value:
import requests
- api_url = "https://api.exchangerate.host/convert"
- response = requests.get(api_url, params={
- "date": transaction_date,
- "from": from_currency,
- "to": to_currency
- })
+ settings = frappe.get_cached_doc('Currency Exchange Settings')
+ req_params = {
+ "transaction_date": transaction_date,
+ "from_currency": from_currency,
+ "to_currency": to_currency
+ }
+ params = {}
+ for row in settings.req_params:
+ params[row.key] = format_ces_api(row.value, req_params)
+ response = requests.get(format_ces_api(settings.api_endpoint, req_params), params=params)
# expire in 6 hours
response.raise_for_status()
- value = response.json()["result"]
+ value = response.json()
+ for res_key in settings.result_key:
+ value = value[format_ces_api(str(res_key.key), req_params)]
cache.setex(name=key, time=21600, value=flt(value))
return flt(value)
except Exception:
@@ -116,6 +122,13 @@
frappe.msgprint(_("Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually").format(from_currency, to_currency, transaction_date))
return 0.0
+def format_ces_api(data, param):
+ return data.format(
+ transaction_date=param.get("transaction_date"),
+ to_currency=param.get("to_currency"),
+ from_currency=param.get("from_currency")
+ )
+
def enable_all_roles_and_domains():
""" enable all roles and domain for testing """
# add all roles to users
diff --git a/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json b/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json
index e47837f..c5640bc 100644
--- a/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json
+++ b/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json
@@ -1,6 +1,6 @@
{
"charts": [],
- "content": "[{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Projects Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"HR Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Selling Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Buying Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Support Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Shopping Cart Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Portal Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Domain Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Products Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Naming Series\",\"col\":4}}]",
+ "content": "[{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Projects Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"HR Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Selling Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Buying Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Support Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Shopping Cart Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Portal Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Domain Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Products Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Naming Series\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Manufacturing Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Education Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Hotel Settings\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"CRM Settings\",\"col\":3}}]",
"creation": "2020-03-12 14:47:51.166455",
"docstatus": 0,
"doctype": "Workspace",
@@ -10,7 +10,7 @@
"idx": 0,
"label": "ERPNext Settings",
"links": [],
- "modified": "2021-11-05 21:32:55.323591",
+ "modified": "2022-01-13 19:18:59.362820",
"modified_by": "Administrator",
"module": "Setup",
"name": "ERPNext Settings",
@@ -19,7 +19,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 12,
+ "sequence_id": 12.0,
"shortcuts": [
{
"icon": "project",
@@ -105,13 +105,6 @@
"type": "DocType"
},
{
- "icon": "non-profit",
- "label": "Healthcare Settings",
- "link_to": "Healthcare Settings",
- "restrict_to_domain": "Healthcare",
- "type": "DocType"
- },
- {
"icon": "setting",
"label": "Domain Settings",
"link_to": "Domain Settings",
diff --git a/erpnext/setup/workspace/home/home.json b/erpnext/setup/workspace/home/home.json
index f9c585c0..19ff2a0 100644
--- a/erpnext/setup/workspace/home/home.json
+++ b/erpnext/setup/workspace/home/home.json
@@ -1,18 +1,13 @@
{
"charts": [],
- "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Home\",\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Customer\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Supplier\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Leaderboard\",\"col\":4}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Human Resources\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"CRM\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Data Import and Settings\",\"col\":4}}]",
+ "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Home\",\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Customer\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Supplier\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Leaderboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Human Resources\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"CRM\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Data Import and Settings\",\"col\":4}}]",
"creation": "2020-01-23 13:46:38.833076",
- "developer_mode_only": 0,
- "disable_user_customization": 0,
"docstatus": 0,
"doctype": "Workspace",
- "extends_another_page": 0,
"for_user": "",
"hide_custom": 0,
"icon": "getting-started",
"idx": 0,
- "is_default": 0,
- "is_standard": 0,
"label": "Home",
"links": [
{
@@ -276,18 +271,16 @@
"type": "Link"
}
],
- "modified": "2021-11-22 12:50:15.771366",
+ "modified": "2022-01-13 17:24:17.002665",
"modified_by": "Administrator",
"module": "Setup",
"name": "Home",
"owner": "Administrator",
"parent_page": "",
- "pin_to_bottom": 0,
- "pin_to_top": 0,
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 1,
+ "sequence_id": 1.0,
"shortcuts": [
{
"label": "Item",
diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py
index 5593101..96751d6 100644
--- a/erpnext/stock/doctype/batch/batch.py
+++ b/erpnext/stock/doctype/batch/batch.py
@@ -292,6 +292,7 @@
join `tabStock Ledger Entry` ignore index (item_code, warehouse)
on (`tabBatch`.batch_id = `tabStock Ledger Entry`.batch_no )
where `tabStock Ledger Entry`.item_code = %s and `tabStock Ledger Entry`.warehouse = %s
+ and `tabStock Ledger Entry`.is_cancelled = 0
and (`tabBatch`.expiry_date >= CURDATE() or `tabBatch`.expiry_date IS NULL) {0}
group by batch_id
order by `tabBatch`.expiry_date ASC, `tabBatch`.creation ASC
@@ -336,4 +337,4 @@
).run()
flt_reserved_batch_qty = flt(reserved_batch_qty[0][0])
- return flt_reserved_batch_qty
\ No newline at end of file
+ return flt_reserved_batch_qty
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index 70d48a4..d1e2244 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -14,6 +14,7 @@
from erpnext.controllers.selling_controller import SellingController
from erpnext.stock.doctype.batch.batch import set_batch_nos
from erpnext.stock.doctype.serial_no.serial_no import get_delivery_note_serial_no
+from erpnext.stock.utils import calculate_mapped_packed_items_return
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@@ -128,8 +129,12 @@
self.validate_uom_is_integer("uom", "qty")
self.validate_with_previous_doc()
- from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
- make_packing_list(self)
+ # Keeps mapped packed_items in case product bundle is updated.
+ if self.is_return and self.return_against:
+ calculate_mapped_packed_items_return(self)
+ else:
+ from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
+ make_packing_list(self)
if self._action != 'submit' and not self.is_return:
set_batch_nos(self, 'warehouse', throw=True)
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index 4f89a19..bd18e78 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -386,8 +386,7 @@
self.assertEqual(actual_qty, 25)
# return bundled item
- dn1 = create_delivery_note(item_code='_Test Product Bundle Item', is_return=1,
- return_against=dn.name, qty=-2, rate=500, company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1")
+ dn1 = create_return_delivery_note(source_name=dn.name, rate=500, qty=-2)
# qty after return
actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1")
@@ -823,6 +822,15 @@
automatically_fetch_payment_terms(enable=0)
+def create_return_delivery_note(**args):
+ args = frappe._dict(args)
+ from erpnext.controllers.sales_and_purchase_return import make_return_doc
+ doc = make_return_doc("Delivery Note", args.source_name, None)
+ doc.items[0].rate = args.rate
+ doc.items[0].qty = args.qty
+ doc.submit()
+ return doc
+
def create_delivery_note(**args):
dn = frappe.new_doc("Delivery Note")
args = frappe._dict(args)
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 29abd45..2d28cc0 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -28,6 +28,7 @@
"standard_rate",
"is_fixed_asset",
"auto_create_assets",
+ "is_grouped_asset",
"asset_category",
"asset_naming_series",
"over_delivery_receipt_allowance",
@@ -1026,6 +1027,13 @@
"fieldname": "grant_commission",
"fieldtype": "Check",
"label": "Grant Commission"
+ },
+ {
+ "default": "0",
+ "depends_on": "auto_create_assets",
+ "fieldname": "is_grouped_asset",
+ "fieldtype": "Check",
+ "label": "Create Grouped Asset"
}
],
"has_web_view": 1,
@@ -1034,7 +1042,7 @@
"image_field": "image",
"index_web_pages_for_search": 1,
"links": [],
- "modified": "2021-12-14 04:13:16.857534",
+ "modified": "2022-01-18 12:57:54.273202",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",
@@ -1104,6 +1112,7 @@
"show_preview_popup": 1,
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
"title_field": "item_name",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index decf522..d99fadc 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -492,18 +492,20 @@
context.shopping_cart = get_product_info_for_website(self.name, skip_quotation_creation=True)
def add_default_uom_in_conversion_factor_table(self):
- uom_conv_list = [d.uom for d in self.get("uoms")]
- if self.stock_uom not in uom_conv_list:
- ch = self.append('uoms', {})
- ch.uom = self.stock_uom
- ch.conversion_factor = 1
+ if not self.is_new() and self.has_value_changed("stock_uom"):
+ self.uoms = []
+ frappe.msgprint(
+ _("Successfully changed Stock UOM, please redefine conversion factors for new UOM."),
+ alert=True,
+ )
- to_remove = []
- for d in self.get("uoms"):
- if d.conversion_factor == 1 and d.uom != self.stock_uom:
- to_remove.append(d)
+ uoms_list = [d.uom for d in self.get("uoms")]
- [self.remove(d) for d in to_remove]
+ if self.stock_uom not in uoms_list:
+ self.append("uoms", {
+ "uom": self.stock_uom,
+ "conversion_factor": 1
+ })
def update_show_in_website(self):
if self.disabled:
@@ -600,14 +602,6 @@
frappe.throw(_("Barcode {0} is not a valid {1} code").format(
item_barcode.barcode, item_barcode.barcode_type), InvalidBarcode)
- if item_barcode.barcode != item_barcode.name:
- # if barcode is getting updated , the row name has to reset.
- # Delete previous old row doc and re-enter row as if new to reset name in db.
- item_barcode.set("__islocal", True)
- item_barcode_entry_name = item_barcode.name
- item_barcode.name = None
- frappe.delete_doc("Item Barcode", item_barcode_entry_name)
-
def validate_warehouse_for_reorder(self):
'''Validate Reorder level table for duplicate and conditional mandatory'''
warehouse = []
diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py
index 4028d93..0957ce0 100644
--- a/erpnext/stock/doctype/item/test_item.py
+++ b/erpnext/stock/doctype/item/test_item.py
@@ -584,6 +584,16 @@
except frappe.ValidationError as e:
self.fail(f"UoM change not allowed even though no SLE / BIN with positive qty exists: {e}")
+ def test_erasure_of_old_conversions(self):
+ item = create_item("_item change uom")
+ item.stock_uom = "Gram"
+ item.append("uoms", frappe._dict(uom="Box", conversion_factor=2))
+ item.save()
+ item.reload()
+ item.stock_uom = "Nos"
+ item.save()
+ self.assertEqual(len(item.uoms), 1)
+
def test_validate_stock_item(self):
self.assertRaises(frappe.ValidationError, validate_is_stock_item, "_Test Non Stock Item")
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.json b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.json
index cd7e63b..0ba97d5 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.json
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.json
@@ -1,7 +1,7 @@
{
"actions": [],
"autoname": "REPOST-ITEM-VAL-.######",
- "creation": "2020-10-22 22:27:07.742161",
+ "creation": "2022-01-11 15:03:38.273179",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
@@ -129,7 +129,7 @@
"reqd": 1
},
{
- "default": "0",
+ "default": "1",
"fieldname": "allow_negative_stock",
"fieldtype": "Check",
"label": "Allow Negative Stock"
@@ -177,7 +177,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-11-24 02:18:10.524560",
+ "modified": "2022-01-18 10:57:33.450907",
"modified_by": "Administrator",
"module": "Stock",
"name": "Repost Item Valuation",
@@ -227,5 +227,6 @@
}
],
"sort_field": "modified",
- "sort_order": "DESC"
-}
+ "sort_order": "DESC",
+ "states": []
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
index fb3b355..01c5e3e 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
@@ -27,8 +27,7 @@
self.item_code = None
self.warehouse = None
- self.allow_negative_stock = self.allow_negative_stock or \
- cint(frappe.db.get_single_value("Stock Settings", "allow_negative_stock"))
+ self.allow_negative_stock = 1
def set_company(self):
if self.based_on == "Transaction":
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index 2947faf..ee55af3 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -402,10 +402,16 @@
def get_auto_serial_nos(serial_no_series, qty):
serial_nos = []
for i in range(cint(qty)):
- serial_nos.append(make_autoname(serial_no_series, "Serial No"))
+ serial_nos.append(get_new_serial_number(serial_no_series))
return "\n".join(serial_nos)
+def get_new_serial_number(series):
+ sr_no = make_autoname(series, "Serial No")
+ if frappe.db.exists("Serial No", sr_no):
+ sr_no = get_new_serial_number(series)
+ return sr_no
+
def auto_make_serial_nos(args):
serial_nos = get_serial_nos(args.get('serial_no'))
created_numbers = []
diff --git a/erpnext/stock/doctype/serial_no/test_serial_no.py b/erpnext/stock/doctype/serial_no/test_serial_no.py
index 99000d1..f8cea71 100644
--- a/erpnext/stock/doctype/serial_no/test_serial_no.py
+++ b/erpnext/stock/doctype/serial_no/test_serial_no.py
@@ -8,8 +8,10 @@
import frappe
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
+from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
+from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
@@ -21,6 +23,10 @@
class TestSerialNo(ERPNextTestCase):
+
+ def tearDown(self):
+ frappe.db.rollback()
+
def test_cannot_create_direct(self):
frappe.delete_doc_if_exists("Serial No", "_TCSER0001")
@@ -176,6 +182,24 @@
self.assertEqual(sn_doc.warehouse, "_Test Warehouse - _TC")
self.assertEqual(sn_doc.purchase_document_no, se.name)
+ def test_auto_creation_of_serial_no(self):
+ """
+ Test if auto created Serial No excludes existing serial numbers
+ """
+ item_code = make_item("_Test Auto Serial Item ", {
+ "has_serial_no": 1,
+ "serial_no_series": "XYZ.###"
+ }).item_code
+
+ # Reserve XYZ005
+ pr_1 = make_purchase_receipt(item_code=item_code, qty=1, serial_no="XYZ005")
+ # XYZ005 is already used and will throw an error if used again
+ pr_2 = make_purchase_receipt(item_code=item_code, qty=10)
+
+ self.assertEqual(get_serial_nos(pr_1.get("items")[0].serial_no)[0], "XYZ005")
+ for serial_no in get_serial_nos(pr_2.get("items")[0].serial_no):
+ self.assertNotEqual(serial_no, "XYZ005")
+
def test_serial_no_sanitation(self):
"Test if Serial No input is sanitised before entering the DB."
item_code = "_Test Serialized Item"
@@ -192,7 +216,28 @@
self.assertEqual(se.get("items")[0].serial_no, "_TS1\n_TS2\n_TS3\n_TS4 - 2021")
- frappe.db.rollback()
+ def test_correct_serial_no_incoming_rate(self):
+ """ Check correct consumption rate based on serial no record.
+ """
+ item_code = "_Test Serialized Item"
+ warehouse = "_Test Warehouse - _TC"
+ serial_nos = ["LOWVALUATION", "HIGHVALUATION"]
- def tearDown(self):
- frappe.db.rollback()
+ in1 = make_stock_entry(item_code=item_code, to_warehouse=warehouse, qty=1, rate=42,
+ serial_no=serial_nos[0])
+ in2 = make_stock_entry(item_code=item_code, to_warehouse=warehouse, qty=1, rate=113,
+ serial_no=serial_nos[1])
+
+ out = create_delivery_note(item_code=item_code, qty=1, serial_no=serial_nos[0], do_not_submit=True)
+
+ # change serial no
+ out.items[0].serial_no = serial_nos[1]
+ out.save()
+ out.submit()
+
+ value_diff = frappe.db.get_value("Stock Ledger Entry",
+ {"voucher_no": out.name, "voucher_type": "Delivery Note"},
+ "stock_value_difference"
+ )
+ self.assertEqual(value_diff, -113)
+
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 93e303c..a61b319 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -8,6 +8,7 @@
import frappe
from frappe import _
from frappe.model.mapper import get_mapped_doc
+from frappe.query_builder.functions import Sum
from frappe.utils import cint, comma_or, cstr, flt, format_time, formatdate, getdate, nowdate
import erpnext
@@ -85,8 +86,11 @@
self.validate_warehouse()
self.validate_work_order()
self.validate_bom()
- self.mark_finished_and_scrap_items()
- self.validate_finished_goods()
+
+ if self.purpose in ("Manufacture", "Repack"):
+ self.mark_finished_and_scrap_items()
+ self.validate_finished_goods()
+
self.validate_with_material_request()
self.validate_batch()
self.validate_inspection()
@@ -109,8 +113,12 @@
self.set_actual_qty()
self.calculate_rate_and_amount()
self.validate_putaway_capacity()
- self.reset_default_field_value("from_warehouse", "items", "s_warehouse")
- self.reset_default_field_value("to_warehouse", "items", "t_warehouse")
+
+ if not self.get("purpose") == "Manufacture":
+ # ignore scrap item wh difference and empty source/target wh
+ # in Manufacture Entry
+ self.reset_default_field_value("from_warehouse", "items", "s_warehouse")
+ self.reset_default_field_value("to_warehouse", "items", "t_warehouse")
def on_submit(self):
self.update_stock_ledger()
@@ -701,26 +709,25 @@
validate_bom_no(item_code, d.bom_no)
def mark_finished_and_scrap_items(self):
- if self.purpose in ("Repack", "Manufacture"):
- if any([d.item_code for d in self.items if (d.is_finished_item and d.t_warehouse)]):
- return
+ if any([d.item_code for d in self.items if (d.is_finished_item and d.t_warehouse)]):
+ return
- finished_item = self.get_finished_item()
+ finished_item = self.get_finished_item()
- if not finished_item and self.purpose == "Manufacture":
- # In case of independent Manufacture entry, don't auto set
- # user must decide and set
- return
+ if not finished_item and self.purpose == "Manufacture":
+ # In case of independent Manufacture entry, don't auto set
+ # user must decide and set
+ return
- for d in self.items:
- if d.t_warehouse and not d.s_warehouse:
- if self.purpose=="Repack" or d.item_code == finished_item:
- d.is_finished_item = 1
- else:
- d.is_scrap_item = 1
+ for d in self.items:
+ if d.t_warehouse and not d.s_warehouse:
+ if self.purpose=="Repack" or d.item_code == finished_item:
+ d.is_finished_item = 1
else:
- d.is_finished_item = 0
- d.is_scrap_item = 0
+ d.is_scrap_item = 1
+ else:
+ d.is_finished_item = 0
+ d.is_scrap_item = 0
def get_finished_item(self):
finished_item = None
@@ -733,9 +740,9 @@
def validate_finished_goods(self):
"""
- 1. Check if FG exists
- 2. Check if Multiple FG Items are present
- 3. Check FG Item and Qty against WO if present
+ 1. Check if FG exists (mfg, repack)
+ 2. Check if Multiple FG Items are present (mfg)
+ 3. Check FG Item and Qty against WO if present (mfg)
"""
production_item, wo_qty, finished_items = None, 0, []
@@ -748,8 +755,9 @@
for d in self.get('items'):
if d.is_finished_item:
if not self.work_order:
+ # Independent MFG Entry/ Repack Entry, no WO to match against
finished_items.append(d.item_code)
- continue # Independent Manufacture Entry, no WO to match against
+ continue
if d.item_code != production_item:
frappe.throw(_("Finished Item {0} does not match with Work Order {1}")
@@ -762,19 +770,17 @@
finished_items.append(d.item_code)
- if len(set(finished_items)) > 1:
+ if not finished_items:
frappe.throw(
- msg=_("Multiple items cannot be marked as finished item"),
- title=_("Note"),
- exc=FinishedGoodError
+ msg=_("There must be atleast 1 Finished Good in this Stock Entry").format(self.name),
+ title=_("Missing Finished Good"), exc=FinishedGoodError
)
if self.purpose == "Manufacture":
- if not finished_items:
+ if len(set(finished_items)) > 1:
frappe.throw(
- msg=_("There must be atleast 1 Finished Good in this Stock Entry").format(self.name),
- title=_("Missing Finished Good"),
- exc=FinishedGoodError
+ msg=_("Multiple items cannot be marked as finished item"),
+ title=_("Note"), exc=FinishedGoodError
)
allowance_percentage = flt(
@@ -1275,22 +1281,29 @@
if not self.pro_doc:
self.set_work_order_details()
- scrap_items = frappe.db.sql('''
- SELECT
- JCSI.item_code, JCSI.item_name, SUM(JCSI.stock_qty) as stock_qty, JCSI.stock_uom, JCSI.description
- FROM
- `tabJob Card` JC, `tabJob Card Scrap Item` JCSI
- WHERE
- JCSI.parent = JC.name AND JC.docstatus = 1
- AND JCSI.item_code IS NOT NULL AND JC.work_order = %s
- GROUP BY
- JCSI.item_code
- ''', self.work_order, as_dict=1)
-
- pending_qty = flt(self.pro_doc.qty) - flt(self.pro_doc.produced_qty)
- if pending_qty <=0:
+ if not self.pro_doc.operations:
return []
+ job_card = frappe.qb.DocType('Job Card')
+ job_card_scrap_item = frappe.qb.DocType('Job Card Scrap Item')
+
+ scrap_items = (
+ frappe.qb.from_(job_card)
+ .select(
+ Sum(job_card_scrap_item.stock_qty).as_('stock_qty'),
+ job_card_scrap_item.item_code, job_card_scrap_item.item_name,
+ job_card_scrap_item.description, job_card_scrap_item.stock_uom)
+ .join(job_card_scrap_item)
+ .on(job_card_scrap_item.parent == job_card.name)
+ .where(
+ (job_card_scrap_item.item_code.isnotnull())
+ & (job_card.work_order == self.work_order)
+ & (job_card.docstatus == 1))
+ .groupby(job_card_scrap_item.item_code)
+ ).run(as_dict=1)
+
+ pending_qty = flt(self.get_completed_job_card_qty()) - flt(self.pro_doc.produced_qty)
+
used_scrap_items = self.get_used_scrap_items()
for row in scrap_items:
row.stock_qty -= flt(used_scrap_items.get(row.item_code))
@@ -1304,6 +1317,9 @@
return scrap_items
+ def get_completed_job_card_qty(self):
+ return flt(min([d.completed_qty for d in self.pro_doc.operations]))
+
def get_used_scrap_items(self):
used_scrap_items = defaultdict(float)
data = frappe.get_all(
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index b874874..306f2c3 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -226,9 +226,47 @@
mtn.cancel()
- def test_repack_no_change_in_valuation(self):
- company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
+ def test_repack_multiple_fg(self):
+ "Test `is_finished_item` for one item repacked into two items."
+ make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=100, basic_rate=100)
+ repack = frappe.copy_doc(test_records[3])
+ repack.posting_date = nowdate()
+ repack.posting_time = nowtime()
+
+ repack.items[0].qty = 100.0
+ repack.items[0].transfer_qty = 100.0
+ repack.items[1].qty = 50.0
+
+ repack.append("items", {
+ "conversion_factor": 1.0,
+ "cost_center": "_Test Cost Center - _TC",
+ "doctype": "Stock Entry Detail",
+ "expense_account": "Stock Adjustment - _TC",
+ "basic_rate": 150,
+ "item_code": "_Test Item 2",
+ "parentfield": "items",
+ "qty": 50.0,
+ "stock_uom": "_Test UOM",
+ "t_warehouse": "_Test Warehouse - _TC",
+ "transfer_qty": 50.0,
+ "uom": "_Test UOM"
+ })
+ repack.set_stock_entry_type()
+ repack.insert()
+
+ self.assertEqual(repack.items[1].is_finished_item, 1)
+ self.assertEqual(repack.items[2].is_finished_item, 1)
+
+ repack.items[1].is_finished_item = 0
+ repack.items[2].is_finished_item = 0
+
+ # must raise error if 0 fg in repack entry
+ self.assertRaises(FinishedGoodError, repack.validate_finished_goods)
+
+ repack.delete() # teardown
+
+ def test_repack_no_change_in_valuation(self):
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC",
qty=50, basic_rate=100)
@@ -813,6 +851,34 @@
self.assertEqual(se.get("items")[0].allow_zero_valuation_rate, 1)
self.assertEqual(se.get("items")[0].amount, 0)
+ def test_zero_incoming_rate(self):
+ """ Make sure incoming rate of 0 is allowed while consuming.
+
+ qty | rate | valuation rate
+ 1 | 100 | 100
+ 1 | 0 | 50
+ -1 | 100 | 0
+ -1 | 0 <--- assert this
+ """
+ item_code = "_TestZeroVal"
+ warehouse = "_Test Warehouse - _TC"
+ create_item('_TestZeroVal')
+ _receipt = make_stock_entry(item_code=item_code, qty=1, to_warehouse=warehouse, rate=100)
+ receipt2 = make_stock_entry(item_code=item_code, qty=1, to_warehouse=warehouse, rate=0, do_not_save=True)
+ receipt2.items[0].allow_zero_valuation_rate = 1
+ receipt2.save()
+ receipt2.submit()
+
+ issue = make_stock_entry(item_code=item_code, qty=1, from_warehouse=warehouse)
+
+ value_diff = frappe.db.get_value("Stock Ledger Entry", {"voucher_no": issue.name, "voucher_type": "Stock Entry"}, "stock_value_difference")
+ self.assertEqual(value_diff, -100)
+
+ issue2 = make_stock_entry(item_code=item_code, qty=1, from_warehouse=warehouse)
+ value_diff = frappe.db.get_value("Stock Ledger Entry", {"voucher_no": issue2.name, "voucher_type": "Stock Entry"}, "stock_value_difference")
+ self.assertEqual(value_diff, 0)
+
+
def test_gle_for_opening_stock_entry(self):
mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1",
company="_Test Company with perpetual inventory", qty=50, basic_rate=100,
diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
index cafbd75..a1030d5 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
@@ -5,7 +5,10 @@
from frappe.core.page.permission_manager.permission_manager import reset
from frappe.utils import add_days, today
-from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
+from erpnext.stock.doctype.delivery_note.test_delivery_note import (
+ create_delivery_note,
+ create_return_delivery_note,
+)
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.landed_cost_voucher.test_landed_cost_voucher import (
create_landed_cost_voucher,
@@ -232,8 +235,7 @@
self.assertEqual(outgoing_rate, 100)
# Return Entry: Qty = -2, Rate = 150
- return_dn = create_delivery_note(is_return=1, return_against=dn.name, item_code=bundled_item, qty=-2, rate=150,
- company=company, warehouse="Stores - _TC", expense_account="Cost of Goods Sold - _TC", cost_center="Main - _TC")
+ return_dn = create_return_delivery_note(source_name=dn.name, rate=150, qty=-2)
# check incoming rate for Return entry
incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry",
diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
index c4ddc9e..428370c 100644
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
@@ -6,7 +6,7 @@
import frappe
-from frappe.utils import add_days, flt, nowdate, nowtime, random_string
+from frappe.utils import add_days, cstr, flt, nowdate, nowtime, random_string
from erpnext.accounts.utils import get_stock_and_account_balance
from erpnext.stock.doctype.item.test_item import create_item
@@ -439,8 +439,8 @@
self.assertRaises(frappe.ValidationError, sr.submit)
def test_serial_no_cancellation(self):
-
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
+
item = create_item("Stock-Reco-Serial-Item-9", is_stock_item=1)
if not item.has_serial_no:
item.has_serial_no = 1
@@ -466,6 +466,31 @@
self.assertEqual(len(active_sr_no), 10)
+ def test_serial_no_creation_and_inactivation(self):
+ item = create_item("_TestItemCreatedWithStockReco", is_stock_item=1)
+ if not item.has_serial_no:
+ item.has_serial_no = 1
+ item.save()
+
+ item_code = item.name
+ warehouse = "_Test Warehouse - _TC"
+
+ sr = create_stock_reconciliation(item_code=item.name, warehouse=warehouse,
+ serial_no="SR-CREATED-SR-NO", qty=1, do_not_submit=True, rate=100)
+ sr.save()
+ self.assertEqual(cstr(sr.items[0].current_serial_no), "")
+ sr.submit()
+
+ active_sr_no = frappe.get_all("Serial No",
+ filters={"item_code": item_code, "warehouse": warehouse, "status": "Active"})
+ self.assertEqual(len(active_sr_no), 1)
+
+ sr.cancel()
+ active_sr_no = frappe.get_all("Serial No",
+ filters={"item_code": item_code, "warehouse": warehouse, "status": "Active"})
+ self.assertEqual(len(active_sr_no), 0)
+
+
def create_batch_item_with_batch(item_name, batch_id):
batch_item_doc = create_item(item_name, is_stock_item=1)
if not batch_item_doc.has_batch_no:
diff --git a/erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py b/erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py
index 44e1386..87097c7 100644
--- a/erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py
+++ b/erpnext/stock/report/batch_item_expiry_status/batch_item_expiry_status.py
@@ -55,7 +55,8 @@
return frappe.db.sql("""select item_code, batch_no, warehouse,
posting_date, actual_qty
from `tabStock Ledger Entry`
- where docstatus < 2 and ifnull(batch_no, '') != '' %s order by item_code, warehouse""" %
+ where is_cancelled = 0
+ and docstatus < 2 and ifnull(batch_no, '') != '' %s order by item_code, warehouse""" %
conditions, as_dict=1)
def get_item_warehouse_batch_map(filters, float_precision):
diff --git a/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py b/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py
index 5f6184d..058af77 100644
--- a/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py
+++ b/erpnext/stock/report/cogs_by_item_group/cogs_by_item_group.py
@@ -91,7 +91,7 @@
voucher_nos = [fe.get('voucher_no') for fe in filtered_entries]
svd_list = frappe.get_list(
'Stock Ledger Entry', fields=['item_code','stock_value_difference'],
- filters=[('voucher_no', 'in', voucher_nos)]
+ filters=[('voucher_no', 'in', voucher_nos), ("is_cancelled", "=", 0)]
)
assign_item_groups_to_svd_list(svd_list)
return svd_list
diff --git a/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py b/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py
index d452ffd..be8597d 100644
--- a/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py
+++ b/erpnext/stock/report/incorrect_serial_no_valuation/incorrect_serial_no_valuation.py
@@ -73,7 +73,7 @@
fields = ['name', 'voucher_type', 'voucher_no', 'item_code', 'serial_no as serial_nos', 'actual_qty',
'posting_date', 'posting_time', 'company', 'warehouse', '(stock_value_difference / actual_qty) as valuation_rate']
- filters = {'serial_no': ("is", "set")}
+ filters = {'serial_no': ("is", "set"), "is_cancelled": 0}
if report_filters.get('item_code'):
filters['item_code'] = report_filters.get('item_code')
diff --git a/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py b/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py
index 3f49065..cfa1e47 100644
--- a/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py
+++ b/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py
@@ -76,6 +76,7 @@
on sle.voucher_no = se.name
where
actual_qty < 0
+ and is_cancelled = 0
and voucher_type not in ('Delivery Note', 'Sales Invoice')
%s
group by item_code""" % condition, as_dict=1)
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 107bb23..0a7ab40 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -105,6 +105,7 @@
def validate_serial_no(sle):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
+
for sn in get_serial_nos(sle.serial_no):
args = copy.deepcopy(sle)
args.serial_no = sn
@@ -423,6 +424,8 @@
return sorted(entries_to_fix, key=lambda k: k['timestamp'])
def process_sle(self, sle):
+ from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
+
# previous sle data for this warehouse
self.wh_data = self.data[sle.warehouse]
@@ -437,7 +440,7 @@
if not self.args.get("sle_id"):
self.get_dynamic_incoming_outgoing_rate(sle)
- if sle.serial_no:
+ if get_serial_nos(sle.serial_no):
self.get_serialized_values(sle)
self.wh_data.qty_after_transaction += flt(sle.actual_qty)
if sle.voucher_type == "Stock Reconciliation":
@@ -449,8 +452,9 @@
# assert
self.wh_data.valuation_rate = sle.valuation_rate
self.wh_data.qty_after_transaction = sle.qty_after_transaction
- self.wh_data.stock_queue = [[self.wh_data.qty_after_transaction, self.wh_data.valuation_rate]]
self.wh_data.stock_value = flt(self.wh_data.qty_after_transaction) * flt(self.wh_data.valuation_rate)
+ if self.valuation_method != "Moving Average":
+ self.wh_data.stock_queue = [[self.wh_data.qty_after_transaction, self.wh_data.valuation_rate]]
else:
if self.valuation_method == "Moving Average":
self.get_moving_average_values(sle)
@@ -602,9 +606,9 @@
incoming_rate = self.wh_data.valuation_rate
stock_value_change = 0
- if incoming_rate:
+ if actual_qty > 0:
stock_value_change = actual_qty * incoming_rate
- elif actual_qty < 0:
+ else:
# In case of delivery/stock issue, get average purchase rate
# of serial nos of current entry
if not sle.is_cancelled:
@@ -646,6 +650,7 @@
where
company = %s
and actual_qty > 0
+ and is_cancelled = 0
and (serial_no = %s
or serial_no like %s
or serial_no like %s
@@ -901,6 +906,7 @@
item_code = %s
AND warehouse = %s
AND valuation_rate >= 0
+ AND is_cancelled = 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))
@@ -911,6 +917,7 @@
where
item_code = %s
AND valuation_rate > 0
+ AND is_cancelled = 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))
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 3c70b41..f620c18 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -103,7 +103,7 @@
serial_nos = get_serial_nos_data_after_transactions(args)
return ((last_entry.qty_after_transaction, last_entry.valuation_rate, serial_nos)
- if last_entry else (0.0, 0.0, 0.0))
+ if last_entry else (0.0, 0.0, None))
else:
return (last_entry.qty_after_transaction, last_entry.valuation_rate) if last_entry else (0.0, 0.0)
else:
@@ -419,6 +419,19 @@
if reposting_in_progress:
frappe.msgprint(_("Item valuation reposting in progress. Report might show incorrect item valuation."), alert=1)
+
+def calculate_mapped_packed_items_return(return_doc):
+ parent_items = set([item.parent_item for item in return_doc.packed_items])
+ against_doc = frappe.get_doc(return_doc.doctype, return_doc.return_against)
+
+ for original_bundle, returned_bundle in zip(against_doc.items, return_doc.items):
+ if original_bundle.item_code in parent_items:
+ for returned_packed_item, original_packed_item in zip(return_doc.packed_items, against_doc.packed_items):
+ if returned_packed_item.parent_item == original_bundle.item_code:
+ returned_packed_item.parent_detail_docname = returned_bundle.name
+ returned_packed_item.qty = (original_packed_item.qty / original_bundle.qty) * returned_bundle.qty
+
+
def check_pending_reposting(posting_date: str, throw_error: bool = True) -> bool:
"""Check if there are pending reposting job till the specified posting date."""
diff --git a/erpnext/stock/workspace/stock/stock.json b/erpnext/stock/workspace/stock/stock.json
index 4df27f5..ed33067 100644
--- a/erpnext/stock/workspace/stock/stock.json
+++ b/erpnext/stock/workspace/stock/stock.json
@@ -1,10 +1,11 @@
{
"charts": [
{
- "chart_name": "Warehouse wise Stock Value"
+ "chart_name": "Warehouse wise Stock Value",
+ "label": "Warehouse wise Stock Value"
}
],
- "content": "[{\"type\": \"onboarding\", \"data\": {\"onboarding_name\":\"Stock\", \"col\": 12}}, {\"type\": \"chart\", \"data\": {\"chart_name\": null, \"col\": 12}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Quick Access\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Item\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Material Request\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Stock Entry\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Purchase Receipt\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Delivery Note\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Stock Ledger\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Stock Balance\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Dashboard\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Masters & Reports\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Items and Pricing\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Stock Transactions\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Stock Reports\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Settings\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Serial No and Batch\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Tools\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Key Reports\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Other Reports\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Incorrect Data Report\", \"col\": 4}}]",
+ "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Stock\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Warehouse wise Stock Value\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Quick Access</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Material Request\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Entry\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Receipt\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Delivery Note\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Ledger\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Balance\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Masters & Reports</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Items and Pricing\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock Transactions\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Serial No and Batch\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]",
"creation": "2020-03-02 15:43:10.096528",
"docstatus": 0,
"doctype": "Workspace",
@@ -706,7 +707,7 @@
"type": "Link"
}
],
- "modified": "2021-11-23 04:34:00.420870",
+ "modified": "2022-01-13 17:47:38.339931",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock",
@@ -715,7 +716,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 24,
+ "sequence_id": 24.0,
"shortcuts": [
{
"color": "Green",
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index d5e5b78..e211e24 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -236,7 +236,7 @@
return False
def calculate_first_response_time(issue, first_responded_on):
- issue_creation_date = issue.creation
+ issue_creation_date = issue.service_level_agreement_creation or issue.creation
issue_creation_time = get_time_in_seconds(issue_creation_date)
first_responded_on_in_seconds = get_time_in_seconds(first_responded_on)
support_hours = frappe.get_cached_doc("Service Level Agreement", issue.service_level_agreement).support_and_resolution
diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js
index bfbffe2..4dbb0e7 100644
--- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js
+++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js
@@ -111,6 +111,7 @@
filters: [
['DocType', 'issingle', '=', 0],
['DocType', 'istable', '=', 0],
+ ['DocType', 'is_submittable', '=', 0],
['DocType', 'name', 'not in', invalid_doctypes],
['DocType', 'module', 'not in', ["Email", "Core", "Custom", "Event Streaming", "Social", "Data Migration", "Geo", "Desk"]]
]
diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py
index b3348f1..526b6aa 100644
--- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py
+++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py
@@ -29,6 +29,7 @@
class ServiceLevelAgreement(Document):
def validate(self):
+ self.validate_selected_doctype()
self.validate_doc()
self.validate_status_field()
self.check_priorities()
@@ -106,6 +107,23 @@
frappe.throw(_("Service Level Agreement for {0} {1} already exists.").format(
frappe.bold(self.entity_type), frappe.bold(self.entity)))
+ def validate_selected_doctype(self):
+ invalid_doctypes = list(frappe.model.core_doctypes_list)
+ invalid_doctypes.extend(['Cost Center', 'Company'])
+ valid_document_types = frappe.get_all('DocType', {
+ 'issingle': 0,
+ 'istable': 0,
+ 'is_submittable': 0,
+ 'name': ['not in', invalid_doctypes],
+ 'module': ['not in', ["Email", "Core", "Custom", "Event Streaming", "Social", "Data Migration", "Geo", "Desk"]]
+ }, pluck="name")
+
+ if self.document_type not in valid_document_types:
+ frappe.throw(
+ msg=_("Please select valid document type."),
+ title=_("Invalid Document Type")
+ )
+
def validate_status_field(self):
meta = frappe.get_meta(self.document_type)
if not meta.get_field("status"):
@@ -247,9 +265,15 @@
]
customer = doc.get('customer')
- or_filters.append(
- ["Service Level Agreement", "entity", "in", [customer] + get_customer_group(customer) + get_customer_territory(customer)]
- )
+ if customer:
+ or_filters.extend([
+ ["Service Level Agreement", "entity", "in", [customer] + get_customer_group(customer) + get_customer_territory(customer)],
+ ["Service Level Agreement", "entity_type", "is", "not set"]
+ ])
+ else:
+ or_filters.append(
+ ["Service Level Agreement", "entity_type", "is", "not set"]
+ )
default_sla_filter = filters + [["Service Level Agreement", "default_service_level_agreement", "=", 1]]
default_sla = frappe.get_all("Service Level Agreement", filters=default_sla_filter,
@@ -361,11 +385,18 @@
sla = get_active_service_level_agreement_for(doc)
if not sla:
+ remove_sla_if_applied(doc)
return
process_sla(doc, sla)
+def remove_sla_if_applied(doc):
+ doc.service_level_agreement = None
+ doc.response_by = None
+ doc.resolution_by = None
+
+
def process_sla(doc, sla):
if not doc.creation:
@@ -670,7 +701,7 @@
update_response_and_resolution_metrics(parent, for_resolution)
update_agreement_status(parent, for_resolution)
- parent.save()
+ parent.save(ignore_permissions=True)
def reset_expected_response_and_resolution(doc):
@@ -853,7 +884,7 @@
@frappe.whitelist()
def get_sla_doctypes():
doctypes = []
- data = frappe.get_list('Service Level Agreement',
+ data = frappe.get_all('Service Level Agreement',
{'enabled': 1},
['document_type'],
distinct=1
diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement_dashboard.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement_dashboard.py
deleted file mode 100644
index 22e2c37..0000000
--- a/erpnext/support/doctype/service_level_agreement/service_level_agreement_dashboard.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from frappe import _
-
-
-def get_data():
- return {
- 'fieldname': 'service_level_agreement',
- 'transactions': [
- {
- 'label': _('Issue'),
- 'items': ['Issue']
- }
- ]
- }
diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py
index b07c862..a34124f 100644
--- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py
+++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py
@@ -244,6 +244,13 @@
applied_sla = frappe.db.get_value('Lead', lead.name, 'service_level_agreement')
self.assertEqual(applied_sla, lead_sla.name)
+ # check if SLA is removed if condition fails
+ lead.reload()
+ lead.source = None
+ lead.save()
+ applied_sla = frappe.db.get_value('Lead', lead.name, 'service_level_agreement')
+ self.assertFalse(applied_sla)
+
def tearDown(self):
for d in frappe.get_all("Service Level Agreement"):
frappe.delete_doc("Service Level Agreement", d.name, force=1)
diff --git a/erpnext/support/workspace/support/support.json b/erpnext/support/workspace/support/support.json
index d68c7c7..8ca3a67 100644
--- a/erpnext/support/workspace/support/support.json
+++ b/erpnext/support/workspace/support/support.json
@@ -1,6 +1,6 @@
{
"charts": [],
- "content": "[{\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Issue\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Maintenance Visit\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Service Level Agreement\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Issues\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Maintenance\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Service Level Agreement\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Warranty\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Settings\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Reports\", \"col\": 4}}]",
+ "content": "[{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Issue\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Maintenance Visit\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Service Level Agreement\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Issues\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Maintenance\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Service Level Agreement\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Warranty\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]",
"creation": "2020-03-02 15:48:23.224699",
"docstatus": 0,
"doctype": "Workspace",
@@ -169,7 +169,7 @@
"type": "Link"
}
],
- "modified": "2021-08-05 12:16:02.699924",
+ "modified": "2022-01-13 17:48:27.247406",
"modified_by": "Administrator",
"module": "Support",
"name": "Support",
@@ -178,7 +178,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 25,
+ "sequence_id": 25.0,
"shortcuts": [
{
"color": "Yellow",
diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py
index fbf2594..bc9f04e 100644
--- a/erpnext/tests/utils.py
+++ b/erpnext/tests/utils.py
@@ -125,17 +125,23 @@
if default_filters is None:
default_filters = {}
+ test_filters = []
report_execute_fn = frappe.get_attr(get_report_module_dotted_path(module, report_name) + ".execute")
report_filters = frappe._dict(default_filters).copy().update(filters)
- report_data = report_execute_fn(report_filters)
+ test_filters.append(report_filters)
if optional_filters:
for key, value in optional_filters.items():
- filter_with_optional_param = report_filters.copy().update({key: value})
- report_execute_fn(filter_with_optional_param)
+ test_filters.append(report_filters.copy().update({key: value}))
- return report_data
+ for test_filter in test_filters:
+ try:
+ report_execute_fn(test_filter)
+ except Exception:
+ print(f"Report failed to execute with filters: {test_filter}")
+ raise
+
def timeout(seconds=30, error_message="Test timed out."):
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index 1d8b3a8..feea228 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -181,8 +181,6 @@
if len(child_table_values) > 1:
self.set(default_field, None)
- else:
- self.set(default_field, list(child_table_values)[0])
def delete_events(ref_type, ref_name):
events = frappe.db.sql_list(""" SELECT
diff --git a/erpnext/utilities/workspace/utilities/utilities.json b/erpnext/utilities/workspace/utilities/utilities.json
index 02a8af5..5b81e03 100644
--- a/erpnext/utilities/workspace/utilities/utilities.json
+++ b/erpnext/utilities/workspace/utilities/utilities.json
@@ -1,6 +1,6 @@
{
"charts": [],
- "content": "[{\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Video\", \"col\": 4}}]",
+ "content": "[{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Video\",\"col\":4}}]",
"creation": "2020-09-10 12:21:22.335307",
"docstatus": 0,
"doctype": "Workspace",
@@ -40,7 +40,7 @@
"type": "Link"
}
],
- "modified": "2021-08-05 12:16:03.350805",
+ "modified": "2022-01-13 17:50:10.067510",
"modified_by": "Administrator",
"module": "Utilities",
"name": "Utilities",
@@ -49,7 +49,7 @@
"public": 1,
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 30,
+ "sequence_id": 30.0,
"shortcuts": [],
"title": "Utilities"
}
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index faefb77..f447fac 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,6 @@
# frappe # https://github.com/frappe/frappe is installed during bench-init
gocardless-pro~=1.22.0
-googlemaps # used in ERPNext, but dependency is defined in Frappe
+googlemaps
pandas~=1.1.5
plaid-python~=7.2.1
pycountry~=20.7.3