Merge branch 'develop' of github.com:frappe/erpnext into refactor-call-popup
diff --git a/.travis.yml b/.travis.yml
index a8a0d82..40afeee 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,51 +1,80 @@
-language: python
dist: trusty
-python:
- - "2.7"
- - "3.6"
+language: python
-env:
- - TEST_TYPE="Server Side Test"
- - TEST_TYPE="Patch Test"
+git:
+ depth: 1
-services:
- - mysql
+cache:
+ - pip
+
+addons:
+ hosts: test_site
+ mariadb: 10.3
+
+jobs:
+ include:
+ - name: "Python 2.7 Server Side Test"
+ python: 2.7
+ script: bench --site test_site run-tests --app erpnext --coverage
+
+ - name: "Python 3.6 Server Side Test"
+ python: 3.6
+ script: bench --site test_site run-tests --app erpnext --coverage
+
+ - name: "Python 2.7 Patch Test"
+ python: 2.7
+ before_script:
+ - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz
+ - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz
+ script: bench --site test_site migrate
+
+ - name: "Python 3.6 Patch Test"
+ python: 3.6
+ before_script:
+ - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz
+ - bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz
+ script: bench --site test_site migrate
install:
- # fix mongodb travis error
- - sudo rm /etc/apt/sources.list.d/mongodb*.list
- - pip install flake8==3.3.0
- - flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
- - sudo rm /etc/apt/sources.list.d/docker.list
- - sudo apt-get install hhvm && rm -rf /home/travis/.kiex/
- - sudo apt-get purge -y mysql-common mysql-server mysql-client
+ - cd ~
- nvm install 10
- - pip install python-coveralls
- - wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py
- - sudo python install.py --develop --user travis --without-bench-setup
- - sudo pip install -e ~/bench
- - rm $TRAVIS_BUILD_DIR/.git/shallow
- - bash $TRAVIS_BUILD_DIR/travis/bench_init.sh
- - cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/
+ - git clone https://github.com/frappe/bench --depth 1
+ - pip install -e ./bench
-before_script:
- - mysql -u root -ptravis -e 'create database test_frappe'
- - echo "USE mysql;\nCREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe';\nFLUSH PRIVILEGES;\n" | mysql -u root -ptravis
- - echo "USE mysql;\nGRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost';\n" | mysql -u root -ptravis
+ - git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1
+ - bench init --skip-assets --frappe-path ~/frappe --python $(which python) frappe-bench
+
+ - mkdir ~/frappe-bench/sites/test_site
+ - cp -r $TRAVIS_BUILD_DIR/.travis/site_config.json ~/frappe-bench/sites/test_site/
+
+ - mysql -u root -e "SET GLOBAL character_set_server = 'utf8mb4'"
+ - mysql -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
+
+ - mysql -u root -e "CREATE DATABASE test_frappe"
+ - mysql -u root -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
+ - mysql -u root -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
+
+ - mysql -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'"
+ - mysql -u root -e "FLUSH PRIVILEGES"
+
+ - wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
+ - tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
+ - sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf
+ - sudo chmod o+x /usr/local/bin/wkhtmltopdf
- cd ~/frappe-bench
- - bench get-app erpnext $TRAVIS_BUILD_DIR
- - bench use test_site
- - bench reinstall --mariadb-root-username root --mariadb-root-password travis --yes
- - bench scheduler disable
- - sed -i 's/9000/9001/g' sites/common_site_config.json
- - bench start &
- - sleep 10
-script:
- - bash $TRAVIS_BUILD_DIR/travis/run-tests.sh
+ - sed -i 's/watch:/# watch:/g' Procfile
+ - sed -i 's/schedule:/# schedule:/g' Procfile
+ - sed -i 's/socketio:/# socketio:/g' Procfile
+ - sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile
+
+ - bench get-app erpnext $TRAVIS_BUILD_DIR
+ - bench start &
+ - bench --site test_site reinstall --yes
after_script:
+ - pip install python-coveralls
- coveralls -b apps/erpnext -d ../../sites/.coverage
diff --git a/test_sites/test_site/site_config.json b/.travis/site_config.json
similarity index 80%
rename from test_sites/test_site/site_config.json
rename to .travis/site_config.json
index 7a4d106..dae8009 100644
--- a/test_sites/test_site/site_config.json
+++ b/.travis/site_config.json
@@ -6,8 +6,8 @@
"mail_login": "test@example.com",
"mail_password": "test",
"admin_password": "admin",
- "run_selenium_tests": 1,
+ "root_login": "root",
"root_password": "travis",
- "host_name": "http://localhost:8000",
+ "host_name": "http://test_site:8000",
"install_apps": ["erpnext"]
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index 68efe37..0e57b3f 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -123,7 +123,9 @@
doc.flags.ignore_root_company_validation = True
doc.update({
"company": company,
- "account_currency": None,
+ # parent account's currency should be passed down to child account's curreny
+ # if it is None, it picks it up from default company currency, which might be unintended
+ "account_currency": self.account_currency,
"parent_account": parent_acc_name_map[company]
})
doc.save()
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
index ffb6d5e..88b11dd 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.js
@@ -4,45 +4,52 @@
frappe.ui.form.on('Accounting Dimension', {
refresh: function(frm) {
- if (!frm.is_new()) {
- frm.add_custom_button(__('Show {0}', [frm.doc.document_type]), function () {
- frappe.set_route("List", frm.doc.document_type);
- });
- }
-
frm.set_query('document_type', () => {
return {
filters: {
- name: ['not in', ['Accounting Dimension', 'Project', 'Cost Center']]
+ name: ['not in', ['Accounting Dimension', 'Project', 'Cost Center', 'Accounting Dimension Detail']]
}
};
});
- let button = frm.doc.disabled ? "Enable" : "Disable";
-
- frm.add_custom_button(__(button), function() {
-
- frm.set_value('disabled', 1 - frm.doc.disabled);
-
- frappe.call({
- method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension",
- args: {
- doc: frm.doc
- },
- freeze: true,
- callback: function(r) {
- let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled";
- frm.save();
- frappe.show_alert({message:__(message), indicator:'green'});
- }
+ if (!frm.is_new()) {
+ frm.add_custom_button(__('Show {0}', [frm.doc.document_type]), function () {
+ frappe.set_route("List", frm.doc.document_type);
});
- });
+
+ let button = frm.doc.disabled ? "Enable" : "Disable";
+
+ frm.add_custom_button(__(button), function() {
+
+ frm.set_value('disabled', 1 - frm.doc.disabled);
+
+ frappe.call({
+ method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension",
+ args: {
+ doc: frm.doc
+ },
+ freeze: true,
+ callback: function(r) {
+ let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled";
+ frm.save();
+ frappe.show_alert({message:__(message), indicator:'green'});
+ }
+ });
+ });
+ }
},
document_type: function(frm) {
+
frm.set_value('label', frm.doc.document_type);
frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type));
+ if (frm.is_new()){
+ let row = frappe.model.add_child(frm.doc, "Accounting Dimension Detail", "dimension_defaults");
+ row.reference_document = frm.doc.document_type;
+ frm.refresh_fields("dimension_defaults");
+ }
+
frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => {
if (r && r.document_type) {
frm.set_df_property('document_type', 'description', "Document type is already set as dimension");
@@ -50,3 +57,10 @@
});
},
});
+
+frappe.ui.form.on('Accounting Dimension Detail', {
+ dimension_defaults_add: function(frm, cdt, cdn) {
+ let row = locals[cdt][cdn];
+ row.reference_document = frm.doc.document_type;
+ }
+});
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json
index 6a4dc5c..cf6dc7a 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json
@@ -1,6 +1,4 @@
{
- "_comments": "[]",
- "_liked_by": "[]",
"autoname": "field:label",
"creation": "2019-05-04 18:13:37.002352",
"doctype": "DocType",
@@ -9,8 +7,7 @@
"document_type",
"label",
"fieldname",
- "mandatory_for_bs",
- "mandatory_for_pl",
+ "dimension_defaults",
"disabled"
],
"fields": [
@@ -43,19 +40,13 @@
"read_only": 1
},
{
- "default": "0",
- "fieldname": "mandatory_for_bs",
- "fieldtype": "Check",
- "label": "Mandatory For Balance Sheet"
- },
- {
- "default": "0",
- "fieldname": "mandatory_for_pl",
- "fieldtype": "Check",
- "label": "Mandatory For Profit and Loss Account"
+ "fieldname": "dimension_defaults",
+ "fieldtype": "Table",
+ "label": "Dimension Defaults",
+ "options": "Accounting Dimension Detail"
}
],
- "modified": "2019-07-14 17:25:01.307948",
+ "modified": "2019-07-17 16:49:31.134385",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting Dimension",
diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
index 3148498..1f418de 100644
--- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
+++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py
@@ -96,13 +96,13 @@
frappe.db.sql("""
DELETE FROM `tabCustom Field`
- WHERE fieldname = %s
+ WHERE fieldname = %s
AND dt IN (%s)""" % #nosec
('%s', ', '.join(['%s']* len(doclist))), tuple([doc.fieldname] + doclist))
frappe.db.sql("""
DELETE FROM `tabProperty Setter`
- WHERE field_name = %s
+ WHERE field_name = %s
AND doc_type IN (%s)""" % #nosec
('%s', ', '.join(['%s']* len(doclist))), tuple([doc.fieldname] + doclist))
@@ -150,14 +150,40 @@
"Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item", "Purchase Receipt Item",
"Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule",
"Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation",
- "Travel Request", "Fees", "POS Profile"]
+ "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item", "Subscription",
+ "Subscription Plan"]
return doclist
def get_accounting_dimensions(as_list=True):
- accounting_dimensions = frappe.get_all("Accounting Dimension", fields=["label", "fieldname", "mandatory_for_pl", "mandatory_for_bs", "disabled"], filters={"disabled": 0})
+ accounting_dimensions = frappe.get_all("Accounting Dimension", fields=["label", "fieldname", "disabled"])
if as_list:
return [d.fieldname for d in accounting_dimensions]
else:
return accounting_dimensions
+
+def get_checks_for_pl_and_bs_accounts():
+ dimensions = frappe.db.sql("""SELECT p.label, p.disabled, p.fieldname, c.company, c.mandatory_for_pl, c.mandatory_for_bs
+ FROM `tabAccounting Dimension`p ,`tabAccounting Dimension Detail` c
+ WHERE p.name = c.parent""", as_dict=1)
+
+ return dimensions
+
+@frappe.whitelist()
+def get_dimension_filters():
+ dimension_filters = frappe.db.sql("""
+ SELECT label, fieldname, document_type
+ FROM `tabAccounting Dimension`
+ WHERE disabled = 0
+ """, as_dict=1)
+
+ default_dimensions = frappe.db.sql("""SELECT parent, company, default_dimension
+ FROM `tabAccounting Dimension Detail`""", as_dict=1)
+
+ default_dimensions_map = {}
+ for dimension in default_dimensions:
+ default_dimensions_map.setdefault(dimension['company'], {})
+ default_dimensions_map[dimension['company']][dimension['parent']] = dimension['default_dimension']
+
+ return dimension_filters, default_dimensions_map
diff --git a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
index 527ddcc..104880f 100644
--- a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
+++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
@@ -27,12 +27,20 @@
dimension1 = frappe.get_doc({
"doctype": "Accounting Dimension",
"document_type": "Location",
- "mandatory_for_pl": 1
- }).insert()
+ })
+
+ dimension1.append("dimension_defaults", {
+ "company": "_Test Company",
+ "reference_document": "Location",
+ "default_dimension": "Block 1",
+ "mandatory_for_bs": 1
+ })
+
+ dimension1.insert()
+ dimension1.save()
else:
dimension1 = frappe.get_doc("Accounting Dimension", "Location")
dimension1.disabled = 0
- dimension1.mandatory_for_pl = 1
dimension1.save()
def test_dimension_against_sales_invoice(self):
@@ -100,7 +108,6 @@
dimension1.save()
dimension2 = frappe.get_doc("Accounting Dimension", "Location")
- dimension2.mandatory_for_pl = 0
dimension2.disabled = 1
dimension2.save()
diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/__init__.py b/erpnext/accounts/doctype/accounting_dimension_detail/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/accounting_dimension_detail/__init__.py
diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json
new file mode 100644
index 0000000..1ccef6c
--- /dev/null
+++ b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json
@@ -0,0 +1,67 @@
+{
+ "creation": "2019-07-16 17:53:18.718831",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "company",
+ "reference_document",
+ "default_dimension",
+ "mandatory_for_bs",
+ "mandatory_for_pl"
+ ],
+ "fields": [
+ {
+ "columns": 2,
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Company",
+ "options": "Company",
+ "reqd": 1
+ },
+ {
+ "fieldname": "reference_document",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Reference Document",
+ "options": "DocType",
+ "read_only": 1
+ },
+ {
+ "columns": 2,
+ "fieldname": "default_dimension",
+ "fieldtype": "Dynamic Link",
+ "in_list_view": 1,
+ "label": "Default Dimension",
+ "options": "reference_document",
+ "reqd": 1
+ },
+ {
+ "columns": 3,
+ "default": "0",
+ "fieldname": "mandatory_for_bs",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Mandatory For Balance Sheet"
+ },
+ {
+ "columns": 3,
+ "default": "0",
+ "fieldname": "mandatory_for_pl",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Mandatory For Profit and Loss Account"
+ }
+ ],
+ "istable": 1,
+ "modified": "2019-07-17 23:34:33.026883",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Accounting Dimension Detail",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py
new file mode 100644
index 0000000..17cf549
--- /dev/null
+++ b/erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class AccountingDimensionDetail(Document):
+ pass
diff --git a/erpnext/accounts/doctype/bank/bank_dashboard.py b/erpnext/accounts/doctype/bank/bank_dashboard.py
index 4324041..4a1dad8 100644
--- a/erpnext/accounts/doctype/bank/bank_dashboard.py
+++ b/erpnext/accounts/doctype/bank/bank_dashboard.py
@@ -10,9 +10,6 @@
{
'label': _('Bank Deatils'),
'items': ['Bank Account', 'Bank Guarantee']
- },
- {
- 'items': ['Payment Order']
}
]
}
diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py
index 84276ea..078e058 100644
--- a/erpnext/accounts/doctype/gl_entry/gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py
@@ -12,7 +12,7 @@
from erpnext.accounts.utils import get_account_currency
from erpnext.accounts.utils import get_fiscal_year
from erpnext.exceptions import InvalidAccountCurrency
-from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts
exclude_from_linked_with = True
class GLEntry(Document):
@@ -86,16 +86,16 @@
account_type = frappe.db.get_value("Account", self.account, "report_type")
- for dimension in get_accounting_dimensions(as_list=False):
+ for dimension in get_checks_for_pl_and_bs_accounts():
if account_type == "Profit and Loss" \
- and dimension.mandatory_for_pl and not dimension.disabled:
+ and self.company == dimension.company and dimension.mandatory_for_pl and not dimension.disabled:
if not self.get(dimension.fieldname):
frappe.throw(_("Accounting Dimension <b>{0}</b> is required for 'Profit and Loss' account {1}.")
.format(dimension.label, self.account))
if account_type == "Balance Sheet" \
- and dimension.mandatory_for_bs and not dimension.disabled:
+ and self.company == dimension.company and dimension.mandatory_for_bs and not dimension.disabled:
if not self.get(dimension.fieldname):
frappe.throw(_("Accounting Dimension <b>{0}</b> is required for 'Balance Sheet' account {1}.")
.format(dimension.label, self.account))
diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
index e4acf5a..8728950 100644
--- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
+++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
@@ -258,6 +258,7 @@
"print_hide": 1
},
{
+ "collapsible": 1,
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
"label": "Accounting Dimensions"
@@ -269,12 +270,13 @@
],
"idx": 1,
"istable": 1,
- "modified": "2019-05-25 22:14:02.715509",
+ "modified": "2019-07-16 17:12:08.238334",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry Account",
"owner": "Administrator",
"permissions": [],
+ "sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json
index 7d2d5a1..bc92418 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json
@@ -10,7 +10,9 @@
"create_missing_party",
"column_break_3",
"invoice_type",
+ "accounting_dimensions_section",
"cost_center",
+ "dimension_col_break",
"section_break_4",
"invoices"
],
@@ -59,11 +61,21 @@
"fieldtype": "Link",
"label": "Cost Center",
"options": "Cost Center"
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "accounting_dimensions_section",
+ "fieldtype": "Section Break",
+ "label": "Accounting Dimensions"
+ },
+ {
+ "fieldname": "dimension_col_break",
+ "fieldtype": "Column Break"
}
],
"hide_toolbar": 1,
"issingle": 1,
- "modified": "2019-06-13 11:45:31.405267",
+ "modified": "2019-07-25 14:57:33.187689",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Opening Invoice Creation Tool",
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
index 5fa7b48..ce8aba7 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
@@ -7,6 +7,7 @@
from frappe import _, scrub
from frappe.utils import flt, nowdate
from frappe.model.document import Document
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
class OpeningInvoiceCreationTool(Document):
@@ -173,6 +174,13 @@
"currency": frappe.get_cached_value('Company', self.company, "default_currency")
})
+ accounting_dimension = get_accounting_dimensions()
+
+ for dimension in accounting_dimension:
+ args.update({
+ dimension: item.get(dimension)
+ })
+
if self.invoice_type == "Sales":
args["is_pos"] = 0
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json b/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json
index afa7229..4ce8cb9 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json
@@ -15,7 +15,9 @@
"outstanding_amount",
"column_break_4",
"qty",
- "cost_center"
+ "accounting_dimensions_section",
+ "cost_center",
+ "dimension_col_break"
],
"fields": [
{
@@ -92,10 +94,19 @@
"fieldtype": "Link",
"label": "Cost Center",
"options": "Cost Center"
+ },
+ {
+ "fieldname": "accounting_dimensions_section",
+ "fieldtype": "Section Break",
+ "label": "Accounting Dimensions"
+ },
+ {
+ "fieldname": "dimension_col_break",
+ "fieldtype": "Column Break"
}
],
"istable": 1,
- "modified": "2019-06-13 11:48:08.324063",
+ "modified": "2019-07-25 15:00:00.460695",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Opening Invoice Creation Tool Item",
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index b4d584f..6deee38 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -20,11 +20,13 @@
test_ignore = ["Serial No"]
class TestPurchaseInvoice(unittest.TestCase):
- def setUp(self):
+ @classmethod
+ def setUpClass(self):
unlink_payment_on_cancel_of_invoice()
frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
- def tearDown(self):
+ @classmethod
+ def tearDownClass(self):
unlink_payment_on_cancel_of_invoice(0)
def test_gl_entries_without_perpetual_inventory(self):
@@ -91,6 +93,7 @@
pi_doc = frappe.get_doc('Purchase Invoice', pi_doc.name)
self.assertRaises(frappe.LinkExistsError, pi_doc.cancel)
+ unlink_payment_on_cancel_of_invoice()
def test_purchase_invoice_for_blocked_supplier(self):
supplier = frappe.get_doc('Supplier', '_Test Supplier')
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 1fe6895..74e9186 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -44,6 +44,10 @@
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
+ if (this.frm.doc.is_return) {
+ this.frm.return_print_format = "Sales Invoice Return";
+ }
+
this.show_general_ledger();
if(doc.update_stock) this.show_stock_ledger();
@@ -148,16 +152,24 @@
},
set_default_print_format: function() {
- // set default print format to POS type
+ // set default print format to POS type or Credit Note
if(cur_frm.doc.is_pos) {
if(cur_frm.pos_print_format) {
cur_frm.meta._default_print_format = cur_frm.meta.default_print_format;
cur_frm.meta.default_print_format = cur_frm.pos_print_format;
}
+ } else if(cur_frm.doc.is_return) {
+ if(cur_frm.return_print_format) {
+ cur_frm.meta._default_print_format = cur_frm.meta.default_print_format;
+ cur_frm.meta.default_print_format = cur_frm.return_print_format;
+ }
} else {
if(cur_frm.meta._default_print_format) {
cur_frm.meta.default_print_format = cur_frm.meta._default_print_format;
cur_frm.meta._default_print_format = null;
+ } else if(in_list([cur_frm.pos_print_format, cur_frm.return_print_format], cur_frm.meta.default_print_format)) {
+ cur_frm.meta.default_print_format = null;
+ cur_frm.meta._default_print_format = null;
}
}
},
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 52470fd..dff5594 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -29,10 +29,12 @@
w.submit()
return w
- def setUp(self):
+ @classmethod
+ def setUpClass(self):
unlink_payment_on_cancel_of_invoice()
- def tearDown(self):
+ @classmethod
+ def tearDownClass(self):
unlink_payment_on_cancel_of_invoice(0)
def test_timestamp_change(self):
@@ -135,6 +137,7 @@
unlink_payment_on_cancel_of_invoice(0)
si = frappe.get_doc('Sales Invoice', si.name)
self.assertRaises(frappe.LinkExistsError, si.cancel)
+ unlink_payment_on_cancel_of_invoice()
def test_sales_invoice_calculation_export_currency(self):
si = frappe.copy_doc(test_records[2])
diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
index 465df27..779ac4f 100644
--- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
+++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
@@ -764,6 +764,7 @@
"label": "Image"
},
{
+ "collapsible": 1,
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
"label": "Accounting Dimensions"
@@ -782,7 +783,7 @@
],
"idx": 1,
"istable": 1,
- "modified": "2019-06-28 17:30:12.156086",
+ "modified": "2019-07-16 16:36:46.527606",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",
diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json
index c930516..29cb62a 100644
--- a/erpnext/accounts/doctype/subscription/subscription.json
+++ b/erpnext/accounts/doctype/subscription/subscription.json
@@ -1,926 +1,245 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "ACC-SUB-.YYYY.-.#####",
- "beta": 0,
- "creation": "2017-07-18 17:50:43.967266",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "autoname": "ACC-SUB-.YYYY.-.#####",
+ "creation": "2017-07-18 17:50:43.967266",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "customer",
+ "cb_1",
+ "status",
+ "subscription_period",
+ "start",
+ "cancelation_date",
+ "trial_period_start",
+ "trial_period_end",
+ "column_break_11",
+ "current_invoice_start",
+ "current_invoice_end",
+ "days_until_due",
+ "cancel_at_period_end",
+ "generate_invoice_at_period_start",
+ "sb_4",
+ "plans",
+ "sb_1",
+ "tax_template",
+ "sb_2",
+ "apply_additional_discount",
+ "cb_2",
+ "additional_discount_percentage",
+ "additional_discount_amount",
+ "sb_3",
+ "invoices",
+ "accounting_dimensions_section",
+ "dimension_col_break"
+ ],
"fields": [
{
- "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": 1,
- "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": 1,
- "search_index": 0,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "customer",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Customer",
+ "options": "Customer",
+ "reqd": 1,
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "cb_1",
- "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,
- "label": "",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "fieldname": "cb_1",
+ "fieldtype": "Column Break"
+ },
{
- "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": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "label": "Status",
+ "options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "subscription_period",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Subscription Period",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "subscription_period",
+ "fieldtype": "Section Break",
+ "label": "Subscription Period"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "start",
- "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": "Subscription Start Date",
- "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": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "start",
+ "fieldtype": "Date",
+ "label": "Subscription Start Date",
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "cancelation_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": "Cancelation Date",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "cancelation_date",
+ "fieldtype": "Date",
+ "label": "Cancelation Date",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "trial_period_start",
- "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": "Trial Period Start Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "fieldname": "trial_period_start",
+ "fieldtype": "Date",
+ "label": "Trial Period Start Date",
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.trial_period_start",
- "fieldname": "trial_period_end",
- "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": "Trial Period End Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
- },
+ "depends_on": "eval:doc.trial_period_start",
+ "fieldname": "trial_period_end",
+ "fieldtype": "Date",
+ "label": "Trial Period End Date",
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_11",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_11",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "current_invoice_start",
- "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": "Current Invoice Start Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "current_invoice_start",
+ "fieldtype": "Date",
+ "label": "Current Invoice Start Date",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "current_invoice_end",
- "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": "Current Invoice End Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "current_invoice_end",
+ "fieldtype": "Date",
+ "label": "Current Invoice End Date",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "0",
- "description": "Number of days that the subscriber has to pay invoices generated by this subscription",
- "fieldname": "days_until_due",
- "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": "Days Until Due",
- "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
- },
+ "default": "0",
+ "description": "Number of days that the subscriber has to pay invoices generated by this subscription",
+ "fieldname": "days_until_due",
+ "fieldtype": "Int",
+ "label": "Days Until Due"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "cancel_at_period_end",
- "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": "Cancel At End Of Period",
- "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
- },
+ "default": "0",
+ "fieldname": "cancel_at_period_end",
+ "fieldtype": "Check",
+ "label": "Cancel At End Of Period"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "generate_invoice_at_period_start",
- "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": "Generate Invoice At Beginning Of Period",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "generate_invoice_at_period_start",
+ "fieldtype": "Check",
+ "label": "Generate Invoice At Beginning Of Period"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "sb_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,
- "label": "Plans",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "fieldname": "sb_4",
+ "fieldtype": "Section Break",
+ "label": "Plans"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "plans",
- "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": "Plans",
- "length": 0,
- "no_copy": 0,
- "options": "Subscription Plan 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
- },
+ "allow_on_submit": 1,
+ "fieldname": "plans",
+ "fieldtype": "Table",
+ "label": "Plans",
+ "options": "Subscription Plan Detail",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "sb_1",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Taxes",
- "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": "sb_1",
+ "fieldtype": "Section Break",
+ "label": "Taxes"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "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": "Sales Taxes and Charges 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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "tax_template",
+ "fieldtype": "Link",
+ "label": "Sales Taxes and Charges Template",
+ "options": "Sales Taxes and Charges Template"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "description": "",
- "fieldname": "sb_2",
- "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": "Discounts",
- "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": "sb_2",
+ "fieldtype": "Section Break",
+ "label": "Discounts"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "apply_additional_discount",
- "fieldtype": "Select",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Apply Additional Discount On",
- "length": 0,
- "no_copy": 0,
- "options": "\nGrand Total\nNet total",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "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": "apply_additional_discount",
+ "fieldtype": "Select",
+ "label": "Apply Additional Discount On",
+ "options": "\nGrand Total\nNet total"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "cb_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,
- "label": "",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "cb_2",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
- "fieldname": "additional_discount_percentage",
- "fieldtype": "Percent",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Additional DIscount Percentage",
- "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
- },
+ "fieldname": "additional_discount_percentage",
+ "fieldtype": "Percent",
+ "label": "Additional DIscount Percentage"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "depends_on": "",
- "fieldname": "additional_discount_amount",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Additional DIscount Amount",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "collapsible": 1,
+ "fieldname": "additional_discount_amount",
+ "fieldtype": "Currency",
+ "label": "Additional DIscount Amount"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "depends_on": "eval:doc.invoices",
- "fieldname": "sb_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,
- "label": "Invoices",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "depends_on": "eval:doc.invoices",
+ "fieldname": "sb_3",
+ "fieldtype": "Section Break",
+ "label": "Invoices"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "depends_on": "",
- "fieldname": "invoices",
- "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": "Invoices",
- "length": 0,
- "no_copy": 0,
- "options": "Subscription Invoice",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "collapsible": 1,
+ "fieldname": "invoices",
+ "fieldtype": "Table",
+ "label": "Invoices",
+ "options": "Subscription Invoice"
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "accounting_dimensions_section",
+ "fieldtype": "Section Break",
+ "label": "Accounting Dimensions"
+ },
+ {
+ "fieldname": "dimension_col_break",
+ "fieldtype": "Column Break"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-10-14 10:38:55.545540",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Subscription",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "modified": "2019-07-25 18:45:38.579579",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Subscription",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts User",
+ "share": 1,
"write": 1
- },
+ },
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "search_fields": "",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
-}
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py
index 858359e..f13ca4c 100644
--- a/erpnext/accounts/doctype/subscription/subscription.py
+++ b/erpnext/accounts/doctype/subscription/subscription.py
@@ -9,6 +9,7 @@
from frappe.model.document import Document
from frappe.utils.data import nowdate, getdate, cint, add_days, date_diff, get_last_day, add_to_date, flt
from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate
+from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
class Subscription(Document):
@@ -241,6 +242,15 @@
invoice.posting_date = self.current_invoice_start
invoice.customer = self.customer
+ ## Add dimesnions in invoice for subscription:
+ accounting_dimensions = get_accounting_dimensions()
+
+ for dimension in accounting_dimensions:
+ if self.get(dimension):
+ invoice.update({
+ dimension: self.get(dimension)
+ })
+
# Subscription is better suited for service items. I won't update `update_stock`
# for that reason
items_list = self.get_items_from_plans(self.plans, prorate)
diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json
index 453521d..9f79066 100644
--- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json
+++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json
@@ -1,612 +1,163 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 1,
- "autoname": "field:plan_name",
- "beta": 0,
- "creation": "2018-02-24 11:31:23.066506",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "allow_rename": 1,
+ "autoname": "field:plan_name",
+ "creation": "2018-02-24 11:31:23.066506",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "plan_name",
+ "currency",
+ "column_break_3",
+ "item",
+ "section_break_5",
+ "price_determination",
+ "column_break_7",
+ "cost",
+ "price_list",
+ "section_break_11",
+ "billing_interval",
+ "column_break_13",
+ "billing_interval_count",
+ "payment_plan_section",
+ "payment_plan_id",
+ "column_break_16",
+ "payment_gateway",
+ "accounting_dimensions_section",
+ "dimension_col_break"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "plan_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": "Plan 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,
+ "fieldname": "plan_name",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Plan Name",
+ "reqd": 1,
"unique": 1
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "currency",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Currency",
- "length": 0,
- "no_copy": 0,
- "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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "currency",
+ "fieldtype": "Link",
+ "label": "Currency",
+ "options": "Currency"
+ },
{
- "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": "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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "item",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Item",
+ "options": "Item",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "section_break_5",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "price_determination",
- "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": "Price Determination",
- "length": 0,
- "no_copy": 0,
- "options": "\nFixed rate\nBased on price 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": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "price_determination",
+ "fieldtype": "Select",
+ "label": "Price Determination",
+ "options": "\nFixed rate\nBased on price list",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_7",
- "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_7",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.price_determination==\"Fixed rate\"",
- "fieldname": "cost",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Cost",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "depends_on": "eval:doc.price_determination==\"Fixed rate\"",
+ "fieldname": "cost",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Cost"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.price_determination==\"Based on price list\"",
- "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",
- "length": 0,
- "no_copy": 0,
- "options": "Price 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
- },
+ "depends_on": "eval:doc.price_determination==\"Based on price list\"",
+ "fieldname": "price_list",
+ "fieldtype": "Link",
+ "label": "Price List",
+ "options": "Price List"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_11",
- "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_11",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Day",
- "fieldname": "billing_interval",
- "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": "Billing Interval",
- "length": 0,
- "no_copy": 0,
- "options": "Day\nWeek\nMonth\nYear",
- "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
- },
+ "default": "Day",
+ "fieldname": "billing_interval",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Billing Interval",
+ "options": "Day\nWeek\nMonth\nYear",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_13",
- "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_13",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "1",
- "description": "Number of intervals for the interval field e.g if Interval is 'Days' and Billing Interval Count is 3, invoices will be generated every 3 days",
- "fieldname": "billing_interval_count",
- "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": "Billing Interval Count",
- "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
- },
+ "default": "1",
+ "description": "Number of intervals for the interval field e.g if Interval is 'Days' and Billing Interval Count is 3, invoices will be generated every 3 days",
+ "fieldname": "billing_interval_count",
+ "fieldtype": "Int",
+ "label": "Billing Interval Count",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "payment_plan_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Payment Plan",
- "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": "payment_plan_section",
+ "fieldtype": "Section Break",
+ "label": "Payment Plan"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "payment_plan_id",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Payment Plan",
- "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": "payment_plan_id",
+ "fieldtype": "Data",
+ "label": "Payment Plan"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_16",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_16",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "payment_gateway",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Payment Gateway",
- "length": 0,
- "no_copy": 0,
- "options": "Payment Gateway Account",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "payment_gateway",
+ "fieldtype": "Link",
+ "label": "Payment Gateway",
+ "options": "Payment Gateway Account"
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "accounting_dimensions_section",
+ "fieldtype": "Section Break",
+ "label": "Accounting Dimensions"
+ },
+ {
+ "fieldname": "dimension_col_break",
+ "fieldtype": "Column Break"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-06-20 16:59:54.082358",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Subscription Plan",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "modified": "2019-07-25 18:35:04.362556",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Subscription Plan",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/accounts/print_format/sales_invoice_return/__init__.py b/erpnext/accounts/print_format/sales_invoice_return/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/print_format/sales_invoice_return/__init__.py
diff --git a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html
new file mode 100644
index 0000000..889b7f7
--- /dev/null
+++ b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html
@@ -0,0 +1,129 @@
+{%- from "templates/print_formats/standard_macros.html" import add_header, render_field, print_value, fieldmeta,
+ get_width, get_align_class -%}
+
+{%- macro render_currency(df, doc) -%}
+<div class="row {% if df.bold %}important{% endif %} data-field">
+ <div class="col-xs-{{ "9" if df.fieldtype=="Check" else "5" }}
+ {%- if doc._align_labels_right %} text-right{%- endif -%}">
+ <label>{{ _(df.label) }}</label>
+ </div>
+ <div class="col-xs-{{ "3" if df.fieldtype=="Check" else "7" }} value">
+ {% if doc.get(df.fieldname) != None -%}
+ {{ frappe.utils.fmt_money((doc[df.fieldname])|int|abs, currency=doc.currency) }}
+ {% endif %}
+ </div>
+</div>
+{%- endmacro -%}
+
+{%- macro render_taxes(df, doc) -%}
+ {%- set data = doc.get(df.fieldname)[df.start:df.end] -%}
+ <div class="row">
+ <div class="col-xs-6"></div>
+ <div class="col-xs-6">
+ {%- for charge in data -%}
+ {%- if (charge.tax_amount or doc.flags.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}
+ <div class="row">
+ <div class="col-xs-5 {%- if doc._align_labels_right %} text-right{%- endif -%}">
+ <label>{{ charge.get_formatted("description") }}</label></div>
+ <div class="col-xs-7 text-right">
+ {{ frappe.utils.fmt_money((charge.tax_amount)|int|abs, currency=doc.currency) }}
+ </div>
+ </div>
+ {%- endif -%}
+ {%- endfor -%}
+ </div>
+ </div>
+{%- endmacro -%}
+
+{%- macro render_table(df, doc) -%}
+ {%- set table_meta = frappe.get_meta(df.options) -%}
+ {%- set data = doc.get(df.fieldname)[df.start:df.end] -%}
+ {%- if doc.print_templates and
+ doc.print_templates.get(df.fieldname) -%}
+ {% include doc.print_templates[df.fieldname] %}
+ {%- else -%}
+ {%- if data -%}
+ {%- set visible_columns = get_visible_columns(doc.get(df.fieldname),
+ table_meta, df) -%}
+ <div {{ fieldmeta(df) }}>
+ <table class="table table-bordered table-condensed">
+ <thead>
+ <tr>
+ <th style="width: 40px" class="table-sr">{{ _("Sr") }}</th>
+ {% for tdf in visible_columns %}
+ {% if (data and not data[0].flags.compact_item_print) or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %}
+ <th style="width: {{ get_width(tdf) }};" class="{{ get_align_class(tdf) }}" {{ fieldmeta(df) }}>
+ {{ _(tdf.label) }}</th>
+ {% endif %}
+ {% endfor %}
+ </tr>
+ </thead>
+ <tbody>
+ {% for d in data %}
+ <tr>
+ <td class="table-sr">{{ d.idx }}</td>
+ {% for tdf in visible_columns %}
+ {% if not d.flags.compact_item_print or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %}
+ <td class="{{ get_align_class(tdf) }}" {{ fieldmeta(df) }}>
+ {% if tdf.fieldtype == 'Currency' %}
+ <div class="value">{{ frappe.utils.fmt_money((d[tdf.fieldname])|int|abs, currency=doc.currency) }}</div></td>
+ {% else %}
+ <div class="value">{{ print_value(tdf, d, doc, visible_columns) }}</div></td>
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </div>
+ {%- endif -%}
+ {%- endif -%}
+{%- endmacro -%}
+
+{% for page in layout %}
+<div class="page-break">
+ <div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}>
+ {{ add_header(loop.index, layout|len, doc, letter_head, no_letterhead, footer, print_settings) }}
+ </div>
+
+ {% if print_settings.repeat_header_footer %}
+ <div id="footer-html" class="visible-pdf">
+ {% if not no_letterhead and footer %}
+ <div class="letter-head-footer">
+ {{ footer }}
+ </div>
+ {% endif %}
+ <p class="text-center small page-number visible-pdf">
+ {{ _("Page {0} of {1}").format('<span class="page"></span>', '<span class="topage"></span>') }}
+ </p>
+ </div>
+ {% endif %}
+
+ {% for section in page %}
+ <div class="row section-break">
+ {% if section.columns.fields %}
+ {%- if doc._line_breaks and loop.index != 1 -%}<hr>{%- endif -%}
+ {%- if doc._show_section_headings and section.label and section.has_data -%}
+ <h4 class='col-sm-12'>{{ _(section.label) }}</h4>
+ {% endif %}
+ {%- endif -%}
+ {% for column in section.columns %}
+ <div class="col-xs-{{ (12 / section.columns|len)|int }} column-break">
+ {% for df in column.fields %}
+ {% if df.fieldname == 'taxes' %}
+ {{ render_taxes(df, doc) }}
+ {% elif df.fieldtype == 'Currency' %}
+ {{ render_currency(df, doc) }}
+ {% elif df.fieldtype =='Table' %}
+ {{ render_table(df, doc)}}
+ {% elif doc[df.fieldname] %}
+ {{ render_field(df, doc) }}
+ {% endif %}
+ {% endfor %}
+ </div>
+ {% endfor %}
+ </div>
+ {% endfor %}
+</div>
+{% endfor %}
diff --git a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json
new file mode 100644
index 0000000..352b549
--- /dev/null
+++ b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.json
@@ -0,0 +1,24 @@
+{
+ "align_labels_right": 1,
+ "creation": "2019-07-24 20:13:30.259953",
+ "custom_format": 0,
+ "default_print_language": "en-US",
+ "disabled": 0,
+ "doc_type": "Sales Invoice",
+ "docstatus": 0,
+ "doctype": "Print Format",
+ "font": "Default",
+ "html": "",
+ "idx": 0,
+ "line_breaks": 1,
+ "modified": "2019-07-24 20:13:30.259953",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Sales Invoice Return",
+ "owner": "Administrator",
+ "print_format_builder": 0,
+ "print_format_type": "Jinja",
+ "raw_printing": 0,
+ "show_section_headings": 1,
+ "standard": "Yes"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js
index cfcc575..8eb670de 100644
--- a/erpnext/accounts/report/accounts_payable/accounts_payable.js
+++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js
@@ -115,13 +115,12 @@
}
}
-erpnext.dimension_filters.then((dimensions) => {
- dimensions.forEach((dimension) => {
- frappe.query_reports["Accounts Payable"].filters.splice(9, 0 ,{
- "fieldname": dimension["fieldname"],
- "label": __(dimension["label"]),
- "fieldtype": "Link",
- "options": dimension["document_type"]
- });
+erpnext.dimension_filters.forEach((dimension) => {
+ frappe.query_reports["Accounts Payable"].filters.splice(9, 0 ,{
+ "fieldname": dimension["fieldname"],
+ "label": __(dimension["label"]),
+ "fieldtype": "Link",
+ "options": dimension["document_type"]
});
});
+
diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
index 006068a..5f0fdc9 100644
--- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
+++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
@@ -99,13 +99,12 @@
}
}
-erpnext.dimension_filters.then((dimensions) => {
- dimensions.forEach((dimension) => {
- frappe.query_reports["Accounts Payable Summary"].filters.splice(9, 0 ,{
- "fieldname": dimension["fieldname"],
- "label": __(dimension["label"]),
- "fieldtype": "Link",
- "options": dimension["document_type"]
- });
+erpnext.dimension_filters.forEach((dimension) => {
+ frappe.query_reports["Accounts Payable Summary"].filters.splice(9, 0 ,{
+ "fieldname": dimension["fieldname"],
+ "label": __(dimension["label"]),
+ "fieldtype": "Link",
+ "options": dimension["document_type"]
});
});
+
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
index 2a45454..4551973 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
@@ -173,13 +173,12 @@
}
}
-erpnext.dimension_filters.then((dimensions) => {
- dimensions.forEach((dimension) => {
- frappe.query_reports["Accounts Receivable"].filters.splice(9, 0 ,{
- "fieldname": dimension["fieldname"],
- "label": __(dimension["label"]),
- "fieldtype": "Link",
- "options": dimension["document_type"]
- });
+erpnext.dimension_filters.forEach((dimension) => {
+ frappe.query_reports["Accounts Receivable"].filters.splice(9, 0 ,{
+ "fieldname": dimension["fieldname"],
+ "label": __(dimension["label"]),
+ "fieldtype": "Link",
+ "options": dimension["document_type"]
});
});
+
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 a7c0787..0120608 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
@@ -117,13 +117,11 @@
}
}
-erpnext.dimension_filters.then((dimensions) => {
- dimensions.forEach((dimension) => {
- frappe.query_reports["Accounts Receivable Summary"].filters.splice(9, 0 ,{
- "fieldname": dimension["fieldname"],
- "label": __(dimension["label"]),
- "fieldtype": "Link",
- "options": dimension["document_type"]
- });
+erpnext.dimension_filters.forEach((dimension) => {
+ frappe.query_reports["Accounts Receivable Summary"].filters.splice(9, 0 ,{
+ "fieldname": dimension["fieldname"],
+ "label": __(dimension["label"]),
+ "fieldtype": "Link",
+ "options": dimension["document_type"]
});
});
diff --git a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
index 1923f78..63317c5 100644
--- a/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
+++ b/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py
@@ -58,8 +58,7 @@
{
"fieldname": "payment_document",
"label": _("Payment Document Type"),
- "fieldtype": "Link",
- "options": "DocType",
+ "fieldtype": "Data",
"width": 220
},
{
diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js
index f2a33a8..2451187 100644
--- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js
+++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js
@@ -63,8 +63,7 @@
]
}
-erpnext.dimension_filters.then((dimensions) => {
- dimensions.forEach((dimension) => {
- frappe.query_reports["Budget Variance Report"].filters[4].options.push(dimension["document_type"]);
- });
+erpnext.dimension_filters.forEach((dimension) => {
+ frappe.query_reports["Budget Variance Report"].filters[4].options.push(dimension["document_type"]);
});
+
diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js
index ea82575..4a28706 100644
--- a/erpnext/accounts/report/general_ledger/general_ledger.js
+++ b/erpnext/accounts/report/general_ledger/general_ledger.js
@@ -159,13 +159,12 @@
]
}
-erpnext.dimension_filters.then((dimensions) => {
- dimensions.forEach((dimension) => {
- frappe.query_reports["General Ledger"].filters.splice(15, 0 ,{
- "fieldname": dimension["fieldname"],
- "label": __(dimension["label"]),
- "fieldtype": "Link",
- "options": dimension["document_type"]
- });
+erpnext.dimension_filters.forEach((dimension) => {
+ frappe.query_reports["General Ledger"].filters.splice(15, 0 ,{
+ "fieldname": dimension["fieldname"],
+ "label": __(dimension["label"]),
+ "fieldtype": "Link",
+ "options": dimension["document_type"]
});
});
+
diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
index d6864b5..889ede5 100644
--- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
+++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
@@ -105,9 +105,8 @@
"initial_depth": 3
}
- erpnext.dimension_filters.then((dimensions) => {
- dimensions.forEach((dimension) => {
- frappe.query_reports["Profitability Analysis"].filters[1].options.push(dimension["document_type"]);
- });
+ erpnext.dimension_filters.forEach((dimension) => {
+ frappe.query_reports["Profitability Analysis"].filters[1].options.push(dimension["document_type"]);
});
+
});
diff --git a/erpnext/accounts/report/sales_register/sales_register.js b/erpnext/accounts/report/sales_register/sales_register.js
index 442aa12..9dee656 100644
--- a/erpnext/accounts/report/sales_register/sales_register.js
+++ b/erpnext/accounts/report/sales_register/sales_register.js
@@ -68,13 +68,12 @@
]
}
-erpnext.dimension_filters.then((dimensions) => {
- dimensions.forEach((dimension) => {
- frappe.query_reports["Sales Register"].filters.splice(7, 0 ,{
- "fieldname": dimension["fieldname"],
- "label": __(dimension["label"]),
- "fieldtype": "Link",
- "options": dimension["document_type"]
- });
+erpnext.dimension_filters.forEach((dimension) => {
+ frappe.query_reports["Sales Register"].filters.splice(7, 0 ,{
+ "fieldname": dimension["fieldname"],
+ "label": __(dimension["label"]),
+ "fieldtype": "Link",
+ "options": dimension["document_type"]
});
});
+
diff --git a/erpnext/accounts/report/trial_balance/trial_balance.js b/erpnext/accounts/report/trial_balance/trial_balance.js
index 73d2ab3..f15b5b1 100644
--- a/erpnext/accounts/report/trial_balance/trial_balance.js
+++ b/erpnext/accounts/report/trial_balance/trial_balance.js
@@ -94,10 +94,8 @@
"parent_field": "parent_account",
"initial_depth": 3
}
-});
-erpnext.dimension_filters.then((dimensions) => {
- dimensions.forEach((dimension) => {
+ erpnext.dimension_filters.forEach((dimension) => {
frappe.query_reports["Trial Balance"].filters.splice(5, 0 ,{
"fieldname": dimension["fieldname"],
"label": __(dimension["label"]),
@@ -107,3 +105,5 @@
});
});
+
+
diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py
index b6ddaa8..10e977a 100644
--- a/erpnext/accounts/report/trial_balance/trial_balance.py
+++ b/erpnext/accounts/report/trial_balance/trial_balance.py
@@ -123,11 +123,12 @@
if accounting_dimensions:
for dimension in accounting_dimensions:
- additional_conditions += """ and {0} in (%({0})s) """.format(dimension)
+ if filters.get(dimension):
+ additional_conditions += """ and {0} in (%({0})s) """.format(dimension)
- query_filters.update({
- dimension: filters.get(dimension)
- })
+ query_filters.update({
+ dimension: filters.get(dimension)
+ })
gle = frappe.db.sql("""
select
diff --git a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py
index 4a13f38..bebf0cc 100644
--- a/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py
+++ b/erpnext/buying/report/procurement_tracker/test_procurement_tracker.py
@@ -30,7 +30,7 @@
company_name="_Test Procurement Company",
abbr="_TPC",
default_currency="INR",
- country="India"
+ country="Pakistan"
)).insert()
warehouse = create_warehouse("_Test Procurement Warehouse", company="_Test Procurement Company")
mr = make_material_request(company="_Test Procurement Company", warehouse=warehouse)
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index ca59a39..288aa08 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -60,7 +60,9 @@
def validate(self):
- self.validate_qty_is_not_zero()
+ if not self.get('is_return'):
+ self.validate_qty_is_not_zero()
+
if self.get("_action") and self._action != "update_after_submit":
self.set_missing_values(for_validate=True)
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 8d24e7a..d2db9d0 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -81,7 +81,12 @@
item.discount_amount = item.price_list_rate - item.rate
item.net_rate = item.rate
- item.amount = flt(item.rate * item.qty, item.precision("amount"))
+
+ if not item.qty and self.doc.get("is_return"):
+ item.amount = flt(-1 * item.rate, item.precision("amount"))
+ else:
+ item.amount = flt(item.rate * item.qty, item.precision("amount"))
+
item.net_amount = item.amount
self._set_in_company_currency(item, ["price_list_rate", "rate", "net_rate", "amount", "net_amount"])
diff --git a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py
index 4a0ce18..9ba6d5e 100644
--- a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py
+++ b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py
@@ -92,5 +92,5 @@
company.abbr = "_TC10"
company.parent_company = "_Test Company"
company.default_currency = "INR"
- company.country = "India"
+ company.country = "Pakistan"
company.insert()
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 398c602..33d4f55 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -624,4 +624,5 @@
erpnext.patches.v12_0.update_due_date_in_gle
erpnext.patches.v12_0.add_default_buying_selling_terms_in_company
erpnext.patches.v12_0.update_ewaybill_field_position
+erpnext.patches.v12_0.create_accounting_dimensions_in_missing_doctypes
erpnext.patches.v11_1.set_status_for_material_request_type_manufacture
diff --git a/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py
new file mode 100644
index 0000000..b71ea66
--- /dev/null
+++ b/erpnext/patches/v12_0/create_accounting_dimensions_in_missing_doctypes.py
@@ -0,0 +1,41 @@
+from __future__ import unicode_literals
+import frappe
+from frappe.custom.doctype.custom_field.custom_field import create_custom_field
+
+def execute():
+
+ frappe.reload_doc('accounts', 'doctype', 'accounting_dimension')
+
+ accounting_dimensions = frappe.db.sql("""select fieldname, label, document_type, disabled from
+ `tabAccounting Dimension`""", as_dict=1)
+
+ if not accounting_dimensions:
+ return
+
+ count = 1
+ for d in accounting_dimensions:
+
+ if count%2 == 0:
+ insert_after_field = 'dimension_col_break'
+ else:
+ insert_after_field = 'accounting_dimensions_section'
+
+ for doctype in ["Subscription Plan", "Subscription", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item"]:
+
+ field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname})
+
+ if field:
+ continue
+
+ df = {
+ "fieldname": d.fieldname,
+ "label": d.label,
+ "fieldtype": "Link",
+ "options": d.document_type,
+ "insert_after": insert_after_field
+ }
+
+ create_custom_field(doctype, df)
+ frappe.clear_cache(doctype=doctype)
+
+ count += 1
\ No newline at end of file
diff --git a/erpnext/patches/v12_0/update_ewaybill_field_position.py b/erpnext/patches/v12_0/update_ewaybill_field_position.py
index d0291d2..c0230c4 100644
--- a/erpnext/patches/v12_0/update_ewaybill_field_position.py
+++ b/erpnext/patches/v12_0/update_ewaybill_field_position.py
@@ -10,18 +10,19 @@
field = frappe.db.get_value("Custom Field", {"dt": "Sales Invoice", "fieldname": "ewaybill"})
- ewaybill_field = frappe.get_doc("Custom Field", field)
+ if field:
+ ewaybill_field = frappe.get_doc("Custom Field", field)
- ewaybill_field.flags.ignore_validate = True
+ ewaybill_field.flags.ignore_validate = True
- ewaybill_field.update({
- 'fieldname': 'ewaybill',
- 'label': 'e-Way Bill No.',
- 'fieldtype': 'Data',
- 'depends_on': 'eval:(doc.docstatus === 1)',
- 'allow_on_submit': 1,
- 'insert_after': 'tax_id',
- 'translatable': 0
- })
+ ewaybill_field.update({
+ 'fieldname': 'ewaybill',
+ 'label': 'e-Way Bill No.',
+ 'fieldtype': 'Data',
+ 'depends_on': 'eval:(doc.docstatus === 1)',
+ 'allow_on_submit': 1,
+ 'insert_after': 'tax_id',
+ 'translatable': 0
+ })
- ewaybill_field.save()
\ No newline at end of file
+ ewaybill_field.save()
\ No newline at end of file
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 50557f1..492eabe 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -145,7 +145,7 @@
def populate_depends_on(self):
if self.parent_task:
- parent = frappe.get_cached_doc('Task', self.parent_task)
+ parent = frappe.get_doc('Task', self.parent_task)
if not self.name in [row.task for row in parent.depends_on]:
parent.append("depends_on", {
"doctype": "Task Depends On",
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 91800cd..7cf2181 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -92,7 +92,13 @@
$.each(this.frm.doc["items"] || [], function(i, item) {
frappe.model.round_floats_in(item);
item.net_rate = item.rate;
- item.amount = flt(item.rate * item.qty, precision("amount", item));
+
+ if ((!item.qty) && me.frm.doc.is_return) {
+ item.amount = flt(item.rate * -1, precision("amount", item));
+ } else {
+ item.amount = flt(item.rate * item.qty, precision("amount", item));
+ }
+
item.net_amount = item.amount;
item.item_tax_amount = 0.0;
item.total_weight = flt(item.weight_per_unit * item.stock_qty);
diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js
index 89cb13d..63e057c 100644
--- a/erpnext/public/js/financial_statements.js
+++ b/erpnext/public/js/financial_statements.js
@@ -129,14 +129,12 @@
}
]
- erpnext.dimension_filters.then((dimensions) => {
- dimensions.forEach((dimension) => {
- filters.push({
- "fieldname": dimension["fieldname"],
- "label": __(dimension["label"]),
- "fieldtype": "Link",
- "options": dimension["document_type"]
- });
+ erpnext.dimension_filters.forEach((dimension) => {
+ filters.push({
+ "fieldname": dimension["fieldname"],
+ "label": __(dimension["label"]),
+ "fieldtype": "Link",
+ "options": dimension["document_type"]
});
});
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 0252f38..0a363a0 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -63,20 +63,6 @@
me.show_serial_batch_selector(grid_row.frm, grid_row.doc);
});
},
-
- get_dimension_filters: async function() {
- if (!frappe.model.can_read('Accounting Dimension')) {
- return [];
- }
- let dimensions = await frappe.db.get_list('Accounting Dimension', {
- fields: ['label', 'fieldname', 'document_type'],
- filters: {
- disabled: 0
- }
- });
-
- return dimensions;
- }
});
diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js
index 549f95e..f1c9209 100644
--- a/erpnext/public/js/utils/dimension_tree_filter.js
+++ b/erpnext/public/js/utils/dimension_tree_filter.js
@@ -5,24 +5,54 @@
"Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item", "Purchase Receipt Item",
"Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule",
"Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation",
- "Travel Request", "Fees", "POS Profile"];
+ "Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item", "Subscription",
+ "Subscription Plan"];
-erpnext.dimension_filters = erpnext.get_dimension_filters();
+frappe.call({
+ method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimension_filters",
+ callback: function(r){
+ erpnext.dimension_filters = r.message[0];
+ erpnext.default_dimensions = r.message[1];
+ }
+});
erpnext.doctypes_with_dimensions.forEach((doctype) => {
frappe.ui.form.on(doctype, {
onload: function(frm) {
- erpnext.dimension_filters.then((dimensions) => {
- dimensions.forEach((dimension) => {
- frappe.model.with_doctype(dimension['document_type'], () => {
- if (frappe.meta.has_field(dimension['document_type'], 'is_group')) {
- frm.set_query(dimension['fieldname'], {
- "is_group": 0
- });
- }
- });
+ erpnext.dimension_filters.forEach((dimension) => {
+ frappe.model.with_doctype(dimension['document_type'], () => {
+ if (frappe.meta.has_field(dimension['document_type'], 'is_group')) {
+ frm.set_query(dimension['fieldname'], {
+ "is_group": 0
+ });
+ }
+ if (frm.is_new() && frappe.meta.has_field(doctype, 'company') && frm.doc.company) {
+ frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
+ }
});
});
+ },
+
+ company: function(frm) {
+ if(frm.doc.company) {
+ erpnext.dimension_filters.forEach((dimension) => {
+ frm.set_value(dimension['fieldname'], erpnext.default_dimensions[frm.doc.company][dimension['document_type']]);
+ });
+ }
+ },
+
+ items_add: function(frm, cdt, cdn) {
+ erpnext.dimension_filters.forEach((dimension) => {
+ var row = frappe.get_doc(cdt, cdn);
+ frm.script_manager.copy_from_first_row("items", row, [dimension['fieldname']]);
+ });
+ },
+
+ accounts_add: function(frm, cdt, cdn) {
+ erpnext.dimension_filters.forEach((dimension) => {
+ var row = frappe.get_doc(cdt, cdn);
+ frm.script_manager.copy_from_first_row("accounts", row, [dimension['fieldname']]);
+ });
}
});
});
\ No newline at end of file
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index e8c170e..2da1085 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -161,8 +161,9 @@
"gst_category": ["in", ["Registered Regular", "Deemed Export", "SEZ"]]
})
- conditions += """ and ifnull(gst_category, '') != 'Overseas' and is_return != 1
- and customer in ({0})""".format(", ".join([frappe.db.escape(c.name) for c in customers]))
+ if customers:
+ conditions += """ and ifnull(gst_category, '') != 'Overseas' and is_return != 1
+ and customer in ({0})""".format(", ".join([frappe.db.escape(c.name) for c in customers]))
if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"):
b2c_limit = frappe.db.get_single_value('GST Settings', 'b2c_limit')
@@ -174,11 +175,11 @@
"gst_category": ["in", ["Unregistered"]]
})
- if self.filters.get("type_of_business") == "B2C Large":
+ if self.filters.get("type_of_business") == "B2C Large" and customers:
conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2)
and grand_total > {0} and is_return != 1 and customer in ({1})""".\
format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers]))
- elif self.filters.get("type_of_business") == "B2C Small":
+ elif self.filters.get("type_of_business") == "B2C Small" and customers:
conditions += """ and (
SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2)
or grand_total <= {0}) and is_return != 1 and customer in ({1})""".\
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 39dda92..2e5f255 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -255,27 +255,44 @@
});
return;
} else {
- var fields = [
- {fieldtype:'Table', fieldname: 'items',
- description: __('Select BOM and Qty for Production'),
- fields: [
- {fieldtype:'Read Only', fieldname:'item_code',
- label: __('Item Code'), in_list_view:1},
- {fieldtype:'Link', fieldname:'bom', options: 'BOM', reqd: 1,
- label: __('Select BOM'), in_list_view:1, get_query: function(doc) {
- return {filters: {item: doc.item_code}};
- }},
- {fieldtype:'Float', fieldname:'pending_qty', reqd: 1,
- label: __('Qty'), in_list_view:1},
- {fieldtype:'Data', fieldname:'sales_order_item', reqd: 1,
- label: __('Sales Order Item'), hidden:1}
- ],
- data: r.message,
- get_data: function() {
- return r.message
+ const fields = [{
+ label: 'Items',
+ fieldtype: 'Table',
+ fieldname: 'items',
+ description: __('Select BOM and Qty for Production'),
+ fields: [{
+ fieldtype: 'Read Only',
+ fieldname: 'item_code',
+ label: __('Item Code'),
+ in_list_view: 1
+ }, {
+ fieldtype: 'Link',
+ fieldname: 'bom',
+ options: 'BOM',
+ reqd: 1,
+ label: __('Select BOM'),
+ in_list_view: 1,
+ get_query: function (doc) {
+ return { filters: { item: doc.item_code } };
}
+ }, {
+ fieldtype: 'Float',
+ fieldname: 'pending_qty',
+ reqd: 1,
+ label: __('Qty'),
+ in_list_view: 1
+ }, {
+ fieldtype: 'Data',
+ fieldname: 'sales_order_item',
+ reqd: 1,
+ label: __('Sales Order Item'),
+ hidden: 1
+ }],
+ data: r.message,
+ get_data: () => {
+ return r.message
}
- ]
+ }]
var d = new frappe.ui.Dialog({
title: __('Select Items to Manufacture'),
fields: fields,
diff --git a/erpnext/selling/report/customer_wise_item_price/__init__.py b/erpnext/selling/report/customer_wise_item_price/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/selling/report/customer_wise_item_price/__init__.py
diff --git a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.js b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.js
new file mode 100644
index 0000000..d333c8b
--- /dev/null
+++ b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.js
@@ -0,0 +1,27 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Customer-wise Item Price"] = {
+ "filters": [
+ {
+ "label": __("Customer"),
+ "fieldname": "customer",
+ "fieldtype": "Link",
+ "options": "Customer",
+ "reqd": 1
+ },
+ {
+ "label": __("Item"),
+ "fieldname": "item",
+ "fieldtype": "Link",
+ "options": "Item",
+ "get_query": () => {
+ return {
+ query: "erpnext.controllers.queries.item_query",
+ filters: { 'is_sales_item': 1 }
+ }
+ }
+ }
+ ]
+}
diff --git a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.json b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.json
new file mode 100644
index 0000000..998ba94
--- /dev/null
+++ b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.json
@@ -0,0 +1,43 @@
+{
+ "add_total_row": 0,
+ "creation": "2019-06-12 03:25:36.263179",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "idx": 0,
+ "is_standard": "Yes",
+ "letter_head": "Delta9",
+ "modified": "2019-06-12 03:25:36.263179",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Customer-wise Item Price",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Customer",
+ "report_name": "Customer-wise Item Price",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "Sales User"
+ },
+ {
+ "role": "Stock Manager"
+ },
+ {
+ "role": "Accounts User"
+ },
+ {
+ "role": "Accounts Manager"
+ },
+ {
+ "role": "Sales Manager"
+ },
+ {
+ "role": "Sales Master Manager"
+ },
+ {
+ "role": "Stock User"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py
new file mode 100644
index 0000000..eb9273a
--- /dev/null
+++ b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py
@@ -0,0 +1,103 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+from erpnext import get_default_company
+from erpnext.accounts.party import get_party_details
+from erpnext.stock.get_item_details import get_price_list_rate_for
+from frappe import _
+
+
+def execute(filters=None):
+ if not filters:
+ filters = {}
+
+ if not filters.get("customer"):
+ frappe.throw(_("Please select a Customer"))
+
+ columns = get_columns(filters)
+ data = get_data(filters)
+
+ return columns, data
+
+
+def get_columns(filters=None):
+ return [
+ {
+ "label": _("Item Code"),
+ "fieldname": "item_code",
+ "fieldtype": "Link",
+ "options": "Item",
+ "width": 150
+ },
+ {
+ "label": _("Item Name"),
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "width": 200
+ },
+ {
+ "label": _("Selling Rate"),
+ "fieldname": "selling_rate",
+ "fieldtype": "Currency"
+ },
+ {
+ "label": _("Available Stock"),
+ "fieldname": "available_stock",
+ "fieldtype": "Float",
+ "width": 150
+ },
+ {
+ "label": _("Price List"),
+ "fieldname": "price_list",
+ "fieldtype": "Link",
+ "options": "Price List",
+ "width": 120
+ }
+ ]
+
+
+def get_data(filters=None):
+ data = []
+ customer_details = get_customer_details(filters)
+
+ items = get_selling_items(filters)
+ item_stock_map = frappe.get_all("Bin", fields=["item_code", "sum(actual_qty) AS available"], group_by="item_code")
+ item_stock_map = {item.item_code: item.available for item in item_stock_map}
+
+ for item in items:
+ price_list_rate = get_price_list_rate_for(customer_details, item.item_code) or 0.0
+ available_stock = item_stock_map.get(item.item_code)
+
+ data.append({
+ "item_code": item.item_code,
+ "item_name": item.item_name,
+ "selling_rate": price_list_rate,
+ "price_list": customer_details.get("price_list"),
+ "available_stock": available_stock,
+ })
+
+ return data
+
+
+def get_customer_details(filters):
+ customer_details = get_party_details(party=filters.get("customer"), party_type="Customer")
+ customer_details.update({
+ "company": get_default_company(),
+ "price_list": customer_details.get("selling_price_list")
+ })
+
+ return customer_details
+
+
+def get_selling_items(filters):
+ if filters.get("item"):
+ item_filters = {"item_code": filters.get("item"), "is_sales_item": 1, "disabled": 0}
+ else:
+ item_filters = {"is_sales_item": 1, "disabled": 0}
+
+ items = frappe.get_all("Item", filters=item_filters, fields=["item_code", "item_name"], order_by="item_name")
+
+ return items
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index f40560a..b530332 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -802,13 +802,13 @@
self.add_to_stock_entry_detail(item_dict)
- if self.purpose != "Send to Subcontractor":
- scrap_item_dict = self.get_bom_scrap_material(self.fg_completed_qty)
- for item in itervalues(scrap_item_dict):
- if self.pro_doc and self.pro_doc.scrap_warehouse:
- item["to_warehouse"] = self.pro_doc.scrap_warehouse
+ if self.purpose != "Send to Subcontractor" and self.purpose == "Manufacture":
+ scrap_item_dict = self.get_bom_scrap_material(self.fg_completed_qty)
+ for item in itervalues(scrap_item_dict):
+ if self.pro_doc and self.pro_doc.scrap_warehouse:
+ item["to_warehouse"] = self.pro_doc.scrap_warehouse
- self.add_to_stock_entry_detail(scrap_item_dict, bom_no=self.bom_no)
+ self.add_to_stock_entry_detail(scrap_item_dict, bom_no=self.bom_no)
# fetch the serial_no of the first stock entry for the second stock entry
if self.work_order and self.purpose == "Manufacture":
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index d9e62c7..98a8c59 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -327,7 +327,8 @@
if sl_entries:
sl_entries.reverse()
- self.make_sl_entries(sl_entries)
+ allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
+ self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock)
# repost future entries for selected item_code, warehouse
for entries in existing_entries:
diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
index f0c71cf..ededc4d 100644
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
@@ -17,10 +17,11 @@
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
class TestStockReconciliation(unittest.TestCase):
- def setUp(self):
+ @classmethod
+ def setUpClass(self):
create_batch_or_serial_no_items()
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
- self.insert_existing_sle()
+ insert_existing_sle()
def test_reco_for_fifo(self):
self._test_reco_sle_gle("FIFO")
@@ -97,18 +98,6 @@
self.assertEqual(["_Test Stock Reco Item", "_Test Warehouse Ledger 1 - _TC", 100],
[items[0]["item_code"], items[0]["warehouse"], items[0]["qty"]])
- def insert_existing_sle(self):
- from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
-
- make_stock_entry(posting_date="2012-12-15", posting_time="02:00", item_code="_Test Item",
- target="_Test Warehouse - _TC", qty=10, basic_rate=700)
-
- make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item",
- source="_Test Warehouse - _TC", qty=15)
-
- make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item",
- target="_Test Warehouse - _TC", qty=15, basic_rate=1200)
-
def test_stock_reco_for_serialized_item(self):
set_perpetual_inventory()
@@ -218,6 +207,18 @@
for d in to_delete_records:
frappe.delete_doc("Stock Reconciliation", d)
+def insert_existing_sle():
+ from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
+
+ make_stock_entry(posting_date="2012-12-15", posting_time="02:00", item_code="_Test Item",
+ target="_Test Warehouse - _TC", qty=10, basic_rate=700)
+
+ make_stock_entry(posting_date="2012-12-25", posting_time="03:00", item_code="_Test Item",
+ source="_Test Warehouse - _TC", qty=15)
+
+ make_stock_entry(posting_date="2013-01-05", posting_time="07:00", item_code="_Test Item",
+ target="_Test Warehouse - _TC", qty=15, basic_rate=1200)
+
def create_batch_or_serial_no_items():
create_warehouse("_Test Warehouse for Stock Reco1",
{"is_group": 0, "parent_warehouse": "_Test Warehouse Group - _TC"})
diff --git a/erpnext/stock/doctype/stock_settings/test_stock_settings.py b/erpnext/stock/doctype/stock_settings/test_stock_settings.py
index 1e83ec2..42a78f7 100644
--- a/erpnext/stock/doctype/stock_settings/test_stock_settings.py
+++ b/erpnext/stock/doctype/stock_settings/test_stock_settings.py
@@ -8,16 +8,7 @@
class TestStockSettings(unittest.TestCase):
def setUp(self):
- settings = frappe.get_single('Stock Settings')
- settings.clean_description_html = 0
- settings.save()
-
- frappe.delete_doc('Item', 'Item for description test')
-
- def tearDown(self):
- settings = frappe.get_single('Stock Settings')
- settings.clean_description_html = 1
- settings.save()
+ frappe.db.set_value("Stock Settings", None, "clean_description_html", 0)
def test_settings(self):
item = frappe.get_doc(dict(
diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.js b/erpnext/stock/report/stock_ageing/stock_ageing.js
index aad8df4..ccde61a 100644
--- a/erpnext/stock/report/stock_ageing/stock_ageing.js
+++ b/erpnext/stock/report/stock_ageing/stock_ageing.js
@@ -37,8 +37,8 @@
"options": "Brand"
},
{
- "fieldname":"show_ageing_warehouse_wise",
- "label": __("Show Ageing Warehouse-wise"),
+ "fieldname":"show_warehouse_wise_stock",
+ "label": __("Show Warehouse-wise Stock"),
"fieldtype": "Check",
"default": 0
}
diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py
index 9692845..83a1d7b 100644
--- a/erpnext/stock/report/stock_ageing/stock_ageing.py
+++ b/erpnext/stock/report/stock_ageing/stock_ageing.py
@@ -6,6 +6,7 @@
from frappe import _
from frappe.utils import date_diff, flt
from six import iteritems
+from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
def execute(filters=None):
@@ -14,9 +15,9 @@
to_date = filters["to_date"]
data = []
for item, item_dict in iteritems(item_details):
- fifo_queue = item_dict["fifo_queue"]
+ fifo_queue = sorted(item_dict["fifo_queue"], key=lambda x: x[1])
details = item_dict["details"]
- if not fifo_queue: continue
+ if not fifo_queue or (not item_dict.get("total_qty")): continue
average_age = get_average_age(fifo_queue, to_date)
earliest_age = date_diff(to_date, fifo_queue[0][1])
@@ -25,7 +26,7 @@
row = [details.name, details.item_name,
details.description, details.item_group, details.brand]
- if filters.get("show_ageing_warehouse_wise"):
+ if filters.get("show_warehouse_wise_stock"):
row.append(details.warehouse)
row.extend([item_dict.get("total_qty"), average_age,
@@ -39,48 +40,150 @@
batch_age = age_qty = total_qty = 0.0
for batch in fifo_queue:
batch_age = date_diff(to_date, batch[1])
- age_qty += batch_age * batch[0]
- total_qty += batch[0]
+
+ if type(batch[0]) in ['int', 'float']:
+ age_qty += batch_age * batch[0]
+ total_qty += batch[0]
+ else:
+ age_qty += batch_age * 1
+ total_qty += 1
return (age_qty / total_qty) if total_qty else 0.0
def get_columns(filters):
- columns = [_("Item Code") + ":Link/Item:100", _("Item Name") + "::100", _("Description") + "::200",
- _("Item Group") + ":Link/Item Group:100", _("Brand") + ":Link/Brand:100"]
+ columns = [
+ {
+ "label": _("Item Code"),
+ "fieldname": "item_code",
+ "fieldtype": "Link",
+ "options": "Item",
+ "width": 100
+ },
+ {
+ "label": _("Item Name"),
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "width": 100
+ },
+ {
+ "label": _("Description"),
+ "fieldname": "description",
+ "fieldtype": "Data",
+ "width": 200
+ },
+ {
+ "label": _("Item Group"),
+ "fieldname": "item_group",
+ "fieldtype": "Link",
+ "options": "Item Group",
+ "width": 100
+ },
+ {
+ "label": _("Brand"),
+ "fieldname": "brand",
+ "fieldtype": "Link",
+ "options": "Brand",
+ "width": 100
+ }]
- if filters.get("show_ageing_warehouse_wise"):
- columns.extend([_("Warehouse") + ":Link/Warehouse:100"])
+ if filters.get("show_warehouse_wise_stock"):
+ columns +=[{
+ "label": _("Warehouse"),
+ "fieldname": "warehouse",
+ "fieldtype": "Link",
+ "options": "Warehouse",
+ "width": 100
+ }]
- columns.extend([_("Available Qty") + ":Float:100", _("Average Age") + ":Float:100",
- _("Earliest") + ":Int:80", _("Latest") + ":Int:80", _("UOM") + ":Link/UOM:100"])
+ columns.extend([
+ {
+ "label": _("Available Qty"),
+ "fieldname": "qty",
+ "fieldtype": "Float",
+ "width": 100
+ },
+ {
+ "label": _("Average Age"),
+ "fieldname": "average_age",
+ "fieldtype": "Float",
+ "width": 100
+ },
+ {
+ "label": _("Earliest"),
+ "fieldname": "earliest",
+ "fieldtype": "Int",
+ "width": 80
+ },
+ {
+ "label": _("Latest"),
+ "fieldname": "latest",
+ "fieldtype": "Int",
+ "width": 80
+ },
+ {
+ "label": _("UOM"),
+ "fieldname": "uom",
+ "fieldtype": "Link",
+ "options": "UOM",
+ "width": 100
+ }
+ ])
return columns
def get_fifo_queue(filters):
item_details = {}
- for d in get_stock_ledger_entries(filters):
- key = (d.name, d.warehouse) if filters.get('show_ageing_warehouse_wise') else d.name
+ transfered_item_details = {}
+ serial_no_batch_purchase_details = {}
+
+ sle = get_stock_ledger_entries(filters)
+
+ for d in sle:
+ key = (d.name, d.warehouse) if filters.get('show_warehouse_wise_stock') else d.name
item_details.setdefault(key, {"details": d, "fifo_queue": []})
fifo_queue = item_details[key]["fifo_queue"]
+ transfered_item_details.setdefault((d.voucher_no, d.name), [])
+
if d.voucher_type == "Stock Reconciliation":
d.actual_qty = flt(d.qty_after_transaction) - flt(item_details[key].get("qty_after_transaction", 0))
+ serial_no_list = get_serial_nos(d.serial_no) if d.serial_no else []
+
if d.actual_qty > 0:
- fifo_queue.append([d.actual_qty, d.posting_date])
- else:
- qty_to_pop = abs(d.actual_qty)
- while qty_to_pop:
- batch = fifo_queue[0] if fifo_queue else [0, None]
- if 0 < batch[0] <= qty_to_pop:
- # if batch qty > 0
- # not enough or exactly same qty in current batch, clear batch
- qty_to_pop -= batch[0]
- fifo_queue.pop(0)
+ if transfered_item_details.get((d.voucher_no, d.name)):
+ batch = transfered_item_details[(d.voucher_no, d.name)][0]
+ fifo_queue.append(batch)
+ transfered_item_details[((d.voucher_no, d.name))].pop(0)
+ else:
+ if serial_no_list:
+ for serial_no in serial_no_list:
+ if serial_no_batch_purchase_details.get(serial_no):
+ fifo_queue.append([serial_no, serial_no_batch_purchase_details.get(serial_no)])
+ else:
+ serial_no_batch_purchase_details.setdefault(serial_no, d.posting_date)
+ fifo_queue.append([serial_no, d.posting_date])
else:
- # all from current batch
- batch[0] -= qty_to_pop
- qty_to_pop = 0
+ fifo_queue.append([d.actual_qty, d.posting_date])
+ else:
+ if serial_no_list:
+ for serial_no in fifo_queue:
+ if serial_no[0] in serial_no_list:
+ fifo_queue.remove(serial_no)
+ else:
+ qty_to_pop = abs(d.actual_qty)
+ while qty_to_pop:
+ batch = fifo_queue[0] if fifo_queue else [0, None]
+ if 0 < batch[0] <= qty_to_pop:
+ # if batch qty > 0
+ # not enough or exactly same qty in current batch, clear batch
+ qty_to_pop -= batch[0]
+ transfered_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0))
+ else:
+ # all from current batch
+ batch[0] -= qty_to_pop
+ transfered_item_details[(d.voucher_no, d.name)].append([qty_to_pop, batch[1]])
+ qty_to_pop = 0
item_details[key]["qty_after_transaction"] = d.qty_after_transaction
@@ -94,7 +197,7 @@
def get_stock_ledger_entries(filters):
return frappe.db.sql("""select
item.name, item.item_name, item_group, brand, description, item.stock_uom,
- actual_qty, posting_date, voucher_type, qty_after_transaction, warehouse
+ actual_qty, posting_date, voucher_type, voucher_no, serial_no, batch_no, qty_after_transaction, warehouse
from `tabStock Ledger Entry` sle,
(select name, item_name, description, stock_uom, brand, item_group
from `tabItem` {item_conditions}) item
@@ -102,7 +205,7 @@
company = %(company)s and
posting_date <= %(to_date)s
{sle_conditions}
- order by posting_date, posting_time, sle.creation"""\
+ order by posting_date, posting_time, sle.creation, actual_qty""" #nosec
.format(item_conditions=get_item_conditions(filters),
sle_conditions=get_sle_conditions(filters)), filters, as_dict=True)
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index ff5b026..5fda2a4 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -363,8 +363,17 @@
self.stock_queue.append([0, sle.incoming_rate or sle.outgoing_rate or self.valuation_rate])
def check_if_allow_zero_valuation_rate(self, voucher_type, voucher_detail_no):
- ref_item_dt = voucher_type + (" Detail" if voucher_type == "Stock Entry" else " Item")
- return frappe.db.get_value(ref_item_dt, voucher_detail_no, "allow_zero_valuation_rate")
+ ref_item_dt = ""
+
+ if voucher_type == "Stock Entry":
+ ref_item_dt = voucher_type + " Detail"
+ elif voucher_type in ["Purchase Invoice", "Sales Invoice", "Delivery Note", "Purchase Receipt"]:
+ ref_item_dt = voucher_type + " Item"
+
+ if ref_item_dt:
+ return frappe.db.get_value(ref_item_dt, voucher_detail_no, "allow_zero_valuation_rate")
+ else:
+ return 0
def get_sle_before_datetime(self):
"""get previous stock ledger entry before current time-bucket"""
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index 98d8c99..58e2076 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -210,6 +210,7 @@
self.service_level_agreement_creation = now_datetime()
self.set_response_and_resolution_time(priority=self.priority, service_level_agreement=self.service_level_agreement)
+ self.agreement_fulfilled = "Ongoing"
self.save()
def get_expected_time_for(parameter, service_level, start_date_time):
diff --git a/erpnext/tests/test_notifications.py b/erpnext/tests/test_notifications.py
index 596bc80..1fd90be 100644
--- a/erpnext/tests/test_notifications.py
+++ b/erpnext/tests/test_notifications.py
@@ -2,45 +2,31 @@
# MIT License. See license.txt
from __future__ import unicode_literals
+import frappe
import unittest
from frappe.desk import notifications
from frappe.test_runner import make_test_objects
class TestNotifications(unittest.TestCase):
- def setUp(self):
- test_records_company = [
- {
- "abbr": "_TC6",
- "company_name": "_Test Company 6",
- "country": "India",
- "default_currency": "INR",
- "doctype": "Company",
- "domain": "Manufacturing",
- "monthly_sales_target": 2000,
- "chart_of_accounts": "Standard"
- },
- {
- "abbr": "_TC7",
- "company_name": "_Test Company 7",
- "country": "United States",
- "default_currency": "USD",
- "doctype": "Company",
- "domain": "Retail",
- "monthly_sales_target": 10000,
- "total_monthly_sales": 1000,
- "chart_of_accounts": "Standard"
- },
- ]
-
- make_test_objects('Company', test_records=test_records_company, reset=True)
-
def test_get_notifications_for_targets(self):
'''
Test notification config entries for targets as percentages
'''
+ company = frappe.get_all("Company")[0]
+ frappe.db.set_value("Company", company.name, "monthly_sales_target", 10000)
+ frappe.db.set_value("Company", company.name, "total_monthly_sales", 1000)
+
config = notifications.get_notification_config()
doc_target_percents = notifications.get_notifications_for_targets(config, {})
- self.assertEqual(doc_target_percents['Company']['_Test Company 7'], 10)
- self.assertEqual(doc_target_percents['Company']['_Test Company 6'], 0)
+
+ self.assertEqual(doc_target_percents['Company'][company.name], 10)
+
+ frappe.db.set_value("Company", company.name, "monthly_sales_target", 2000)
+ frappe.db.set_value("Company", company.name, "total_monthly_sales", 0)
+
+ config = notifications.get_notification_config()
+ doc_target_percents = notifications.get_notifications_for_targets(config, {})
+
+ self.assertEqual(doc_target_percents['Company'][company.name], 0)
diff --git a/test_sites/apps.txt b/test_sites/apps.txt
deleted file mode 100644
index ee64549..0000000
--- a/test_sites/apps.txt
+++ /dev/null
@@ -1 +0,0 @@
-erpnext
\ No newline at end of file
diff --git a/travis/bench_init.sh b/travis/bench_init.sh
deleted file mode 100755
index f96269b..0000000
--- a/travis/bench_init.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-cd ~/
-curl -I https://github.com/frappe/frappe/tree/$TRAVIS_BRANCH | head -n 1 | cut -d $' ' -f2 | (
- read response;
- [ $response == '200' ] && branch=$TRAVIS_BRANCH || branch='develop';
- bench init frappe-bench --frappe-path https://github.com/frappe/frappe.git --frappe-branch $branch --python $(which python)
-)
diff --git a/travis/run-tests.sh b/travis/run-tests.sh
deleted file mode 100755
index 7cfd648..0000000
--- a/travis/run-tests.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-set -e
-
-if [[ $TEST_TYPE == 'Server Side Test' ]]; then
- bench run-tests --app erpnext --coverage
-
-elif [[ $TEST_TYPE == 'Patch Test' ]]; then
- wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz
- bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis
- bench migrate
-fi